diff --git a/build.gradle b/build.gradle index 3cd5886a465..91baa7ff33d 100644 --- a/build.gradle +++ b/build.gradle @@ -189,7 +189,8 @@ def setupTasks(SourceSet sourceSet) { tasks.named(sourceSet.processResourcesTaskName, ProcessResources).configure { ProcessResources process -> process.setGroup('process resources') process.duplicatesStrategy(DuplicatesStrategy.FAIL) - var versionProperties = ['version': mod_version, 'mc_version': minecraft_version_range, 'forge_version': forge_version_range, 'loader_version': loader_version_range] + var versionProperties = ['version': mod_version, 'mc_version': minecraft_version_range, 'forge_version': forge_version_range, 'loader_version': loader_version_range, + 'jei_version': jei_version_range] //Mark the properties as inputs so that when they change things update process.inputs.properties(versionProperties) process.filesMatching('META-INF/neoforge.mods.toml') { expand(versionProperties) } diff --git a/gradle.properties b/gradle.properties index 5a5fc882cb6..a7b0198765e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -44,7 +44,7 @@ emi_version=1.1.12 grand_power_version=3.0.0 jade_api_id=5427895 jade_id=5639932 -jei_version=19.8.5.118 +jei_version=19.9.0.120 json_things_version=0.12.1 top_version=1.21_neo-12.0.3-5 wildfire_gender_mod_id=5579007 @@ -52,7 +52,7 @@ wthit_version=12.3.0 framedblocks_mod_id=5629510 #Mod dependency min version ranges - +jei_version_range=[19.9.0.120,) #Mod dependency min version ranges until next MC version. For deps that we need a min version of but otherwise don't have to force ourselves loading after diff --git a/src/api/java/mekanism/api/chemical/attribute/ChemicalAttribute.java b/src/api/java/mekanism/api/chemical/attribute/ChemicalAttribute.java index c92a886baa6..e284621cca7 100644 --- a/src/api/java/mekanism/api/chemical/attribute/ChemicalAttribute.java +++ b/src/api/java/mekanism/api/chemical/attribute/ChemicalAttribute.java @@ -1,6 +1,8 @@ package mekanism.api.chemical.attribute; +import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; import net.minecraft.network.chat.Component; /** @@ -25,8 +27,27 @@ public boolean needsValidation() { * @param list list of tooltips to be displayed * * @return updated list of tooltips + * + * @deprecated since 10.7.4. Use {@link #collectTooltips(Consumer)} instead. */ + @Deprecated(since = "10.7.4", forRemoval = true) public List addTooltipText(List list) { return list; } + + /** + * Add text components to this chemical attribute's tooltip. + * + * @param adder Method reference to add tooltips to be displayed. + * + * @since 10.7.4 + */ + public void collectTooltips(Consumer adder) { + //TODO - 1.22: When removing this legacy handling, make overriders call super + List list = new ArrayList<>(); + addTooltipText(list); + for (Component component : list) { + adder.accept(component); + } + } } diff --git a/src/api/java/mekanism/api/chemical/attribute/ChemicalAttributes.java b/src/api/java/mekanism/api/chemical/attribute/ChemicalAttributes.java index 3d527072a0b..155a4ad4d83 100644 --- a/src/api/java/mekanism/api/chemical/attribute/ChemicalAttributes.java +++ b/src/api/java/mekanism/api/chemical/attribute/ChemicalAttributes.java @@ -1,6 +1,7 @@ package mekanism.api.chemical.attribute; import java.util.List; +import java.util.function.Consumer; import java.util.function.IntSupplier; import java.util.function.LongSupplier; import mekanism.api.MekanismAPI; @@ -58,14 +59,19 @@ public boolean needsValidation() { } @Override + @Deprecated(since = "10.7.4", forRemoval = true) public List addTooltipText(List list) { - super.addTooltipText(list); + collectTooltips(list::add); + return list; + } + + @Override + public void collectTooltips(Consumer adder) { if (needsValidation()) { //Only show the radioactive tooltip information if radiation is actually enabled ITooltipHelper tooltipHelper = ITooltipHelper.INSTANCE; - list.add(APILang.CHEMICAL_ATTRIBUTE_RADIATION.translateColored(EnumColor.GRAY, EnumColor.INDIGO, tooltipHelper.getRadioactivityDisplayShort(getRadioactivity()))); + adder.accept(APILang.CHEMICAL_ATTRIBUTE_RADIATION.translateColored(EnumColor.GRAY, EnumColor.INDIGO, tooltipHelper.getRadioactivityDisplayShort(getRadioactivity()))); } - return list; } } @@ -114,13 +120,18 @@ public double getConductivity() { } @Override + @Deprecated(since = "10.7.4", forRemoval = true) public List addTooltipText(List list) { - super.addTooltipText(list); + collectTooltips(list::add); + return list; + } + + @Override + public void collectTooltips(Consumer adder) { ITooltipHelper tooltipHelper = ITooltipHelper.INSTANCE; - list.add(APILang.CHEMICAL_ATTRIBUTE_COOLANT_EFFICIENCY.translateColored(EnumColor.GRAY, EnumColor.INDIGO, tooltipHelper.getPercent(conductivity))); - list.add(APILang.CHEMICAL_ATTRIBUTE_COOLANT_ENTHALPY.translateColored(EnumColor.GRAY, EnumColor.INDIGO, + adder.accept(APILang.CHEMICAL_ATTRIBUTE_COOLANT_EFFICIENCY.translateColored(EnumColor.GRAY, EnumColor.INDIGO, tooltipHelper.getPercent(conductivity))); + adder.accept(APILang.CHEMICAL_ATTRIBUTE_COOLANT_ENTHALPY.translateColored(EnumColor.GRAY, EnumColor.INDIGO, tooltipHelper.getEnergyPerMBDisplayShort(MathUtils.clampToLong(thermalEnthalpy)))); - return list; } } @@ -245,13 +256,18 @@ public long getEnergyPerTick() { } @Override + @Deprecated(since = "10.7.4", forRemoval = true) public List addTooltipText(List list) { - super.addTooltipText(list); + collectTooltips(list::add); + return list; + } + + @Override + public void collectTooltips(Consumer adder) { ITooltipHelper tooltipHelper = ITooltipHelper.INSTANCE; - list.add(APILang.CHEMICAL_ATTRIBUTE_FUEL_BURN_TICKS.translateColored(EnumColor.GRAY, EnumColor.INDIGO, tooltipHelper.getFormattedNumber(getBurnTicks()))); - list.add(APILang.CHEMICAL_ATTRIBUTE_FUEL_ENERGY_DENSITY.translateColored(EnumColor.GRAY, EnumColor.INDIGO, + adder.accept(APILang.CHEMICAL_ATTRIBUTE_FUEL_BURN_TICKS.translateColored(EnumColor.GRAY, EnumColor.INDIGO, tooltipHelper.getFormattedNumber(getBurnTicks()))); + adder.accept(APILang.CHEMICAL_ATTRIBUTE_FUEL_ENERGY_DENSITY.translateColored(EnumColor.GRAY, EnumColor.INDIGO, tooltipHelper.getEnergyPerMBDisplayShort(energyDensity.getAsLong()))); - return list; } } } diff --git a/src/main/java/mekanism/client/recipe_viewer/jei/BaseRecipeCategory.java b/src/main/java/mekanism/client/recipe_viewer/jei/BaseRecipeCategory.java index fb692b28dae..009668fe460 100644 --- a/src/main/java/mekanism/client/recipe_viewer/jei/BaseRecipeCategory.java +++ b/src/main/java/mekanism/client/recipe_viewer/jei/BaseRecipeCategory.java @@ -1,6 +1,5 @@ package mekanism.client.recipe_viewer.jei; -import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.vertex.PoseStack; import java.util.ArrayList; import java.util.EnumMap; @@ -29,9 +28,11 @@ import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.ingredient.IRecipeSlotView; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder; import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.neoforge.NeoForgeTypes; +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; @@ -49,6 +50,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +//TODO: Re-evaluate this extending AbstractContainerEventHandler public abstract class BaseRecipeCategory extends AbstractContainerEventHandler implements IRecipeCategory, IGuiWrapper { protected static IDrawable createIcon(IGuiHelper helper, IRecipeViewerRecipeType recipeType) { @@ -108,13 +110,12 @@ public ScreenRectangle getRectangle() { } @Override - public boolean handleInput(RECIPE recipe, double mouseX, double mouseY, InputConstants.Key input) { - return switch (input.getType()) { - case KEYSYM -> keyPressed(input.getValue(), -1, 0); - case SCANCODE -> keyPressed(-1, input.getValue(), 0); - //Shift by the offset as JEI doesn't realize we are actually starting at negatives - case MOUSE -> mouseClicked(mouseX, mouseY, input.getValue()); - }; + public void createRecipeExtras(IRecipeExtrasBuilder builder, RECIPE recipe, IFocusGroup focuses) { + for (GuiElement guiElement : guiElements) { + //TODO: I believe we can use this method and adding via builder.addWidget to reduce some of our draw override hacks + //TODO: Only add this for ones that we actually have interaction behavior for? + builder.addGuiEventListener(new MekJeiWidget(guiElement)); + } } /** diff --git a/src/main/java/mekanism/client/recipe_viewer/jei/ChemicalStackHelper.java b/src/main/java/mekanism/client/recipe_viewer/jei/ChemicalStackHelper.java index dba74c6478c..9b7a79fed6a 100644 --- a/src/main/java/mekanism/client/recipe_viewer/jei/ChemicalStackHelper.java +++ b/src/main/java/mekanism/client/recipe_viewer/jei/ChemicalStackHelper.java @@ -2,10 +2,10 @@ import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; +import com.mojang.datafixers.util.Pair; import java.util.Collection; +import java.util.List; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import java.util.stream.Stream; import mekanism.api.MekanismAPI; import mekanism.api.chemical.Chemical; @@ -40,10 +40,17 @@ public String getDisplayName(ChemicalStack ingredient) { } @Override + @Deprecated(forRemoval = true) public String getUniqueId(ChemicalStack ingredient, UidContext context) { return "chemical:" + ingredient.getTypeRegistryName(); } + @Override + public Object getUid(ChemicalStack ingredient, UidContext context) { + //Note: We just return the registry element itself as we have no component data + return ingredient.getChemical(); + } + @Override public ResourceLocation getResourceLocation(ChemicalStack ingredient) { return ingredient.getTypeRegistryName(); @@ -89,13 +96,14 @@ public Stream getTagStream(ChemicalStack ingredient) { } @Override - public Optional getTagEquivalent(Collection stacks) { + public Optional> getTagKeyEquivalent(Collection stacks) { if (stacks.size() < 2) { return Optional.empty(); } - Set values = stacks.stream() + List values = stacks.stream() .map(ChemicalStack::getChemical) - .collect(Collectors.toSet()); + .distinct() + .toList(); int expected = values.size(); if (expected != stacks.size()) { //One of the chemicals is there more than once, definitely not a tag @@ -104,8 +112,16 @@ public Optional getTagEquivalent(Collection sta return MekanismAPI.CHEMICAL_REGISTRY.getTags() .filter(pair -> { Named tag = pair.getSecond(); - return tag.size() == expected && tag.stream().allMatch(holder -> values.contains(holder.value())); - }).map(pair -> pair.getFirst().location()) + if (tag.size() != expected) { + return false; + } + for (int i = 0; i < expected; i++) { + if (tag.get(i).value() != values.get(i)) { + return false; + } + } + return true; + }).>map(Pair::getFirst) .findFirst(); } diff --git a/src/main/java/mekanism/client/recipe_viewer/jei/ChemicalStackRenderer.java b/src/main/java/mekanism/client/recipe_viewer/jei/ChemicalStackRenderer.java index 0e182f8c266..171db0d661d 100644 --- a/src/main/java/mekanism/client/recipe_viewer/jei/ChemicalStackRenderer.java +++ b/src/main/java/mekanism/client/recipe_viewer/jei/ChemicalStackRenderer.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.Consumer; import mekanism.api.chemical.Chemical; import mekanism.api.chemical.ChemicalStack; import mekanism.api.math.MathUtils; @@ -16,6 +17,7 @@ import mekanism.common.registries.MekanismChemicals; import mekanism.common.util.ChemicalUtil; import mekanism.common.util.text.TextUtils; +import mezz.jei.api.gui.builder.ITooltipBuilder; import mezz.jei.api.ingredients.IIngredientRenderer; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; @@ -71,26 +73,40 @@ public void render(@NotNull GuiGraphics guiGraphics, ChemicalStack stack) { } @Override + @Deprecated(forRemoval = true) public List getTooltip(ChemicalStack stack, TooltipFlag tooltipFlag) { Chemical chemical = stack.getChemical(); if (chemical.isEmptyType()) { return Collections.emptyList(); } List tooltips = new ArrayList<>(); - tooltips.add(TextComponentUtil.build(chemical)); - if (stack.getChemical() == MekanismChemicals.ETHENE.get()) { - //TODO - 1.22: Remove this - tooltips.add(MekanismLang.ALSO_KNOWN_AS.translateColored(EnumColor.GRAY, EnumColor.INDIGO, MekanismLang.ETHENE_ETHYLENE_ALIAS)); - } - if (tooltipMode == TooltipMode.SHOW_AMOUNT_AND_CAPACITY) { - tooltips.add(MekanismLang.JEI_AMOUNT_WITH_CAPACITY.translateColored(EnumColor.GRAY, TextUtils.format(stack.getAmount()), TextUtils.format(capacityMb))); - } else if (tooltipMode == TooltipMode.SHOW_AMOUNT) { - tooltips.add(MekanismLang.GENERIC_MB.translateColored(EnumColor.GRAY, TextUtils.format(stack.getAmount()))); - } - ChemicalUtil.addChemicalDataToTooltip(tooltips, stack.getChemical(), tooltipFlag.isAdvanced()); + collectTooltips(stack, tooltipFlag, tooltips::add); return tooltips; } + @Override + public void getTooltip(ITooltipBuilder tooltip, ChemicalStack stack, TooltipFlag tooltipFlag) { + //TODO - 1.22: Flatten the collectTooltips into this method + collectTooltips(stack, tooltipFlag, tooltip::add); + } + + private void collectTooltips(ChemicalStack stack, TooltipFlag tooltipFlag, Consumer tooltipAdder) { + Chemical chemical = stack.getChemical(); + if (!chemical.isEmptyType()) { + tooltipAdder.accept(TextComponentUtil.build(chemical)); + if (stack.getChemical() == MekanismChemicals.ETHENE.get()) { + //TODO - 1.22: Remove this + tooltipAdder.accept(MekanismLang.ALSO_KNOWN_AS.translateColored(EnumColor.GRAY, EnumColor.INDIGO, MekanismLang.ETHENE_ETHYLENE_ALIAS)); + } + if (tooltipMode == TooltipMode.SHOW_AMOUNT_AND_CAPACITY) { + tooltipAdder.accept(MekanismLang.JEI_AMOUNT_WITH_CAPACITY.translateColored(EnumColor.GRAY, TextUtils.format(stack.getAmount()), TextUtils.format(capacityMb))); + } else if (tooltipMode == TooltipMode.SHOW_AMOUNT) { + tooltipAdder.accept(MekanismLang.GENERIC_MB.translateColored(EnumColor.GRAY, TextUtils.format(stack.getAmount()))); + } + ChemicalUtil.addChemicalDataToTooltip(stack.getChemical(), tooltipFlag.isAdvanced(), tooltipAdder); + } + } + @Override public Font getFontRenderer(Minecraft minecraft, ChemicalStack stack) { return minecraft.font; diff --git a/src/main/java/mekanism/client/recipe_viewer/jei/JeiQIOCraftingTransferHandler.java b/src/main/java/mekanism/client/recipe_viewer/jei/JeiQIOCraftingTransferHandler.java index a74d11afdfa..6f75fb92900 100644 --- a/src/main/java/mekanism/client/recipe_viewer/jei/JeiQIOCraftingTransferHandler.java +++ b/src/main/java/mekanism/client/recipe_viewer/jei/JeiQIOCraftingTransferHandler.java @@ -67,7 +67,7 @@ public IRecipeTransferError transferRecipe(CONTAINER container, RecipeHolder recipeHolder, IRecipeSlotsView recipeSlots, Player player, int transferAmount, IRecipeTransferHandlerHelper handlerHelper, IStackHelper stackHelper - ) implements RVRecipeInfo { + ) implements RVRecipeInfo { @Override public IRecipeTransferError createInternalError() { @@ -85,8 +85,8 @@ public IRecipeTransferError createMissingSlotsError(List missing) } @Override - public String itemUUID(HashedItem hashed) { - return stackHelper.getUniqueIdentifierForStack(hashed.getInternalStack(), UidContext.Recipe); + public Object itemUUID(HashedItem hashed) { + return stackHelper.getUidForStack(hashed.getInternalStack(), UidContext.Recipe); } @Override diff --git a/src/main/java/mekanism/client/recipe_viewer/jei/MekJeiWidget.java b/src/main/java/mekanism/client/recipe_viewer/jei/MekJeiWidget.java new file mode 100644 index 00000000000..45c33d7e628 --- /dev/null +++ b/src/main/java/mekanism/client/recipe_viewer/jei/MekJeiWidget.java @@ -0,0 +1,66 @@ +package mekanism.client.recipe_viewer.jei; + +import mekanism.client.gui.element.GuiElement; +import mezz.jei.api.gui.inputs.IJeiGuiEventListener; +import net.minecraft.client.gui.navigation.ScreenRectangle; + +public class MekJeiWidget implements IJeiGuiEventListener { + + private final ScreenRectangle area; + private final GuiElement element; + + public MekJeiWidget(GuiElement element) { + this.element = element; + this.area = element.getRectangle(); + } + + @Override + public final ScreenRectangle getArea() { + return area; + } + + @Override + public void mouseMoved(double mouseX, double mouseY) { + //Shift the mouse positions to being global instead of relative + mouseX += element.getX(); + mouseY += element.getY(); + element.mouseMoved(mouseX, mouseY); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + //Shift the mouse positions to being global instead of relative + mouseX += element.getX(); + mouseY += element.getY(); + return element.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + //Shift the mouse positions to being global instead of relative + mouseX += element.getX(); + mouseY += element.getY(); + return element.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) { + //Shift the mouse positions to being global instead of relative + mouseX += element.getX(); + mouseY += element.getY(); + return element.mouseDragged(mouseX, mouseY, button, dragX, dragY); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) { + //Shift the mouse positions to being global instead of relative + mouseX += element.getX(); + mouseY += element.getY(); + return element.mouseScrolled(mouseX, mouseY, scrollX, scrollY); + } + + @Override + public boolean keyPressed(double mouseX, double mouseY, int keyCode, int scanCode, int modifiers) { + return element.keyPressed(keyCode, scanCode, modifiers); + } +} \ No newline at end of file diff --git a/src/main/java/mekanism/client/recipe_viewer/jei/MekanismJEI.java b/src/main/java/mekanism/client/recipe_viewer/jei/MekanismJEI.java index de369e519f0..ca2cdfb0698 100644 --- a/src/main/java/mekanism/client/recipe_viewer/jei/MekanismJEI.java +++ b/src/main/java/mekanism/client/recipe_viewer/jei/MekanismJEI.java @@ -6,9 +6,8 @@ import java.util.List; import java.util.Map; import mekanism.api.MekanismAPI; +import mekanism.api.chemical.Chemical; import mekanism.api.chemical.ChemicalStack; -import mekanism.api.chemical.IChemicalHandler; -import mekanism.api.energy.IStrictEnergyHandler; import mekanism.client.gui.GuiMekanism; import mekanism.client.gui.robit.GuiRobitRepair; import mekanism.client.recipe_viewer.RecipeViewerUtils; @@ -41,7 +40,6 @@ import mekanism.client.recipe_viewer.type.RecipeViewerRecipeType; import mekanism.common.Mekanism; import mekanism.common.MekanismLang; -import mekanism.common.attachments.containers.ContainerType; import mekanism.common.capabilities.Capabilities; import mekanism.common.config.MekanismConfig; import mekanism.common.inventory.container.entity.robit.CraftingRobitContainer; @@ -52,7 +50,6 @@ import mekanism.common.registries.MekanismContainerTypes; import mekanism.common.registries.MekanismFluids; import mekanism.common.registries.MekanismItems; -import mekanism.common.util.RegistryUtils; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; import mezz.jei.api.constants.RecipeTypes; @@ -60,8 +57,7 @@ import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.helpers.IStackHelper; import mezz.jei.api.ingredients.IIngredientType; -import mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter; -import mezz.jei.api.ingredients.subtypes.UidContext; +import mezz.jei.api.ingredients.subtypes.ISubtypeInterpreter; import mezz.jei.api.neoforge.NeoForgeTypes; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.transfer.IRecipeTransferHandlerHelper; @@ -78,9 +74,7 @@ import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.level.ItemLike; -import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; -import net.neoforged.neoforge.fluids.capability.IFluidHandler; import org.jetbrains.annotations.NotNull; @JeiPlugin @@ -89,7 +83,7 @@ public class MekanismJEI implements IModPlugin { public static final IIngredientType TYPE_CHEMICAL = () -> ChemicalStack.class; public static final ChemicalStackHelper CHEMICAL_STACK_HELPER = new ChemicalStackHelper(); - + private static final ISubtypeInterpreter MEKANISM_DATA_INTERPRETER = new MekanismSubtypeInterpreter(); private static final Map, RecipeType> recipeTypeInstanceCache = new HashMap<>(); public static boolean shouldLoad() { @@ -126,81 +120,6 @@ public static RecipeType[] recipeType(IRecipeViewerRecipeType... recipeTyp return Arrays.stream(recipeTypes).map(MekanismJEI::genericRecipeType).toArray(RecipeType[]::new); } - private static final IIngredientSubtypeInterpreter MEKANISM_NBT_INTERPRETER = (stack, context) -> { - if (context == UidContext.Ingredient) { - String representation = getChemicalComponent(stack); - representation = addInterpretation(representation, getFluidComponent(stack)); - representation = addInterpretation(representation, getEnergyComponent(stack)); - return representation; - } - return IIngredientSubtypeInterpreter.NONE; - }; - - private static String addInterpretation(String nbtRepresentation, String component) { - return nbtRepresentation.isEmpty() ? component : nbtRepresentation + ":" + component; - } - - private static String getChemicalComponent(ItemStack stack) { - IChemicalHandler handler = ContainerType.CHEMICAL.createHandlerIfData(stack); - if (handler == null) { - handler = Capabilities.CHEMICAL.getCapability(stack); - } - if (handler != null) { - String component = ""; - for (int tank = 0, tanks = handler.getChemicalTanks(); tank < tanks; tank++) { - ChemicalStack chemicalStack = handler.getChemicalInTank(tank); - if (!chemicalStack.isEmpty()) { - component = addInterpretation(component, chemicalStack.getTypeRegistryName().toString()); - } else if (tanks > 1) { - component = addInterpretation(component, "empty"); - } - } - return component; - } - return IIngredientSubtypeInterpreter.NONE; - } - - private static String getFluidComponent(ItemStack stack) { - IFluidHandler handler = ContainerType.FLUID.createHandlerIfData(stack); - if (handler == null) { - handler = Capabilities.FLUID.getCapability(stack); - } - if (handler != null) { - String component = ""; - for (int tank = 0, tanks = handler.getTanks(); tank < tanks; tank++) { - FluidStack fluidStack = handler.getFluidInTank(tank); - if (!fluidStack.isEmpty()) { - component = addInterpretation(component, RegistryUtils.getName(fluidStack.getFluid()).toString()); - } else if (tanks > 1) { - component = addInterpretation(component, "empty"); - } - } - return component; - } - return IIngredientSubtypeInterpreter.NONE; - } - - private static String getEnergyComponent(ItemStack stack) { - IStrictEnergyHandler energyHandlerItem = ContainerType.ENERGY.createHandlerIfData(stack); - if (energyHandlerItem == null) { - energyHandlerItem = Capabilities.STRICT_ENERGY.getCapability(stack); - } - if (energyHandlerItem != null) { - String component = ""; - int containers = energyHandlerItem.getEnergyContainerCount(); - for (int container = 0; container < containers; container++) { - long neededEnergy = energyHandlerItem.getNeededEnergy(container); - if (neededEnergy == 0L) { - component = addInterpretation(component, "filled"); - } else if (containers > 1) { - component = addInterpretation(component, "empty"); - } - } - return component; - } - return IIngredientSubtypeInterpreter.NONE; - } - @NotNull @Override public ResourceLocation getPluginUid() { @@ -214,7 +133,7 @@ public static void registerItemSubtypes(ISubtypeRegistration registry, Collectio //Handle items ItemStack stack = new ItemStack(itemProvider.value()); if (Capabilities.STRICT_ENERGY.hasCapability(stack) || Capabilities.CHEMICAL.hasCapability(stack) || Capabilities.FLUID.hasCapability(stack)) { - registry.registerSubtypeInterpreter(stack.getItem(), MEKANISM_NBT_INTERPRETER); + registry.registerSubtypeInterpreter(stack.getItem(), MEKANISM_DATA_INTERPRETER); } } } @@ -235,7 +154,10 @@ public void registerIngredients(IModIngredientRegistration registry) { .map(chemical -> chemical.getStack(FluidType.BUCKET_VOLUME)) .toList(); CHEMICAL_STACK_HELPER.setColorHelper(registry.getColorHelper()); - registry.register(TYPE_CHEMICAL, types, CHEMICAL_STACK_HELPER, new ChemicalStackRenderer()); + registry.register(TYPE_CHEMICAL, types, CHEMICAL_STACK_HELPER, new ChemicalStackRenderer(), Chemical.CODEC.xmap( + chemical -> chemical.getStack(FluidType.BUCKET_VOLUME), + ChemicalStack::getChemical + )); } @Override diff --git a/src/main/java/mekanism/client/recipe_viewer/jei/MekanismSubtypeInterpreter.java b/src/main/java/mekanism/client/recipe_viewer/jei/MekanismSubtypeInterpreter.java new file mode 100644 index 00000000000..bf9d4f080c1 --- /dev/null +++ b/src/main/java/mekanism/client/recipe_viewer/jei/MekanismSubtypeInterpreter.java @@ -0,0 +1,174 @@ +package mekanism.client.recipe_viewer.jei; + +import java.util.ArrayList; +import java.util.List; +import mekanism.api.chemical.ChemicalStack; +import mekanism.api.chemical.IChemicalHandler; +import mekanism.api.energy.IStrictEnergyHandler; +import mekanism.common.attachments.containers.ContainerType; +import mekanism.common.capabilities.Capabilities; +import mekanism.common.util.RegistryUtils; +import mezz.jei.api.ingredients.subtypes.ISubtypeInterpreter; +import mezz.jei.api.ingredients.subtypes.UidContext; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import org.jetbrains.annotations.Nullable; + +public class MekanismSubtypeInterpreter implements ISubtypeInterpreter { + + private List tryAddData(@Nullable List subTypeData, Object data) { + if (subTypeData == null) { + subTypeData = new ArrayList<>(); + } + subTypeData.add(data); + return subTypeData; + } + + @Nullable + @Override + public Object getSubtypeData(ItemStack stack, UidContext context) { + if (context != UidContext.Ingredient) { + return null; + } + List subTypeData = null; + + IChemicalHandler chemicalHandler = getChemicalHandler(stack); + if (chemicalHandler != null) { + for (int tank = 0, tanks = chemicalHandler.getChemicalTanks(); tank < tanks; tank++) { + ChemicalStack chemicalStack = chemicalHandler.getChemicalInTank(tank); + //Store the type of the chemical. We skip empty chemicals if there is only a single tank + if (!chemicalStack.isEmpty() || tanks > 1) { + subTypeData = tryAddData(subTypeData, chemicalStack.getChemical()); + } + } + } + + IFluidHandler fluidHandler = getFluidHandler(stack); + if (fluidHandler != null) { + for (int tank = 0, tanks = fluidHandler.getTanks(); tank < tanks; tank++) { + FluidStack fluidStack = fluidHandler.getFluidInTank(tank); + //Store the type of the fluid. We skip empty fluids if there is only a single tank + if (!fluidStack.isEmpty() || tanks > 1) { + //TODO: Should this be using the fluidstack's subtype interpretation? (So that it takes fluid components into account? + subTypeData = tryAddData(subTypeData, fluidStack.getFluid()); + } + } + } + + IStrictEnergyHandler energyHandler = getEnergyHandler(stack); + if (energyHandler != null) { + for (int container = 0, containers = energyHandler.getEnergyContainerCount(); container < containers; container++) { + //TODO: Should we just be storing the amount of stored energy?? + long neededEnergy = energyHandler.getNeededEnergy(container); + if (neededEnergy == 0L) { + //Energy container is full + subTypeData = tryAddData(subTypeData, true); + } else if (containers > 1) { + //Energy container is not full + subTypeData = tryAddData(subTypeData, false); + } + } + } + return subTypeData; + } + + @Override + @Deprecated + public String getLegacyStringSubtypeInfo(ItemStack stack, UidContext context) { + if (context == UidContext.Ingredient) { + String representation = getChemicalComponent(stack); + representation = addInterpretation(representation, getFluidComponent(stack)); + representation = addInterpretation(representation, getEnergyComponent(stack)); + return representation; + } + return ""; + } + + @Deprecated + private static String addInterpretation(String nbtRepresentation, String component) { + return nbtRepresentation.isEmpty() ? component : nbtRepresentation + ":" + component; + } + + @Deprecated + private static String getChemicalComponent(ItemStack stack) { + IChemicalHandler chemicalHandler = getChemicalHandler(stack); + if (chemicalHandler != null) { + String component = ""; + for (int tank = 0, tanks = chemicalHandler.getChemicalTanks(); tank < tanks; tank++) { + ChemicalStack chemicalStack = chemicalHandler.getChemicalInTank(tank); + if (!chemicalStack.isEmpty()) { + component = addInterpretation(component, chemicalStack.getTypeRegistryName().toString()); + } else if (tanks > 1) { + component = addInterpretation(component, "empty"); + } + } + return component; + } + return ""; + } + + @Deprecated + private static String getFluidComponent(ItemStack stack) { + IFluidHandler handler = getFluidHandler(stack); + if (handler != null) { + String component = ""; + for (int tank = 0, tanks = handler.getTanks(); tank < tanks; tank++) { + FluidStack fluidStack = handler.getFluidInTank(tank); + if (!fluidStack.isEmpty()) { + component = addInterpretation(component, RegistryUtils.getName(fluidStack.getFluid()).toString()); + } else if (tanks > 1) { + component = addInterpretation(component, "empty"); + } + } + return component; + } + return ""; + } + + @Deprecated + private static String getEnergyComponent(ItemStack stack) { + IStrictEnergyHandler energyHandlerItem = getEnergyHandler(stack); + if (energyHandlerItem != null) { + String component = ""; + int containers = energyHandlerItem.getEnergyContainerCount(); + for (int container = 0; container < containers; container++) { + long neededEnergy = energyHandlerItem.getNeededEnergy(container); + if (neededEnergy == 0L) { + component = addInterpretation(component, "filled"); + } else if (containers > 1) { + component = addInterpretation(component, "empty"); + } + } + return component; + } + return ""; + } + + @Nullable + private static IChemicalHandler getChemicalHandler(ItemStack stack) { + IChemicalHandler handler = ContainerType.CHEMICAL.createHandlerIfData(stack); + if (handler == null) { + return Capabilities.CHEMICAL.getCapability(stack); + } + return handler; + } + + @Nullable + private static IFluidHandler getFluidHandler(ItemStack stack) { + IFluidHandler handler = ContainerType.FLUID.createHandlerIfData(stack); + if (handler == null) { + return Capabilities.FLUID.getCapability(stack); + } + return handler; + } + + @Nullable + private static IStrictEnergyHandler getEnergyHandler(ItemStack stack) { + IStrictEnergyHandler handler = ContainerType.ENERGY.createHandlerIfData(stack); + if (handler == null) { + return Capabilities.STRICT_ENERGY.getCapability(stack); + } + return handler; + } +} \ No newline at end of file diff --git a/src/main/java/mekanism/client/recipe_viewer/jei/machine/ItemStackToEnergyRecipeCategory.java b/src/main/java/mekanism/client/recipe_viewer/jei/machine/ItemStackToEnergyRecipeCategory.java index 5c7cc30bc4c..250d17ca603 100644 --- a/src/main/java/mekanism/client/recipe_viewer/jei/machine/ItemStackToEnergyRecipeCategory.java +++ b/src/main/java/mekanism/client/recipe_viewer/jei/machine/ItemStackToEnergyRecipeCategory.java @@ -1,7 +1,5 @@ package mekanism.client.recipe_viewer.jei.machine; -import java.util.Collections; -import java.util.List; import mekanism.api.recipes.ItemStackToEnergyRecipe; import mekanism.api.text.TextComponentUtil; import mekanism.client.gui.element.gauge.GaugeType; @@ -16,6 +14,7 @@ import mekanism.common.util.text.EnergyDisplay; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +import mezz.jei.api.gui.builder.ITooltipBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.recipe.IFocusGroup; @@ -24,7 +23,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeHolder; import org.jetbrains.annotations.NotNull; @@ -59,19 +57,17 @@ protected void renderElements(RecipeHolder recipeHolder } @Override - public List getTooltipStrings(RecipeHolder recipeHolder, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) { + public void getTooltip(ITooltipBuilder tooltip, RecipeHolder recipeHolder, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) { if (gauge.isMouseOver(mouseX, mouseY)) { long energy = getOutputEnergy(recipeHolder, recipeSlotsView); if (energy != 0L) { //Manually add the tooltip showing the amounts if the mouse is over the energy gauge - Component energyOutput = EnergyDisplay.of(energy).getTextComponent(); + tooltip.add(EnergyDisplay.of(energy).getTextComponent()); if (Minecraft.getInstance().options.advancedItemTooltips || Screen.hasShiftDown()) { - return List.of(energyOutput, TextComponentUtil.build(ChatFormatting.DARK_GRAY, MekanismLang.JEI_RECIPE_ID.translate(recipeHolder.id()))); + tooltip.add(TextComponentUtil.build(ChatFormatting.DARK_GRAY, MekanismLang.JEI_RECIPE_ID.translate(recipeHolder.id()))); } - return Collections.singletonList(energyOutput); } } - return Collections.emptyList(); } private long getOutputEnergy(RecipeHolder recipeHolder, IRecipeSlotsView recipeSlotsView) { diff --git a/src/main/java/mekanism/client/recipe_viewer/jei/machine/NucleosynthesizingRecipeCategory.java b/src/main/java/mekanism/client/recipe_viewer/jei/machine/NucleosynthesizingRecipeCategory.java index b326cc154ed..e2782149770 100644 --- a/src/main/java/mekanism/client/recipe_viewer/jei/machine/NucleosynthesizingRecipeCategory.java +++ b/src/main/java/mekanism/client/recipe_viewer/jei/machine/NucleosynthesizingRecipeCategory.java @@ -1,6 +1,5 @@ package mekanism.client.recipe_viewer.jei.machine; -import java.util.Collections; import java.util.List; import mekanism.api.chemical.ChemicalStack; import mekanism.api.recipes.NucleosynthesizingRecipe; @@ -23,11 +22,11 @@ import mekanism.common.tile.component.config.DataType; import mekanism.common.tile.machine.TileEntityAntiprotonicNucleosynthesizer; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +import mezz.jei.api.gui.builder.ITooltipBuilder; 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 net.minecraft.network.chat.Component; import net.minecraft.world.item.crafting.RecipeHolder; import org.jetbrains.annotations.NotNull; @@ -64,11 +63,10 @@ public long getMaxEnergy() { } @Override - public List getTooltipStrings(RecipeHolder recipeHolder, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) { + public void getTooltip(ITooltipBuilder tooltip, RecipeHolder recipeHolder, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) { if (rateBar.isMouseOver(mouseX, mouseY)) { - return Collections.singletonList(MekanismLang.TICKS_REQUIRED.translate(recipeHolder.value().getDuration())); + tooltip.add(MekanismLang.TICKS_REQUIRED.translate(recipeHolder.value().getDuration())); } - return Collections.emptyList(); } @Override diff --git a/src/main/java/mekanism/common/util/ChemicalUtil.java b/src/main/java/mekanism/common/util/ChemicalUtil.java index 8f41ac5ef18..989741e68e3 100644 --- a/src/main/java/mekanism/common/util/ChemicalUtil.java +++ b/src/main/java/mekanism/common/util/ChemicalUtil.java @@ -2,6 +2,7 @@ import java.util.Collection; import java.util.List; +import java.util.function.Consumer; import java.util.function.Predicate; import mekanism.api.Action; import mekanism.api.AutomationType; @@ -110,21 +111,27 @@ public static boolean hasChemical(ItemStack stack, Predicate vali return false; } - public static void addAttributeTooltips(List tooltips, Chemical chemical) { + public static void addAttributeTooltips(Chemical chemical, Consumer tooltipAdder) { for (ChemicalAttribute attr : chemical.getAttributes()) { - attr.addTooltipText(tooltips); + attr.collectTooltips(tooltipAdder); } } public static void addChemicalDataToTooltip(List tooltips, Chemical chemical, boolean advanced) { if (!chemical.isEmptyType()) { - addAttributeTooltips(tooltips, chemical); + addChemicalDataToTooltip(chemical, advanced, tooltips::add); + } + } + + public static void addChemicalDataToTooltip(Chemical chemical, boolean advanced, Consumer tooltipAdder) { + if (!chemical.isEmptyType()) { + addAttributeTooltips(chemical, tooltipAdder); if (chemical.is(MekanismAPITags.Chemicals.WASTE_BARREL_DECAY_BLACKLIST)) { - tooltips.add(MekanismLang.DECAY_IMMUNE.translateColored(EnumColor.AQUA)); + tooltipAdder.accept(MekanismLang.DECAY_IMMUNE.translateColored(EnumColor.AQUA)); } if (advanced) { //If advanced tooltips are on, display the registry name - tooltips.add(TextComponentUtil.build(ChatFormatting.DARK_GRAY, chemical.getRegistryName())); + tooltipAdder.accept(TextComponentUtil.build(ChatFormatting.DARK_GRAY, chemical.getRegistryName())); } } } diff --git a/src/main/java/mekanism/common/util/StorageUtils.java b/src/main/java/mekanism/common/util/StorageUtils.java index f911248cf4a..0e16770cec7 100644 --- a/src/main/java/mekanism/common/util/StorageUtils.java +++ b/src/main/java/mekanism/common/util/StorageUtils.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Optional; import java.util.function.BiFunction; +import java.util.function.Consumer; import mekanism.api.Action; import mekanism.api.chemical.Chemical; import mekanism.api.chemical.ChemicalStack; @@ -66,16 +67,20 @@ public static void addStoredChemical(@NotNull ItemStack stack, @NotNull List 0) { + Consumer tooltipAdder = tooltip::add; + for (int tank = 0; tank < tanks; tank++) { + ChemicalStack chemicalInTank = handler.getChemicalInTank(tank); + if (chemicalInTank.isEmpty()) { + tooltip.add(MekanismLang.NO_CHEMICAL.translateColored(EnumColor.GRAY)); + } else { + tooltip.add(MekanismLang.STORED.translateColored(EnumColor.ORANGE, EnumColor.ORANGE, chemicalInTank, EnumColor.GRAY, + MekanismLang.GENERIC_MB.translate(TextUtils.format(chemicalInTank.getAmount())))); + } + if (showAttributes) { + ChemicalUtil.addAttributeTooltips(chemicalInTank.getChemical(), tooltipAdder); + } } } } else if (showMissingCap) { diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml index c35dcb63ec4..958f26a510b 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -23,6 +23,12 @@ license="MIT" type="required" versionRange="${forge_version}" side="BOTH" +[[dependencies.mekanism]] + modId="jei" + type="optional" + versionRange="${jei_version}" + ordering="NONE" + side="BOTH" [[dependencies.mekanism]] modId="appmek"