diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index 4a42d3925e..5ece959791 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -2159,6 +2159,7 @@ "entity.gtceu.industrial_tnt": "⟘N⟘ ןɐıɹʇsnpuI", "entity.gtceu.powderbarrel": "ןǝɹɹɐqɹǝpʍoԀ", "fluid.empty": "ʎʇdɯƎ", + "fluid.gtceu.potion": "uoıʇoԀ", "fluid.spawnlocation.name": "uoıʇɐɯɹoɟuI uıǝΛ pınןℲ", "fluid.tile.lava": "ɐʌɐꞀ", "fluid.tile.water": "ɹǝʇɐM", @@ -3448,6 +3449,7 @@ "gtceu.recipe_memory_widget.tooltip.0": "pıɹb buıʇɟɐɹɔ ǝɥʇ oʇuı ǝdıɔǝɹ sıɥʇ ʇnduı ʎןןɐɔıʇɐɯoʇnɐ oʇ ʞɔıןɔ ʇɟǝꞀㄥ§", "gtceu.recipe_memory_widget.tooltip.1": "ǝdıɔǝɹ sıɥʇ ʞɔoןun/ʞɔoן oʇ ʞɔıןɔ ʇɟıɥSㄥ§", "gtceu.recipe_type.show_recipes": "sǝdıɔǝᴚ ʍoɥS", + "gtceu.rei.group.potion_fluids": "spınןℲ uoıʇoԀ", "gtceu.research_station": "uoıʇɐʇS ɥɔɹɐǝsǝᴚ", "gtceu.rock_breaker": "ɹǝʞɐǝɹᗺ ʞɔoᴚ", "gtceu.scanner": "ɹǝuuɐɔS", diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index 366f45806b..1e0e1e2341 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -2159,6 +2159,7 @@ "entity.gtceu.industrial_tnt": "Industrial TNT", "entity.gtceu.powderbarrel": "Powderbarrel", "fluid.empty": "Empty", + "fluid.gtceu.potion": "Potion", "fluid.spawnlocation.name": "Fluid Vein Information", "fluid.tile.lava": "Lava", "fluid.tile.water": "Water", @@ -3448,6 +3449,7 @@ "gtceu.recipe_memory_widget.tooltip.0": "§7Left click to automatically input this recipe into the crafting grid", "gtceu.recipe_memory_widget.tooltip.1": "§7Shift click to lock/unlock this recipe", "gtceu.recipe_type.show_recipes": "Show Recipes", + "gtceu.rei.group.potion_fluids": "Potion Fluids", "gtceu.research_station": "Research Station", "gtceu.rock_breaker": "Rock Breaker", "gtceu.scanner": "Scanner", diff --git a/src/generated/resources/data/forge/tags/fluids/potion.json b/src/generated/resources/data/forge/tags/fluids/potion.json new file mode 100644 index 0000000000..a99661c023 --- /dev/null +++ b/src/generated/resources/data/forge/tags/fluids/potion.json @@ -0,0 +1,6 @@ +{ + "values": [ + "gtceu:flowing_potion", + "gtceu:potion" + ] +} \ No newline at end of file diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java index af4421acd2..8d94706f29 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/FluidRecipeCapability.java @@ -14,8 +14,11 @@ import com.gregtechceu.gtceu.api.recipe.modifier.ParallelLogic; import com.gregtechceu.gtceu.api.recipe.ui.GTRecipeTypeUI; import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable; -import com.gregtechceu.gtceu.api.transfer.fluid.TagOrCycleFluidHandler; import com.gregtechceu.gtceu.client.TooltipsHandler; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidEntryList; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidStackList; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidTagList; +import com.gregtechceu.gtceu.integration.xei.handlers.fluid.CycleFluidEntryHandler; import com.gregtechceu.gtceu.integration.xei.widgets.GTRecipeWidget; import com.gregtechceu.gtceu.utils.FluidKey; import com.gregtechceu.gtceu.utils.GTHashMaps; @@ -28,13 +31,10 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; -import net.minecraft.tags.TagKey; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.material.Fluid; import net.minecraftforge.fluids.FluidStack; -import com.mojang.datafixers.util.Either; -import com.mojang.datafixers.util.Pair; import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -304,8 +304,7 @@ public int getMaxParallelRatio(IRecipeCapabilityHolder holder, GTRecipe recipe, public Object createXEIContainer(List contents) { // cast is safe if you don't pass the wrong thing. // noinspection unchecked - return new TagOrCycleFluidHandler( - (List, Integer>>, List>>) contents); + return new CycleFluidEntryHandler((List) contents); } @NotNull @@ -334,14 +333,15 @@ public void applyWidgetInfo(@NotNull Widget widget, @Nullable Content content, @Nullable Object storage, int recipeTier, int chanceTier) { if (widget instanceof TankWidget tank) { - if (storage instanceof TagOrCycleFluidHandler fluidHandler) { - tank.setFluidTank(fluidHandler, index); + if (storage instanceof CycleFluidEntryHandler cycleHandler) { + tank.setFluidTank(cycleHandler, index); } else if (storage instanceof IFluidHandlerModifiable fluidHandler) { tank.setFluidTank(new OverlayingFluidStorage(fluidHandler, index)); } tank.setIngredientIO(io == IO.IN ? IngredientIO.INPUT : IngredientIO.OUTPUT); tank.setAllowClickFilled(!isXEI); tank.setAllowClickDrained(!isXEI && io.support(IO.IN)); + if (isXEI) tank.setShowAmount(false); if (content != null) { float chance = (float) recipeType.getChanceFunction() .getBoostedChance(content, recipeTier, chanceTier) / content.maxChance; @@ -350,10 +350,7 @@ public void applyWidgetInfo(@NotNull Widget widget, FluidIngredient ingredient = FluidRecipeCapability.CAP.of(content.content); if (!isXEI && ingredient.getStacks().length > 0) { FluidStack stack = ingredient.getStacks()[0]; - TooltipsHandler.appendFluidTooltips(stack.getFluid(), - stack.getAmount(), - tooltips::add, - TooltipFlag.NORMAL); + TooltipsHandler.appendFluidTooltips(stack, tooltips::add, TooltipFlag.NORMAL); } GTRecipeWidget.setConsumedChance(content, @@ -370,24 +367,24 @@ public void applyWidgetInfo(@NotNull Widget widget, } } - // Maps fluids to Either<(tag with count), FluidStack>s - public static Either, Integer>>, List> mapFluid(FluidIngredient ingredient) { + // Maps fluids to a FluidEntryList for XEI: either a FluidTagList or a FluidStackList + public static FluidEntryList mapFluid(FluidIngredient ingredient) { int amount = ingredient.getAmount(); CompoundTag tag = ingredient.getNbt(); - List, Integer>> tags = new ArrayList<>(); - List fluids = new ArrayList<>(); + FluidTagList tags = new FluidTagList(); + FluidStackList fluids = new FluidStackList(); for (FluidIngredient.Value value : ingredient.values) { if (value instanceof FluidIngredient.TagValue tagValue) { - tags.add(Pair.of(tagValue.getTag(), amount)); + tags.add(tagValue.getTag(), amount, ingredient.getNbt()); } else { fluids.addAll(value.getFluids().stream().map(fluid -> new FluidStack(fluid, amount, tag)).toList()); } } if (!tags.isEmpty()) { - return Either.left(tags); + return tags; } else { - return Either.right(fluids); + return fluids; } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java index f8ac38a7a9..cc91703be7 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/ItemRecipeCapability.java @@ -17,8 +17,6 @@ import com.gregtechceu.gtceu.api.recipe.lookup.*; import com.gregtechceu.gtceu.api.recipe.modifier.ParallelLogic; import com.gregtechceu.gtceu.api.recipe.ui.GTRecipeTypeUI; -import com.gregtechceu.gtceu.api.transfer.item.CycleItemStackHandler; -import com.gregtechceu.gtceu.api.transfer.item.TagOrCycleItemStackHandler; import com.gregtechceu.gtceu.common.recipe.condition.ResearchCondition; import com.gregtechceu.gtceu.common.valueprovider.AddedFloat; import com.gregtechceu.gtceu.common.valueprovider.CastedFloat; @@ -28,6 +26,11 @@ import com.gregtechceu.gtceu.core.mixins.IngredientAccessor; import com.gregtechceu.gtceu.core.mixins.IntersectionIngredientAccessor; import com.gregtechceu.gtceu.core.mixins.TagValueAccessor; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemEntryList; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemStackList; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemTagList; +import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemEntryHandler; +import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemStackHandler; import com.gregtechceu.gtceu.integration.xei.widgets.GTRecipeWidget; import com.gregtechceu.gtceu.utils.*; @@ -35,12 +38,9 @@ import com.lowdragmc.lowdraglib.jei.IngredientIO; import net.minecraft.ChatFormatting; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; -import net.minecraft.tags.TagKey; import net.minecraft.util.valueproviders.ConstantFloat; import net.minecraft.util.valueproviders.IntProvider; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraftforge.common.crafting.IntersectionIngredient; @@ -49,18 +49,14 @@ import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.wrapper.CombinedInvWrapper; -import com.mojang.datafixers.util.Either; import com.mojang.datafixers.util.Pair; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; import java.util.*; -import java.util.function.Function; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; /** @@ -415,12 +411,13 @@ private Object2IntMap getIngredientStacks(IRecipeCapabilityHolder hol @Override public @NotNull List createXEIContainerContents(List contents, GTRecipe recipe, IO io) { - var outputStacks = contents.stream().map(content -> content.content) + var entryLists = contents.stream() + .map(Content::getContent) .map(this::of) .map(ItemRecipeCapability::mapItem) .collect(Collectors.toList()); - List, Integer>>, List>> scannerPossibilities = null; + List scannerPossibilities = null; if (io == IO.OUT && recipe.recipeType.isScanner()) { scannerPossibilities = new ArrayList<>(); // Scanner Output replacing, used for cycling research outputs @@ -432,48 +429,33 @@ private Object2IntMap getIngredientStacks(IRecipeCapabilityHolder hol if (researchData != null) { Collection possibleRecipes = researchData.getFirst() .getDataStickEntry(researchData.getSecond()); + Set cache = new ObjectOpenCustomHashSet<>(ItemStackHashStrategy.comparingItem()); if (possibleRecipes != null) { for (GTRecipe r : possibleRecipes) { - ItemStack researchItem = ItemRecipeCapability.CAP - .of(r.getOutputContents(ItemRecipeCapability.CAP).get(0).content).getItems()[0]; - researchItem = researchItem.copy(); - researchItem.setCount(1); - boolean didMatch = false; - for (Either, Integer>>, List> stacks : scannerPossibilities) { - for (ItemStack stack : stacks.map( - tag -> tag - .stream() - .flatMap(key -> BuiltInRegistries.ITEM.getTag(key.getFirst()).stream()) - .flatMap(holders -> holders.stream() - .map(holder -> new ItemStack(holder.get()))) - .collect(Collectors.toList()), - Function.identity())) { - if (ItemStack.isSameItem(stack, researchItem)) { - didMatch = true; - break; - } - } + Content outputContent = r.getOutputContents(ItemRecipeCapability.CAP).get(0); + ItemStack researchStack = ItemRecipeCapability.CAP.of(outputContent.content).getItems()[0]; + if (!cache.contains(researchStack)) { + cache.add(researchStack); + scannerPossibilities.add(ItemStackList.of(researchStack.copyWithCount(1))); } - if (!didMatch) scannerPossibilities.add(Either.right(List.of(researchItem))); } } - scannerPossibilities.add(outputStacks.get(0)); + scannerPossibilities.add(entryLists.get(0)); } } if (scannerPossibilities != null && !scannerPossibilities.isEmpty()) { - outputStacks = scannerPossibilities; + entryLists = scannerPossibilities; } - while (outputStacks.size() < recipe.recipeType.getMaxOutputs(ItemRecipeCapability.CAP)) outputStacks.add(null); + while (entryLists.size() < recipe.recipeType.getMaxOutputs(ItemRecipeCapability.CAP)) entryLists.add(null); - return new ArrayList<>(outputStacks); + return new ArrayList<>(entryLists); } public Object createXEIContainer(List contents) { // cast is safe if you don't pass the wrong thing. // noinspection unchecked - return new TagOrCycleItemStackHandler( - (List, Integer>>, List>>) contents); + return new CycleItemEntryHandler((List) contents); } @NotNull @@ -565,161 +547,60 @@ public void applyWidgetInfo(@NotNull Widget widget, } } - // Maps ingredients to Either <(Tag with count), ItemStack>s - @SuppressWarnings("deprecation") - private static Either, Integer>>, List> mapItem(final Ingredient ingredient) { + // Maps ingredients to an ItemEntryList for XEI: either an ItemTagList or an ItemStackList + private static ItemEntryList mapItem(final Ingredient ingredient) { if (ingredient instanceof SizedIngredient sizedIngredient) { final int amount = sizedIngredient.getAmount(); - if (sizedIngredient.getInner() instanceof IntersectionIngredient intersection) { - List children = ((IntersectionIngredientAccessor) intersection).getChildren(); - if (children.isEmpty()) { - return Either.right(null); - } - var childEither = mapItem(children.get(0)); - return Either.right(childEither.map(tags -> { - List tagItems = tags.stream() - .map(pair -> Pair.of(BuiltInRegistries.ITEM.getTag(pair.getFirst()).stream(), - pair.getSecond())) - .flatMap(pair -> pair.getFirst().flatMap( - tag -> tag.stream().map(holder -> new ItemStack(holder.value(), pair.getSecond())))) - .collect(Collectors.toList()); - ListIterator iterator = tagItems.listIterator(); - iteratorLoop: - while (iterator.hasNext()) { - var item = iterator.next(); - for (int i = 1; i < children.size(); ++i) { - if (!children.get(i).test(item)) { - iterator.remove(); - continue iteratorLoop; - } - } - iterator.set(item.copyWithCount(amount)); - } - return tagItems; - }, items -> { - items = new ArrayList<>(items); - ListIterator iterator = items.listIterator(); - iteratorLoop: - while (iterator.hasNext()) { - var item = iterator.next(); - for (int i = 1; i < children.size(); ++i) { - if (!children.get(i).test(item)) { - iterator.remove(); - continue iteratorLoop; - } - } - iterator.set(item.copyWithCount(amount)); - } - return items; - })); - } else if (((IngredientAccessor) sizedIngredient.getInner()).getValues().length > 0 && - ((IngredientAccessor) sizedIngredient.getInner()) - .getValues()[0] instanceof Ingredient.TagValue tagValue) { - return Either.left(List.of(Pair.of(((TagValueAccessor) tagValue).getTag(), amount))); - } - } else if (ingredient instanceof IntersectionIngredient intersection) { - // Map intersection ingredients to the items inside, as recipe viewers don't support them. - List children = ((IntersectionIngredientAccessor) intersection).getChildren(); - if (children.isEmpty()) { - return Either.right(null); - } - var childEither = mapItem(children.get(0)); - return Either.right(childEither.map(tags -> { - List tagItems = tags.stream() - .map(pair -> Pair.of(BuiltInRegistries.ITEM.getTag(pair.getFirst()).stream(), pair.getSecond())) - .flatMap(pair -> pair.getFirst().flatMap( - tag -> tag.stream().map(holder -> new ItemStack(holder.value(), pair.getSecond())))) - .collect(Collectors.toList()); - ListIterator iterator = tagItems.listIterator(); - while (iterator.hasNext()) { - var item = iterator.next(); - for (int i = 1; i < children.size(); ++i) { - if (!children.get(i).test(item)) { - iterator.remove(); - break; - } - } - } - return tagItems; - }, items -> { - items = new ArrayList<>(items); - ListIterator iterator = items.listIterator(); - while (iterator.hasNext()) { - var item = iterator.next(); - for (int i = 1; i < children.size(); ++i) { - if (!children.get(i).test(item)) { - iterator.remove(); - break; - } - } - } - return items; - })); + var mapped = tryMapInner(sizedIngredient.getInner(), amount); + if (mapped != null) return mapped; } else if (ingredient instanceof IntProviderIngredient intProvider) { final int amount = 1; - if (intProvider.getInner() instanceof IntersectionIngredient intersection) { - List children = ((IntersectionIngredientAccessor) intersection).getChildren(); - if (children.isEmpty()) { - return Either.right(null); - } - var childEither = mapItem(children.get(0)); - return Either.right(childEither.map(tags -> { - List tagItems = tags.stream() - .map(pair -> Pair.of(BuiltInRegistries.ITEM.getTag(pair.getFirst()).stream(), - pair.getSecond())) - .flatMap(pair -> pair.getFirst().flatMap( - tag -> tag.stream().map(holder -> new ItemStack(holder.value(), pair.getSecond())))) - .collect(Collectors.toList()); - ListIterator iterator = tagItems.listIterator(); - iteratorLoop: - while (iterator.hasNext()) { - var item = iterator.next(); - for (int i = 1; i < children.size(); ++i) { - if (!children.get(i).test(item)) { - iterator.remove(); - continue iteratorLoop; - } - } - iterator.set(item.copyWithCount(amount)); - } - return tagItems; - }, items -> { - items = new ArrayList<>(items); - ListIterator iterator = items.listIterator(); - iteratorLoop: - while (iterator.hasNext()) { - var item = iterator.next(); - for (int i = 1; i < children.size(); ++i) { - if (!children.get(i).test(item)) { - iterator.remove(); - continue iteratorLoop; - } - } - iterator.set(item.copyWithCount(amount)); - } - return items; - })); - } else if (((IngredientAccessor) intProvider.getInner()).getValues().length > 0 && - ((IngredientAccessor) intProvider.getInner()) - .getValues()[0] instanceof Ingredient.TagValue tagValue) { - return Either.left(List.of(Pair.of(((TagValueAccessor) tagValue).getTag(), amount))); - } + var mapped = tryMapInner(intProvider.getInner(), amount); + if (mapped != null) return mapped; + } else if (ingredient instanceof IntersectionIngredient intersection) { + return mapIntersection(intersection, -1); + } else { + var tagList = tryMapTag(ingredient, 1); + if (tagList != null) return tagList; + } + ItemStackList stackList = new ItemStackList(); + boolean isIntProvider = ingredient instanceof IntProviderIngredient || + (ingredient instanceof SizedIngredient sized && sized.getInner() instanceof IntProviderIngredient); + + UnaryOperator setCount = stack -> isIntProvider ? stack.copyWithCount(1) : stack; + Arrays.stream(ingredient.getItems()) + .map(setCount) + .forEach(stackList::add); + return stackList; + } - } else if (((IngredientAccessor) ingredient).getValues().length > 0 && - ((IngredientAccessor) ingredient).getValues()[0] instanceof Ingredient.TagValue tagValue) { - return Either.left(List.of(Pair.of(((TagValueAccessor) tagValue).getTag(), 1))); - } - return Either.right(Arrays.stream(ingredient.getItems()).map(stack -> { - //@formatter:off - if (ingredient instanceof IntProviderIngredient) { - stack.setCount(1); - } else if (ingredient instanceof SizedIngredient sized && - sized.getInner() instanceof IntProviderIngredient) { - stack.setCount(1); + private static @Nullable ItemEntryList tryMapInner(final Ingredient inner, int amount) { + if (inner instanceof IntersectionIngredient intersection) return mapIntersection(intersection, amount); + return tryMapTag(inner, amount); + } + + // Map intersection ingredients to the items inside, as recipe viewers don't support them. + private static ItemEntryList mapIntersection(final IntersectionIngredient intersection, int amount) { + List children = ((IntersectionIngredientAccessor) intersection).getChildren(); + if (children.isEmpty()) return new ItemStackList(); + + var childList = mapItem(children.get(0)); + ItemStackList stackList = new ItemStackList(); + for (var stack : childList.getStacks()) { + if (children.stream().skip(1).allMatch(child -> child.test(stack))) { + if (amount > 0) stackList.add(stack.copyWithCount(amount)); + else stackList.add(stack.copy()); } - //@formatter:on - return stack; - }).toList()); + } + return stackList; + } + + private static @Nullable ItemTagList tryMapTag(final Ingredient ingredient, int amount) { + var values = ((IngredientAccessor) ingredient).getValues(); + if (values.length > 0 && values[0] instanceof Ingredient.TagValue tagValue) { + return ItemTagList.of(((TagValueAccessor) tagValue).getTag(), amount, null); + } + return null; } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/fluids/store/FluidStorageKeys.java b/src/main/java/com/gregtechceu/gtceu/api/fluids/store/FluidStorageKeys.java index ba6717dde3..72ade027fb 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/fluids/store/FluidStorageKeys.java +++ b/src/main/java/com/gregtechceu/gtceu/api/fluids/store/FluidStorageKeys.java @@ -44,7 +44,7 @@ public final class FluidStorageKeys { FluidState.PLASMA, -1); public static final FluidStorageKey MOLTEN = new FluidStorageKey(GTCEu.id("molten"), - "moltens", + "molten", MaterialIconType.molten, m -> "molten_" + m.getName(), m -> "gtceu.fluid.molten", diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PatternPreviewWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PatternPreviewWidget.java index ef1abf407a..ce329dab36 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PatternPreviewWidget.java +++ b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/PatternPreviewWidget.java @@ -10,8 +10,8 @@ import com.gregtechceu.gtceu.api.pattern.MultiblockShapeInfo; import com.gregtechceu.gtceu.api.pattern.TraceabilityPredicate; import com.gregtechceu.gtceu.api.pattern.predicates.SimplePredicate; -import com.gregtechceu.gtceu.api.transfer.item.CycleItemStackHandler; import com.gregtechceu.gtceu.config.ConfigHolder; +import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemStackHandler; import com.lowdragmc.lowdraglib.LDLib; import com.lowdragmc.lowdraglib.gui.editor.ColorPattern; diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/SlotWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/SlotWidget.java index 89bb79fecf..192e5f2c39 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/SlotWidget.java +++ b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/SlotWidget.java @@ -1,7 +1,10 @@ package com.gregtechceu.gtceu.api.gui.widget; -import com.gregtechceu.gtceu.api.transfer.item.CycleItemStackHandler; -import com.gregtechceu.gtceu.api.transfer.item.TagOrCycleItemStackHandler; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemEntryList; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemStackList; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemTagList; +import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemEntryHandler; +import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemStackHandler; import com.lowdragmc.lowdraglib.LDLib; import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; @@ -12,35 +15,35 @@ import com.lowdragmc.lowdraglib.jei.IngredientIO; import com.lowdragmc.lowdraglib.jei.JEIPlugin; import com.lowdragmc.lowdraglib.side.item.IItemTransfer; +import com.lowdragmc.lowdraglib.utils.Position; +import com.lowdragmc.lowdraglib.utils.Size; -import net.minecraft.core.HolderSet; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; -import net.minecraft.tags.TagKey; import net.minecraft.world.Container; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Blocks; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; -import com.mojang.datafixers.util.Either; -import com.mojang.datafixers.util.Pair; +import dev.emi.emi.api.stack.EmiIngredient; +import dev.emi.emi.api.stack.EmiStack; import lombok.Getter; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.EntryStacks; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Function; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import java.util.stream.Stream; @LDLRegister(name = "item_slot", group = "widget.container", priority = 50) public class SlotWidget extends com.lowdragmc.lowdraglib.gui.widget.SlotWidget { @@ -194,20 +197,19 @@ public Object getXEIIngredientOverMouse(double mouseX, double mouseY) { if (handler == null) return null; ItemStack realStack = getRealStack(handler.getItem()); if (handler instanceof WidgetSlotItemHandler slotHandler) { - if (slotHandler.itemHandler instanceof CycleItemStackHandler cycleHandler) { - return getXEIIngredientsFromCycleHandlerClickable(cycleHandler, slotHandler.index); - } else if (slotHandler.itemHandler instanceof TagOrCycleItemStackHandler tagHandler) { - return getXEIIngredientsFromTagOrCycleHandlerClickable(tagHandler, slotHandler.index); + if (slotHandler.itemHandler instanceof CycleItemStackHandler stackHandler) { + return getXEIIngredientsClickable(stackHandler, slotHandler.index); + } else if (slotHandler.itemHandler instanceof CycleItemEntryHandler entryHandler) { + return getXEIIngredientsClickable(entryHandler, slotHandler.index); } } if (LDLib.isJeiLoaded() && !realStack.isEmpty()) { - return JEIPlugin.getItemIngredient(realStack, getPositionX(), getPositionY(), getSizeWidth(), - getSizeHeight()); + return JEICallWrapper.getJEIStackClickable(realStack, getPosition(), getSize()); } else if (LDLib.isReiLoaded()) { - return REICallWrapper.getReiIngredients(realStack); + return EntryStacks.of(realStack); } else if (LDLib.isEmiLoaded()) { - return EMICallWrapper.getEmiIngredients(realStack, getXEIChance()); + return EmiStack.of(realStack).setChance(getXEIChance()); } return realStack; } @@ -221,130 +223,69 @@ public List getXEIIngredients() { if (handler == null) return Collections.emptyList(); ItemStack realStack = getRealStack(handler.getItem()); if (handler instanceof WidgetSlotItemHandler slotHandler) { - if (slotHandler.itemHandler instanceof CycleItemStackHandler cycleHandler) { - return getXEIIngredientsFromCycleHandlerClickable(cycleHandler, slotHandler.index); - } else if (slotHandler.itemHandler instanceof TagOrCycleItemStackHandler tagHandler) { - return getXEIIngredientsFromTagOrCycleHandlerClickable(tagHandler, slotHandler.index); + if (slotHandler.itemHandler instanceof CycleItemStackHandler stackHandler) { + return getXEIIngredientsClickable(stackHandler, slotHandler.index); + } else if (slotHandler.itemHandler instanceof CycleItemEntryHandler entryHandler) { + return getXEIIngredientsClickable(entryHandler, slotHandler.index); } } - if (LDLib.isJeiLoaded()) { - var ingredient = JEIPlugin.getItemIngredient(realStack, getPosition().x, getPosition().y, getSize().width, - getSize().height); - return ingredient == null ? Collections.emptyList() : List.of(ingredient); + if (LDLib.isJeiLoaded() && !realStack.isEmpty()) { + return List.of(JEICallWrapper.getJEIStackClickable(realStack, getPosition(), getSize())); } else if (LDLib.isReiLoaded()) { - return REICallWrapper.getReiIngredients(realStack); + return List.of(EntryStacks.of(realStack)); } else if (LDLib.isEmiLoaded()) { - return EMICallWrapper.getEmiIngredients(realStack, getXEIChance()); + return List.of(EmiStack.of(realStack).setChance(getXEIChance())); } return List.of(realStack); } - private List getXEIIngredientsFromCycleHandler(CycleItemStackHandler handler, int index) { - var stream = handler.getStackList(index).stream().map(this::getRealStack); + private List getXEIIngredients(CycleItemStackHandler handler, int index) { + var stackList = handler.getStackList(index); if (LDLib.isJeiLoaded()) { - return stream.filter(stack -> !stack.isEmpty()).collect(Collectors.toList()); + return JEICallWrapper.getJEIIngredients(stackList, this::getRealStack); } else if (LDLib.isReiLoaded()) { - return REICallWrapper.getReiIngredients(stream); + return REICallWrapper.getREIIngredients(stackList, this::getRealStack); } else if (LDLib.isEmiLoaded()) { - return EMICallWrapper.getEmiIngredients(stream, getXEIChance()); + return EMICallWrapper.getEMIIngredients(stackList, getXEIChance(), this::getRealStack); } return Collections.emptyList(); } - private List getXEIIngredientsFromCycleHandlerClickable(CycleItemStackHandler handler, int index) { - var stream = handler.getStackList(index).stream().map(this::getRealStack); + private List getXEIIngredientsClickable(CycleItemStackHandler handler, int index) { + var stackList = handler.getStackList(index); if (LDLib.isJeiLoaded()) { - return stream - .filter(stack -> !stack.isEmpty()) - .map(item -> JEIPlugin.getItemIngredient(item, getPositionX(), getPositionY(), getSizeWidth(), - getSizeHeight())) - .toList(); + return JEICallWrapper.getJEIIngredientsClickable(stackList, getPosition(), getSize(), this::getRealStack); } else if (LDLib.isReiLoaded()) { - return REICallWrapper.getReiIngredients(stream); + return REICallWrapper.getREIIngredients(stackList, this::getRealStack); } else if (LDLib.isEmiLoaded()) { - return EMICallWrapper.getEmiIngredients(stream, getXEIChance()); + return EMICallWrapper.getEMIIngredients(stackList, getXEIChance(), this::getRealStack); } return Collections.emptyList(); } - private List getXEIIngredientsFromTagOrCycleHandler(TagOrCycleItemStackHandler handler, int index) { - Either, Integer>>, List> either = handler - .getStacks() - .get(index); - var ref = new Object() { - - List returnValue = Collections.emptyList(); - }; - either.ifLeft(list -> { - if (LDLib.isJeiLoaded()) { - ref.returnValue = list.stream() - .flatMap(pair -> BuiltInRegistries.ITEM - .getTag(pair.getFirst()) - .stream() - .flatMap(HolderSet.ListBacked::stream) - .map(item -> getRealStack(new ItemStack(item.value(), pair.getSecond())))) - .collect(Collectors.toList()); - } else if (LDLib.isReiLoaded()) { - ref.returnValue = REICallWrapper.getReiIngredients(this::getRealStack, list); - } else if (LDLib.isEmiLoaded()) { - ref.returnValue = EMICallWrapper.getEmiIngredients(list, getXEIChance()); - } - }).ifRight(items -> { - var stream = items.stream().map(this::getRealStack); - if (LDLib.isJeiLoaded()) { - ref.returnValue = stream - .filter(stack -> !stack.isEmpty()) - .collect(Collectors.toList()); - } else if (LDLib.isReiLoaded()) { - ref.returnValue = REICallWrapper.getReiIngredients(stream); - } else if (LDLib.isEmiLoaded()) { - ref.returnValue = EMICallWrapper.getEmiIngredients(stream, getXEIChance()); - } - }); - return ref.returnValue; + private List getXEIIngredients(CycleItemEntryHandler handler, int index) { + ItemEntryList entryList = handler.getEntry(index); + if (LDLib.isJeiLoaded()) { + return JEICallWrapper.getJEIIngredients(entryList, this::getRealStack); + } else if (LDLib.isReiLoaded()) { + return REICallWrapper.getREIIngredients(entryList, this::getRealStack); + } else if (LDLib.isEmiLoaded()) { + return EMICallWrapper.getEMIIngredients(entryList, getXEIChance(), this::getRealStack); + } + return Collections.emptyList(); } - private List getXEIIngredientsFromTagOrCycleHandlerClickable(TagOrCycleItemStackHandler handler, - int index) { - Either, Integer>>, List> either = handler - .getStacks() - .get(index); - var ref = new Object() { - - List returnValue = Collections.emptyList(); - }; - either.ifLeft(list -> { - if (LDLib.isJeiLoaded()) { - ref.returnValue = list.stream() - .flatMap(pair -> BuiltInRegistries.ITEM - .getTag(pair.getFirst()) - .stream() - .flatMap(HolderSet.ListBacked::stream) - .map(item -> JEIPlugin.getItemIngredient( - getRealStack(new ItemStack(item.value(), pair.getSecond())), - getPosition().x, getPosition().y, getSize().width, getSize().height))) - .collect(Collectors.toList()); - } else if (LDLib.isReiLoaded()) { - ref.returnValue = REICallWrapper.getReiIngredients(this::getRealStack, list); - } else if (LDLib.isEmiLoaded()) { - ref.returnValue = EMICallWrapper.getEmiIngredients(list, getXEIChance()); - } - }).ifRight(items -> { - var stream = items.stream().map(this::getRealStack); - if (LDLib.isJeiLoaded()) { - ref.returnValue = stream - .filter(stack -> !stack.isEmpty()) - .map(item -> JEIPlugin.getItemIngredient(item, getPosition().x, getPosition().y, - getSize().width, getSize().height)) - .toList(); - } else if (LDLib.isReiLoaded()) { - ref.returnValue = REICallWrapper.getReiIngredients(stream); - } else if (LDLib.isEmiLoaded()) { - ref.returnValue = EMICallWrapper.getEmiIngredients(stream, getXEIChance()); - } - }); - return ref.returnValue; + private List getXEIIngredientsClickable(CycleItemEntryHandler handler, int index) { + ItemEntryList entryList = handler.getEntry(index); + if (LDLib.isJeiLoaded()) { + return JEICallWrapper.getJEIIngredientsClickable(entryList, getPosition(), getSize(), this::getRealStack); + } else if (LDLib.isReiLoaded()) { + return REICallWrapper.getREIIngredients(entryList, this::getRealStack); + } else if (LDLib.isEmiLoaded()) { + return EMICallWrapper.getEMIIngredients(entryList, getXEIChance(), this::getRealStack); + } + return Collections.emptyList(); } public class WidgetSlotItemHandler extends Slot { @@ -361,7 +302,7 @@ public WidgetSlotItemHandler(IItemHandlerModifiable itemHandler, int index, int } @Override - public boolean mayPlace(@Nonnull ItemStack stack) { + public boolean mayPlace(@NotNull ItemStack stack) { return SlotWidget.this.canPutStack(stack) && (!stack.isEmpty() && this.itemHandler.isItemValid(this.index, stack)); } @@ -372,24 +313,24 @@ public boolean mayPickup(@Nullable Player playerIn) { } @Override - @Nonnull + @NotNull public ItemStack getItem() { return this.itemHandler.getStackInSlot(index); } @Override - public void setByPlayer(ItemStack stack) { + public void setByPlayer(@NotNull ItemStack stack) { this.itemHandler.setStackInSlot(index, stack); } @Override - public void set(@Nonnull ItemStack stack) { + public void set(@NotNull ItemStack stack) { this.itemHandler.setStackInSlot(index, stack); this.setChanged(); } @Override - public void onQuickCraft(@Nonnull ItemStack oldStackIn, @Nonnull ItemStack newStackIn) {} + public void onQuickCraft(@NotNull ItemStack oldStackIn, @NotNull ItemStack newStackIn) {} @Override public int getMaxStackSize() { @@ -397,7 +338,7 @@ public int getMaxStackSize() { } @Override - public int getMaxStackSize(@Nonnull ItemStack stack) { + public int getMaxStackSize(@NotNull ItemStack stack) { ItemStack maxAdd = stack.copy(); int maxInput = stack.getMaxStackSize(); maxAdd.setCount(maxInput); @@ -431,4 +372,82 @@ public boolean isActive() { return SlotWidget.this.isEnabled() && (HOVER_SLOT == null || HOVER_SLOT == this); } } + + public static final class JEICallWrapper { + + public static Object getJEIStackClickable(ItemStack stack, Position pos, Size size) { + return JEIPlugin.getItemIngredient(stack, pos.x, pos.y, size.width, size.height); + } + + public static List getJEIIngredients(ItemEntryList list, UnaryOperator realStack) { + return list.getStacks() + .stream() + .filter(stack -> !stack.isEmpty()) + .map(realStack) + .collect(Collectors.toList()); + } + + public static List getJEIIngredientsClickable(ItemEntryList list, Position pos, Size size, + UnaryOperator realStack) { + return list.getStacks() + .stream() + .filter(stack -> !stack.isEmpty()) + .map(realStack) + .map(stack -> getJEIStackClickable(stack, pos, size)) + .collect(Collectors.toList()); + } + } + + public static final class REICallWrapper { + + private static EntryIngredient toREIIngredient(Stream stream, UnaryOperator realStack) { + return EntryIngredient.of(stream.map(realStack) + .map(EntryStacks::of) + .toList()); + } + + public static List getREIIngredients(ItemStackList list, UnaryOperator realStack) { + return List.of(toREIIngredient(list.stream(), realStack)); + } + + public static List getREIIngredients(ItemTagList list, UnaryOperator realStack) { + return list.getEntries().stream() + .map(ItemTagList.ItemTagEntry::stacks) + .map(stream -> toREIIngredient(stream, realStack)) + .collect(Collectors.toList()); + } + + public static List getREIIngredients(ItemEntryList list, UnaryOperator realStack) { + if (list instanceof ItemTagList tagList) return getREIIngredients(tagList, realStack); + if (list instanceof ItemStackList stackList) return getREIIngredients(stackList, realStack); + return Collections.emptyList(); + } + } + + public static final class EMICallWrapper { + + private static EmiIngredient toEMIIngredient(Stream stream, UnaryOperator realStack) { + return EmiIngredient.of(stream.map(realStack).map(EmiStack::of).toList()); + } + + public static List getEMIIngredients(ItemStackList list, float xeiChance, + UnaryOperator realStack) { + return List.of(toEMIIngredient(list.stream(), realStack).setChance(xeiChance)); + } + + public static List getEMIIngredients(ItemTagList list, float xeiChance, + UnaryOperator realStack) { + return list.getEntries().stream() + .map(ItemTagList.ItemTagEntry::stacks) + .map(stream -> toEMIIngredient(stream, realStack).setChance(xeiChance)) + .collect(Collectors.toList()); + } + + public static List getEMIIngredients(ItemEntryList list, float xeiChance, + UnaryOperator realStack) { + if (list instanceof ItemTagList tagList) return getEMIIngredients(tagList, xeiChance, realStack); + if (list instanceof ItemStackList stackList) return getEMIIngredients(stackList, xeiChance, realStack); + return Collections.emptyList(); + } + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/TankWidget.java b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/TankWidget.java index 24e16b268e..b896b030e7 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/gui/widget/TankWidget.java +++ b/src/main/java/com/gregtechceu/gtceu/api/gui/widget/TankWidget.java @@ -1,9 +1,11 @@ package com.gregtechceu.gtceu.api.gui.widget; -import com.gregtechceu.gtceu.api.data.chemical.ChemicalHelper; -import com.gregtechceu.gtceu.api.transfer.fluid.CycleFluidHandler; -import com.gregtechceu.gtceu.api.transfer.fluid.TagOrCycleFluidHandler; import com.gregtechceu.gtceu.client.TooltipsHandler; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidEntryList; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidStackList; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidTagList; +import com.gregtechceu.gtceu.integration.xei.handlers.fluid.CycleFluidEntryHandler; +import com.gregtechceu.gtceu.integration.xei.handlers.fluid.CycleFluidStackHandler; import com.lowdragmc.lowdraglib.LDLib; import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; @@ -28,18 +30,14 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.core.HolderSet; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; -import net.minecraft.tags.TagKey; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluids; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -51,17 +49,16 @@ import net.minecraftforge.fluids.capability.templates.FluidTank; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.datafixers.util.Either; -import com.mojang.datafixers.util.Pair; +import dev.emi.emi.api.forge.ForgeEmiStack; import dev.emi.emi.api.stack.EmiIngredient; -import dev.emi.emi.api.stack.EmiStack; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import me.shedaniel.rei.api.common.entry.EntryIngredient; -import me.shedaniel.rei.api.common.util.EntryIngredients; import me.shedaniel.rei.api.common.util.EntryStacks; import mezz.jei.api.helpers.IPlatformFluidHelper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; @@ -70,9 +67,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - @SuppressWarnings("unused") @LDLRegister(name = "fluid_slot", group = "widget.container", priority = 50) @Accessors(chain = true) @@ -202,22 +196,18 @@ public Object getXEIIngredientOverMouse(double mouseX, double mouseY) { if (self().isMouseOverElement(mouseX, mouseY)) { if (lastFluidInTank == null || lastFluidInTank.isEmpty()) return null; - if (this.fluidTank instanceof CycleFluidHandler cycleFluidHandler) { - return getXEIIngredientsFromCycleHandlerClickable(cycleFluidHandler, tank).get(0); - } else if (this.fluidTank instanceof TagOrCycleFluidHandler tagOrCycleFluidHandler) { - return getXEIIngredientsFromTagOrCycleHandlerClickable(tagOrCycleFluidHandler, tank).get(0); + if (fluidTank instanceof CycleFluidStackHandler stackHandler) { + return getXEIIngredientsClickable(stackHandler, tank).get(0); + } else if (fluidTank instanceof CycleFluidEntryHandler entryHandler) { + return getXEIIngredientsClickable(entryHandler, tank).get(0); } if (LDLib.isJeiLoaded()) { - return JEICallWrapper.getPlatformFluidTypeForJEIClickable(lastFluidInTank, getPosition(), getSize()); - } - if (LDLib.isReiLoaded()) { - return EntryStacks.of(dev.architectury.fluid.FluidStack.create(lastFluidInTank.getFluid(), - lastFluidInTank.getAmount(), lastFluidInTank.getTag())); - } - if (LDLib.isEmiLoaded()) { - return EmiStack.of(lastFluidInTank.getFluid(), lastFluidInTank.getTag(), lastFluidInTank.getAmount()) - .setChance(XEIChance); + return JEICallWrapper.getJEIFluidClickable(lastFluidInTank, getPosition(), getSize()); + } else if (LDLib.isReiLoaded()) { + return EntryStacks.of(REICallWrapper.toREIStack(lastFluidInTank)); + } else if (LDLib.isEmiLoaded()) { + return ForgeEmiStack.of(lastFluidInTank).setChance(XEIChance); } } return null; @@ -227,132 +217,68 @@ public Object getXEIIngredientOverMouse(double mouseX, double mouseY) { public List getXEIIngredients() { if (lastFluidInTank == null || lastFluidInTank.isEmpty()) return Collections.emptyList(); - if (this.fluidTank instanceof CycleFluidHandler cycleFluidHandler) { - return getXEIIngredientsFromCycleHandlerClickable(cycleFluidHandler, tank); - } else if (this.fluidTank instanceof TagOrCycleFluidHandler tagOrCycleFluidHandler) { - return getXEIIngredientsFromTagOrCycleHandlerClickable(tagOrCycleFluidHandler, tank); + if (fluidTank instanceof CycleFluidStackHandler stackHandler) { + return getXEIIngredientsClickable(stackHandler, tank); + } else if (fluidTank instanceof CycleFluidEntryHandler entryHandler) { + return getXEIIngredientsClickable(entryHandler, tank); } if (LDLib.isJeiLoaded()) { - return List - .of(JEICallWrapper.getPlatformFluidTypeForJEIClickable(lastFluidInTank, getPosition(), getSize())); - } - if (LDLib.isReiLoaded()) { - return List.of(EntryStacks.of(dev.architectury.fluid.FluidStack.create(lastFluidInTank.getFluid(), - lastFluidInTank.getAmount(), lastFluidInTank.getTag()))); - } - if (LDLib.isEmiLoaded()) { - return List - .of(EmiStack.of(lastFluidInTank.getFluid(), lastFluidInTank.getTag(), lastFluidInTank.getAmount()) - .setChance(XEIChance)); + return List.of(JEICallWrapper.getJEIFluidClickable(lastFluidInTank, getPosition(), getSize())); + } else if (LDLib.isReiLoaded()) { + return List.of(EntryStacks.of(REICallWrapper.toREIStack(lastFluidInTank))); + } else if (LDLib.isEmiLoaded()) { + return List.of(ForgeEmiStack.of(lastFluidInTank).setChance(XEIChance)); } return List.of(lastFluidInTank); } - private List getXEIIngredientsFromCycleHandler(CycleFluidHandler handler, int index) { - var stream = handler.getStackList(index).stream(); + private List getXEIIngredients(CycleFluidStackHandler handler, int index) { + FluidStackList stackList = handler.getStackList(index); if (LDLib.isJeiLoaded()) { - return stream.filter(fluid -> !fluid.isEmpty()).map(JEICallWrapper::getPlatformFluidTypeForJEI).toList(); + return JEICallWrapper.getJEIIngredients(stackList); } else if (LDLib.isReiLoaded()) { - return REICallWrapper.getReiIngredients(stream); + return REICallWrapper.getREIIngredients(stackList); } else if (LDLib.isEmiLoaded()) { - return EMICallWrapper.getEmiIngredients(stream, getXEIChance()); + return EMICallWrapper.getEMIIngredients(stackList, getXEIChance()); } return Collections.emptyList(); } - private List getXEIIngredientsFromCycleHandlerClickable(CycleFluidHandler handler, int index) { - var stream = handler.getStackList(index).stream(); + private List getXEIIngredientsClickable(CycleFluidStackHandler handler, int index) { + FluidStackList stackList = handler.getStackList(index); if (LDLib.isJeiLoaded()) { - return stream - .filter(fluid -> !fluid.isEmpty()) - .map(fluid -> JEICallWrapper.getPlatformFluidTypeForJEIClickable(fluid, getPosition(), getSize())) - .toList(); + return JEICallWrapper.getJEIIngredientsClickable(stackList, getPosition(), getSize()); } else if (LDLib.isReiLoaded()) { - return REICallWrapper.getReiIngredients(stream); + return REICallWrapper.getREIIngredients(stackList); } else if (LDLib.isEmiLoaded()) { - return EMICallWrapper.getEmiIngredients(stream, getXEIChance()); + return EMICallWrapper.getEMIIngredients(stackList, getXEIChance()); } return Collections.emptyList(); } - private List getXEIIngredientsFromTagOrCycleHandler(TagOrCycleFluidHandler handler, int index) { - Either, Integer>>, List> either = handler - .getStacks() - .get(index); - var ref = new Object() { - - List returnValue = Collections.emptyList(); - }; - either.ifLeft(list -> { - if (LDLib.isJeiLoaded()) { - ref.returnValue = list.stream() - .flatMap(pair -> BuiltInRegistries.FLUID - .getTag(pair.getFirst()) - .stream() - .flatMap(HolderSet.ListBacked::stream) - .map(fluid -> new FluidStack(fluid.value(), pair.getSecond())) - .map(JEICallWrapper::getPlatformFluidTypeForJEI)) - .collect(Collectors.toList()); - } else if (LDLib.isReiLoaded()) { - ref.returnValue = REICallWrapper.getReiIngredients(list); - } else if (LDLib.isEmiLoaded()) { - ref.returnValue = EMICallWrapper.getEmiIngredients(list, getXEIChance()); - } - }).ifRight(fluids -> { - var stream = fluids.stream(); - if (LDLib.isJeiLoaded()) { - ref.returnValue = stream.filter(fluid -> !fluid.isEmpty()) - .map(JEICallWrapper::getPlatformFluidTypeForJEI) - .toList(); - } else if (LDLib.isReiLoaded()) { - ref.returnValue = REICallWrapper.getReiIngredients(stream); - } else if (LDLib.isEmiLoaded()) { - ref.returnValue = EMICallWrapper.getEmiIngredients(stream, getXEIChance()); - } - }); - return ref.returnValue; + private List getXEIIngredients(CycleFluidEntryHandler handler, int index) { + FluidEntryList entryList = handler.getEntry(index); + if (LDLib.isJeiLoaded()) { + return JEICallWrapper.getJEIIngredients(entryList); + } else if (LDLib.isReiLoaded()) { + return REICallWrapper.getREIIngredients(entryList); + } else if (LDLib.isEmiLoaded()) { + return EMICallWrapper.getEMIIngredients(entryList, getXEIChance()); + } + return Collections.emptyList(); } - private List getXEIIngredientsFromTagOrCycleHandlerClickable(TagOrCycleFluidHandler handler, int index) { - Either, Integer>>, List> either = handler - .getStacks() - .get(index); - var ref = new Object() { - - List returnValue = Collections.emptyList(); - }; - either.ifLeft(list -> { - if (LDLib.isJeiLoaded()) { - ref.returnValue = list.stream() - .flatMap(pair -> BuiltInRegistries.FLUID - .getTag(pair.getFirst()) - .stream() - .flatMap(HolderSet.ListBacked::stream) - .map(fluid -> new FluidStack(fluid.value(), pair.getSecond())) - .map(fluidStack -> JEICallWrapper.getPlatformFluidTypeForJEIClickable( - fluidStack, getPosition(), getSize()))) - .collect(Collectors.toList()); - } else if (LDLib.isReiLoaded()) { - ref.returnValue = REICallWrapper.getReiIngredients(list); - } else if (LDLib.isEmiLoaded()) { - ref.returnValue = EMICallWrapper.getEmiIngredients(list, getXEIChance()); - } - }).ifRight(fluids -> { - var stream = fluids.stream(); - if (LDLib.isJeiLoaded()) { - ref.returnValue = stream - .filter(fluid -> !fluid.isEmpty()) - .map(fluid -> JEICallWrapper.getPlatformFluidTypeForJEIClickable(fluid, getPosition(), - getSize())) - .toList(); - } else if (LDLib.isReiLoaded()) { - ref.returnValue = REICallWrapper.getReiIngredients(stream); - } else if (LDLib.isEmiLoaded()) { - ref.returnValue = EMICallWrapper.getEmiIngredients(stream, getXEIChance()); - } - }); - return ref.returnValue; + private List getXEIIngredientsClickable(CycleFluidEntryHandler handler, int index) { + FluidEntryList entryList = handler.getEntry(index); + if (LDLib.isJeiLoaded()) { + return JEICallWrapper.getJEIIngredientsClickable(entryList, getPosition(), getSize()); + } else if (LDLib.isReiLoaded()) { + return REICallWrapper.getREIIngredients(entryList); + } else if (LDLib.isEmiLoaded()) { + return EMICallWrapper.getEMIIngredients(entryList, getXEIChance()); + } + return Collections.emptyList(); } @Override @@ -377,22 +303,13 @@ public List getFullTooltipTexts() { if (stack != null && !stack.isEmpty()) { tooltips.add(stack.getDisplayName()); if (!isPhantom && showAmount) { - tooltips.add( - Component.translatable("ldlib.fluid.amount", stack.getAmount(), lastTankCapacity) - .append(" mB")); - } - if (ChemicalHelper.getMaterial(stack.getFluid()) != null) { - TooltipsHandler.appendFluidTooltips(stack.getFluid(), stack.getAmount(), tooltips::add, null); - } else { - tooltips.add(Component.translatable("ldlib.fluid.temperature", - stack.getFluid().getFluidType().getTemperature(stack))); - tooltips.add(Component.translatable(stack.getFluid().getFluidType().isLighterThanAir() ? - "ldlib.fluid.state_gas" : "ldlib.fluid.state_liquid")); + tooltips.add(Component.translatable("gtceu.fluid.amount", stack.getAmount(), lastTankCapacity)); } + TooltipsHandler.appendFluidTooltips(stack, tooltips::add, null); } else { - tooltips.add(Component.translatable("ldlib.fluid.empty")); + tooltips.add(Component.translatable("gtceu.fluid.empty")); if (!isPhantom && showAmount) { - tooltips.add(Component.translatable("ldlib.fluid.amount", 0, lastTankCapacity).append(" mB")); + tooltips.add(Component.translatable("gtceu.fluid.amount", 0, lastTankCapacity).append(" mB")); } } tooltips.addAll(getTooltipTexts()); @@ -410,7 +327,7 @@ public void setCurrentJEIRenderedIngredient(Object ingredient) { @Override @OnlyIn(Dist.CLIENT) - public void drawInBackground(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + public void drawInBackground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { super.drawInBackground(graphics, mouseX, mouseY, partialTicks); if (isClientSideWidget && fluidTank != null) { FluidStack fluidStack = fluidTank.getFluidInTank(tank); @@ -470,7 +387,7 @@ public void drawInBackground(@Nonnull GuiGraphics graphics, int mouseX, int mous @Override @OnlyIn(Dist.CLIENT) - public void drawInForeground(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + public void drawInForeground(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { if (drawHoverTips && isMouseOverElement(mouseX, mouseY) && getHoverElement(mouseX, mouseY) == this) { if (gui != null) { gui.getModularUIGui().setHoverTooltip(getFullTooltipTexts(), ItemStack.EMPTY, null, null); @@ -705,21 +622,37 @@ public void updateScreen() { */ public static final class JEICallWrapper { - public static Object getPlatformFluidTypeForJEI(FluidStack fluidStack) { - return _getPlatformFluidTypeForJEI(JEIPlugin.jeiHelpers.getPlatformFluidHelper(), fluidStack); + public static List getJEIIngredients(FluidEntryList list) { + return list.getStacks() + .stream() + .filter(stack -> !stack.isEmpty()) + .map(JEICallWrapper::getJEIFluid) + .toList(); + } + + public static List getJEIIngredientsClickable(FluidEntryList list, Position pos, Size size) { + return list.getStacks() + .stream() + .filter(stack -> !stack.isEmpty()) + .map(stack -> getJEIFluidClickable(stack, pos, size)) + .toList(); + } + + public static Object getJEIFluid(FluidStack fluidStack) { + return _getJEIFluid(JEIPlugin.jeiHelpers.getPlatformFluidHelper(), fluidStack); } - private static Object _getPlatformFluidTypeForJEI(IPlatformFluidHelper helper, FluidStack fluidStack) { + private static Object _getJEIFluid(IPlatformFluidHelper helper, FluidStack fluidStack) { return helper.create(fluidStack.getFluid(), fluidStack.getAmount(), fluidStack.getTag()); } - public static Object getPlatformFluidTypeForJEIClickable(FluidStack fluidStack, Position pos, Size size) { - return _getPlatformFluidTypeForJEIClickable(JEIPlugin.jeiHelpers.getPlatformFluidHelper(), fluidStack, pos, + public static Object getJEIFluidClickable(FluidStack fluidStack, Position pos, Size size) { + return _getJEIFluidClickable(JEIPlugin.jeiHelpers.getPlatformFluidHelper(), fluidStack, pos, size); } - private static Object _getPlatformFluidTypeForJEIClickable(IPlatformFluidHelper helper, - FluidStack fluidStack, Position pos, Size size) { + private static Object _getJEIFluidClickable(IPlatformFluidHelper helper, + FluidStack fluidStack, Position pos, Size size) { T ingredient = helper.create(fluidStack.getFluid(), fluidStack.getAmount(), fluidStack.getTag()); return JEIPlugin.jeiHelpers.getIngredientManager().createTypedIngredient(ingredient) .map(typedIngredient -> new ClickableIngredient<>(typedIngredient, pos.x, pos.y, size.width, @@ -730,34 +663,56 @@ private static Object _getPlatformFluidTypeForJEIClickable(IPlatformFluidHel public static final class REICallWrapper { - public static List getReiIngredients(Stream stream) { - return List.of(EntryIngredient.of(stream - .map(fluidStack -> dev.architectury.fluid.FluidStack.create(fluidStack.getFluid(), - fluidStack.getAmount(), fluidStack.getTag())) + public static dev.architectury.fluid.FluidStack toREIStack(FluidStack stack) { + return dev.architectury.fluid.FluidStack.create(stack.getFluid(), stack.getAmount(), stack.getTag()); + } + + private static EntryIngredient toREIIngredient(Stream stream) { + return EntryIngredient.of(stream + .map(REICallWrapper::toREIStack) .map(EntryStacks::of) - .toList())); + .toList()); + } + + public static List getREIIngredients(FluidStackList list) { + return List.of(toREIIngredient(list.stream())); } - public static List getReiIngredients(List, Integer>> list) { - return list.stream() - .map(pair -> EntryIngredients.ofTag(pair.getFirst(), - holder -> EntryStacks - .of(dev.architectury.fluid.FluidStack.create(holder.value(), pair.getSecond())))) + public static List getREIIngredients(FluidTagList list) { + return list.getEntries().stream() + .map(FluidTagList.FluidTagEntry::stacks) + .map(REICallWrapper::toREIIngredient) .collect(Collectors.toList()); } + + public static List getREIIngredients(FluidEntryList list) { + if (list instanceof FluidTagList tagList) return getREIIngredients(tagList); + if (list instanceof FluidStackList stackList) return getREIIngredients(stackList); + return Collections.emptyList(); + } } public static final class EMICallWrapper { - public static List getEmiIngredients(Stream stream, float xeiChance) { - return List.of(EmiIngredient.of(stream.map(fluidStack -> EmiStack.of(fluidStack.getFluid(), - fluidStack.getTag(), fluidStack.getAmount())).toList()).setChance(xeiChance)); + private static EmiIngredient toEMIIngredient(Stream stream) { + return EmiIngredient.of(stream.map(ForgeEmiStack::of).toList()); } - public static List getEmiIngredients(List, Integer>> list, float xeiChance) { - return list.stream() - .map(pair -> EmiIngredient.of(pair.getFirst()).setAmount(pair.getSecond()).setChance(xeiChance)) + public static List getEMIIngredients(FluidStackList list, float xeiChance) { + return List.of(toEMIIngredient(list.stream()).setChance(xeiChance)); + } + + public static List getEMIIngredients(FluidTagList list, float xeiChance) { + return list.getEntries().stream() + .map(FluidTagList.FluidTagEntry::stacks) + .map(stream -> toEMIIngredient(stream).setChance(xeiChance)) .collect(Collectors.toList()); } + + public static List getEMIIngredients(FluidEntryList list, float xeiChance) { + if (list instanceof FluidTagList tagList) return getEMIIngredients(tagList, xeiChance); + if (list instanceof FluidStackList stackList) return getEMIIngredients(stackList, xeiChance); + return Collections.emptyList(); + } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/component/ThermalFluidStats.java b/src/main/java/com/gregtechceu/gtceu/api/item/component/ThermalFluidStats.java index 031e1bac16..a427a9f918 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/component/ThermalFluidStats.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/component/ThermalFluidStats.java @@ -75,7 +75,7 @@ public void appendHoverText(ItemStack stack, @Nullable Level level, List, Integer>>, List>> stacks; - - private List> unwrapped = null; - - public TagOrCycleFluidHandler(List, Integer>>, List>> stacks) { - updateStacks(stacks); - } - - public void updateStacks(List, Integer>>, List>> stacks) { - this.stacks = new ArrayList<>(stacks); - this.unwrapped = null; - } - - public List> getUnwrapped() { - if (unwrapped == null) { - unwrapped = stacks.stream() - .map(tagOrFluid -> { - if (tagOrFluid == null) { - return null; - } - return tagOrFluid.map( - tagList -> tagList - .stream() - .flatMap(pair -> BuiltInRegistries.FLUID.getTag(pair.getFirst()) - .map(holderSet -> holderSet.stream() - .map(holder -> new FluidStack(holder.value(), - pair.getSecond()))) - .orElseGet(Stream::empty)) - .toList(), - Function.identity()); - }) - .collect(Collectors.toList()); - } - return unwrapped; - } - - @Override - public int getTanks() { - return stacks.size(); - } - - @NotNull - @Override - public FluidStack getFluidInTank(int tank) { - List stackList = getUnwrapped().get(tank); - return stackList == null || stackList.isEmpty() ? FluidStack.EMPTY : - stackList.get(Math.abs((int) (System.currentTimeMillis() / 1000) % stackList.size())); - } - - @Override - public void setFluidInTank(int tank, @NotNull FluidStack fluidStack) { - if (tank >= 0 && tank < stacks.size()) { - stacks.set(tank, Either.right(List.of(fluidStack))); - unwrapped = null; - } - } - - @Override - public int getTankCapacity(int tank) { - return getFluidInTank(tank).getAmount(); - } - - @Override - public boolean isFluidValid(int tank, @NotNull FluidStack stack) { - return true; - } - - @Override - public int fill(FluidStack resource, FluidAction action) { - return 0; - } - - @Override - public boolean supportsFill(int tank) { - return false; - } - - @NotNull - @Override - public FluidStack drain(FluidStack resource, FluidAction action) { - return FluidStack.EMPTY; - } - - @Override - public @NotNull FluidStack drain(int maxDrain, FluidAction action) { - return FluidStack.EMPTY; - } - - @Override - public boolean supportsDrain(int tank) { - return false; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/api/transfer/item/TagOrCycleItemStackHandler.java b/src/main/java/com/gregtechceu/gtceu/api/transfer/item/TagOrCycleItemStackHandler.java deleted file mode 100644 index 02a91bec19..0000000000 --- a/src/main/java/com/gregtechceu/gtceu/api/transfer/item/TagOrCycleItemStackHandler.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.gregtechceu.gtceu.api.transfer.item; - -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandlerModifiable; - -import com.mojang.datafixers.util.Either; -import com.mojang.datafixers.util.Pair; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class TagOrCycleItemStackHandler implements IItemHandlerModifiable { - - @Getter - private List, Integer>>, List>> stacks; - - private List> unwrapped = null; - - public TagOrCycleItemStackHandler(List, Integer>>, List>> stacks) { - updateStacks(stacks); - } - - public void updateStacks(List, Integer>>, List>> stacks) { - this.stacks = new ArrayList<>(stacks); - this.unwrapped = null; - } - - public List> getUnwrapped() { - if (unwrapped == null) { - unwrapped = stacks.stream() - .map(tagOrItem -> { - if (tagOrItem == null) { - return null; - } - return tagOrItem.map( - tagList -> tagList - .stream() - .flatMap(pair -> BuiltInRegistries.ITEM.getTag(pair.getFirst()) - .map(holderSet -> holderSet.stream() - .map(holder -> new ItemStack(holder.value(), pair.getSecond()))) - .orElseGet(Stream::empty)) - .toList(), - Function.identity()); - }) - .collect(Collectors.toCollection(ArrayList::new)); - } - return unwrapped; - } - - @Override - public int getSlots() { - return stacks.size(); - } - - @NotNull - @Override - public ItemStack getStackInSlot(int slot) { - List stackList = getUnwrapped().get(slot); - return stackList == null || stackList.isEmpty() ? ItemStack.EMPTY : - stackList.get(Math.abs((int) (System.currentTimeMillis() / 1000) % stackList.size())); - } - - @Override - public void setStackInSlot(int index, ItemStack stack) { - if (index >= 0 && index < stacks.size()) { - stacks.set(index, Either.right(List.of(stack))); - unwrapped = null; - } - } - - @NotNull - @Override - public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { - return stack; - } - - @NotNull - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - return ItemStack.EMPTY; - } - - @Override - public int getSlotLimit(int slot) { - return Integer.MAX_VALUE; - } - - @Override - public boolean isItemValid(int slot, @NotNull ItemStack stack) { - return true; - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/client/TooltipsHandler.java b/src/main/java/com/gregtechceu/gtceu/client/TooltipsHandler.java index 2a025704df..3fe75aeafa 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/TooltipsHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/client/TooltipsHandler.java @@ -9,6 +9,8 @@ import com.gregtechceu.gtceu.api.fluids.FluidConstants; import com.gregtechceu.gtceu.api.fluids.FluidState; import com.gregtechceu.gtceu.api.fluids.GTFluid; +import com.gregtechceu.gtceu.common.data.GTFluids; +import com.gregtechceu.gtceu.common.fluid.potion.PotionFluidHelper; import com.gregtechceu.gtceu.data.lang.LangHandler; import com.gregtechceu.gtceu.utils.GTUtil; @@ -16,12 +18,14 @@ import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.tags.FluidTags; import net.minecraft.world.item.BucketItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.material.Fluid; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidType; import java.util.List; @@ -48,7 +52,7 @@ public static void appendTooltips(ItemStack stack, TooltipFlag flag, List tooltips, TooltipFlag flag) { + public static void appendFluidTooltips(FluidStack fluidStack, Consumer tooltips, TooltipFlag flag) { + Fluid fluid = fluidStack.getFluid(); + int amount = fluidStack.getAmount(); FluidType fluidType = fluid.getFluidType(); + + if (fluidType == GTFluids.POTION.getType()) { + if (fluid.is(FluidTags.WATER)) { + return; + } + PotionFluidHelper.addPotionTooltip(fluidStack, tooltips); + return; + } + var material = ChemicalHelper.getMaterial(fluid); if (material != null) { if (material.getChemicalFormula() != null && !material.getChemicalFormula().isEmpty()) @@ -91,21 +106,24 @@ public static void appendFluidTooltips(Fluid fluid, long amount, Consumer tooltips.accept(Component.translatable("gtceu.fluid.state_liquid")); - case GAS -> tooltips.accept(Component.translatable("gtceu.fluid.state_gas")); - case PLASMA -> tooltips.accept(Component.translatable("gtceu.fluid.state_plasma")); - } - - attributedFluid.getAttributes().forEach(a -> a.appendFluidTooltips(tooltips)); - } - tooltips.accept(Component.translatable("gtceu.fluid.temperature", fluidType.getTemperature())); - if (fluidType.getTemperature() < FluidConstants.CRYOGENIC_FLUID_THRESHOLD) { - tooltips.accept(Component.translatable("gtceu.fluid.temperature.cryogenic")); + if (fluid instanceof GTFluid attributedFluid) { + FluidState state = attributedFluid.getState(); + switch (state) { + case LIQUID -> tooltips.accept(Component.translatable("gtceu.fluid.state_liquid")); + case GAS -> tooltips.accept(Component.translatable("gtceu.fluid.state_gas")); + case PLASMA -> tooltips.accept(Component.translatable("gtceu.fluid.state_plasma")); } + attributedFluid.getAttributes().forEach(a -> a.appendFluidTooltips(tooltips)); + } else { + String key = "gtceu.fluid.state_" + (fluidType.isLighterThanAir() ? "gas" : "liquid"); + tooltips.accept(Component.translatable(key)); + } + + tooltips.accept(Component.translatable("gtceu.fluid.temperature", fluidType.getTemperature())); + if (fluidType.getTemperature() < FluidConstants.CRYOGENIC_FLUID_THRESHOLD) { + tooltips.accept(Component.translatable("gtceu.fluid.temperature.cryogenic")); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java index 98e4d6e57f..4504eac441 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java +++ b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java @@ -56,7 +56,6 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.repository.Pack; -import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.event.AddPackFindersEvent; @@ -122,7 +121,6 @@ public static void init() { GTSoundEntries.init(); GTDamageTypes.init(); GTCovers.init(); - ForgeMod.enableMilkFluid(); GTFluids.init(); GTCreativeModeTabs.init(); GTBlocks.init(); diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GCYMRecipeTypes.java b/src/main/java/com/gregtechceu/gtceu/common/data/GCYMRecipeTypes.java index e7b400cbb9..723ea2a78c 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GCYMRecipeTypes.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GCYMRecipeTypes.java @@ -6,7 +6,7 @@ import com.gregtechceu.gtceu.api.gui.GuiTextures; import com.gregtechceu.gtceu.api.gui.widget.SlotWidget; import com.gregtechceu.gtceu.api.recipe.GTRecipeType; -import com.gregtechceu.gtceu.api.transfer.item.CycleItemStackHandler; +import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemStackHandler; import com.gregtechceu.gtceu.utils.FormattingUtil; import com.lowdragmc.lowdraglib.utils.LocalizationUtils; diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTFluids.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTFluids.java index 49047bfb2d..b9e208ae28 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTFluids.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTFluids.java @@ -1,16 +1,20 @@ package com.gregtechceu.gtceu.common.data; +import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.GTCEuAPI; import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; import com.gregtechceu.gtceu.api.data.chemical.material.registry.MaterialRegistry; import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKeys; import com.gregtechceu.gtceu.api.registry.registrate.GTRegistrate; +import com.gregtechceu.gtceu.common.fluid.potion.PotionFluid; +import com.gregtechceu.gtceu.data.recipe.CustomTags; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluids; import net.minecraftforge.common.ForgeMod; +import com.tterrag.registrate.util.entry.FluidEntry; import org.jetbrains.annotations.NotNull; import java.util.function.Supplier; @@ -24,10 +28,19 @@ */ public class GTFluids { + public static final FluidEntry POTION = REGISTRATE + .fluid("potion", GTCEu.id("block/fluids/fluid.potion"), GTCEu.id("block/fluids/fluid.potion"), + PotionFluid.PotionFluidType::new, PotionFluid::new) + .lang("Potion") + .source(PotionFluid::new).noBlock().noBucket() + .tag(CustomTags.POTION_FLUIDS) + .register(); + public static void init() { handleNonMaterialFluids(GTMaterials.Water, Fluids.WATER); handleNonMaterialFluids(GTMaterials.Lava, Fluids.LAVA); handleNonMaterialFluids(GTMaterials.Milk, ForgeMod.MILK); + ForgeMod.enableMilkFluid(); REGISTRATE.creativeModeTab(() -> GTCreativeModeTabs.MATERIAL_FLUID); // register fluids for materials for (MaterialRegistry registry : GTCEuAPI.materialManager.getRegistries()) { diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java index 843bbb39ed..54b2bf71c0 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java @@ -18,8 +18,8 @@ import com.gregtechceu.gtceu.api.sound.ExistingSoundEntry; import com.gregtechceu.gtceu.api.transfer.fluid.CustomFluidTank; import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler; -import com.gregtechceu.gtceu.api.transfer.item.CycleItemStackHandler; import com.gregtechceu.gtceu.common.machine.multiblock.electric.FusionReactorMachine; +import com.gregtechceu.gtceu.common.machine.trait.customlogic.BreweryLogic; import com.gregtechceu.gtceu.common.machine.trait.customlogic.CannerLogic; import com.gregtechceu.gtceu.common.machine.trait.customlogic.FormingPressLogic; import com.gregtechceu.gtceu.common.recipe.condition.RPMCondition; @@ -27,6 +27,7 @@ import com.gregtechceu.gtceu.data.recipe.RecipeHelper; import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder; import com.gregtechceu.gtceu.integration.kjs.GTRegistryInfo; +import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemStackHandler; import com.gregtechceu.gtceu.utils.FormattingUtil; import com.gregtechceu.gtceu.utils.ResearchManager; @@ -143,6 +144,7 @@ public class GTRecipeTypes { .prepareBuilder(recipeBuilder -> recipeBuilder.duration(128).EUt(4)) .setSlotOverlay(false, false, GuiTextures.BREWER_OVERLAY) .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW_MULTIPLE, LEFT_TO_RIGHT) + .addCustomRecipeLogic(new BreweryLogic()) .setSound(GTSoundEntries.CHEMICAL); public final static GTRecipeType MACERATOR_RECIPES = register("macerator", ELECTRIC).setMaxIOSize(1, 4, 0, 0) diff --git a/src/main/java/com/gregtechceu/gtceu/common/fluid/potion/PotionFluid.java b/src/main/java/com/gregtechceu/gtceu/common/fluid/potion/PotionFluid.java new file mode 100644 index 0000000000..1c509b2af8 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/fluid/potion/PotionFluid.java @@ -0,0 +1,122 @@ +package com.gregtechceu.gtceu.common.fluid.potion; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.common.data.GTFluids; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LiquidBlock; +import net.minecraft.world.level.material.FluidState; +import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidType; +import net.minecraftforge.fluids.ForgeFlowingFluid; + +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; + +public class PotionFluid extends ForgeFlowingFluid { + + public PotionFluid(Properties properties) { + super(properties + .bucket(() -> Items.AIR) + .block(() -> (LiquidBlock) Blocks.WATER)); + } + + public static FluidStack of(int amount, Potion potion) { + FluidStack fluidStack = new FluidStack(GTFluids.POTION.get() + .getSource(), amount); + addPotionToFluidStack(fluidStack, potion); + return fluidStack; + } + + public static FluidStack withEffects(int amount, Potion potion, List customEffects) { + FluidStack fluidStack = of(amount, potion); + appendEffects(fluidStack, customEffects); + return fluidStack; + } + + public static FluidStack addPotionToFluidStack(FluidStack fluidStack, Potion potion) { + ResourceLocation resourcelocation = BuiltInRegistries.POTION.getKey(potion); + if (potion == Potions.EMPTY) { + fluidStack.removeChildTag("Potion"); + return fluidStack; + } + fluidStack.getOrCreateTag() + .putString("Potion", resourcelocation.toString()); + return fluidStack; + } + + public static FluidStack appendEffects(FluidStack fluidStack, Collection customEffects) { + if (customEffects.isEmpty()) + return fluidStack; + CompoundTag tag = fluidStack.getOrCreateTag(); + ListTag effects = tag.getList("CustomPotionEffects", 9); + for (MobEffectInstance effect : customEffects) + effects.add(effect.save(new CompoundTag())); + tag.put("CustomPotionEffects", effects); + return fluidStack; + } + + @Override + public boolean isSource(FluidState state) { + return this == GTFluids.POTION.get().getSource(); + } + + @Override + public int getAmount(FluidState state) { + return 0; + } + + public static class PotionFluidType extends FluidType { + + private static final ResourceLocation texture = GTCEu.id("block/fluids/fluid.potion"); + + /** + * Default constructor. + * + * @param properties the general properties of the fluid type + */ + public PotionFluidType(Properties properties, ResourceLocation still, ResourceLocation flow) { + super(properties); + } + + @Override + public void initializeClient(Consumer consumer) { + consumer.accept(new IClientFluidTypeExtensions() { + + @Override + public ResourceLocation getStillTexture() { + return texture; + } + + @Override + public ResourceLocation getFlowingTexture() { + return texture; + } + + @Override + public int getTintColor(FluidStack stack) { + CompoundTag tag = stack.getOrCreateTag(); + return PotionUtils.getColor(PotionUtils.getAllEffects(tag)) | 0xff000000; + } + }); + } + + @Override + public String getDescriptionId(FluidStack stack) { + CompoundTag tag = stack.getOrCreateTag(); + return PotionUtils.getPotion(tag) + .getName(Items.POTION.getDescriptionId() + ".effect."); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/fluid/potion/PotionFluidHelper.java b/src/main/java/com/gregtechceu/gtceu/common/fluid/potion/PotionFluidHelper.java new file mode 100644 index 0000000000..57fe115bb5 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/fluid/potion/PotionFluidHelper.java @@ -0,0 +1,207 @@ +package com.gregtechceu.gtceu.common.fluid.potion; + +import com.gregtechceu.gtceu.api.recipe.ingredient.FluidIngredient; +import com.gregtechceu.gtceu.common.data.GTFluids; +import com.gregtechceu.gtceu.core.mixins.StrictNBTIngredientAccessor; +import com.gregtechceu.gtceu.utils.FormattingUtil; +import com.gregtechceu.gtceu.utils.GTMath; + +import net.minecraft.ChatFormatting; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.Tuple; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffectUtil; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.material.Fluids; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidType; + +import com.google.common.collect.Lists; +import com.mojang.datafixers.util.Pair; + +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Stream; + +public class PotionFluidHelper { + + public static final int BOTTLE_AMOUNT = FluidType.BUCKET_VOLUME / 4; + public static final int MB_PER_RECIPE = BOTTLE_AMOUNT * 3; + + public static Pair emptyPotion(ItemStack stack, boolean simulate) { + FluidStack fluid = getFluidFromPotionItem(stack, BOTTLE_AMOUNT); + if (!simulate) + stack.shrink(1); + return Pair.of(fluid, new ItemStack(Items.GLASS_BOTTLE)); + } + + public static FluidIngredient potionIngredient(Potion potion, int amount) { + FluidStack stack = PotionFluidHelper + .getFluidFromPotionItem(PotionUtils.setPotion(new ItemStack(Items.POTION), potion), amount); + stack.setAmount(amount); + return FluidIngredient.of(stack); + } + + public static FluidIngredient getPotionFluidIngredientFrom(Ingredient potion, int amount) { + if (potion instanceof StrictNBTIngredientAccessor strict) { + return FluidIngredient.of(Stream.of(GTFluids.POTION.get()), amount, strict.getStack().getTag()); + } + + List fluids = new ArrayList<>(); + for (ItemStack stack : potion.getItems()) { + FluidStack fluidStack = getFluidFromPotionItem(stack, amount); + if (!fluidStack.isEmpty()) { + fluids.add(fluidStack); + } + } + return FluidIngredient.of(fluids.toArray(FluidStack[]::new)); + } + + public static FluidStack getFluidFromPotionItem(ItemStack stack, int amount) { + Potion potion = PotionUtils.getPotion(stack); + if (potion == Potions.EMPTY) { + return FluidStack.EMPTY; + } + List list = PotionUtils.getCustomEffects(stack); + if (potion == Potions.WATER && list.isEmpty()) + return new FluidStack(Fluids.WATER, amount); + return PotionFluid.withEffects(amount, potion, list); + } + + public static FluidStack getFluidFromPotion(Potion potion, int amount) { + if (potion == Potions.WATER) + return new FluidStack(Fluids.WATER, amount); + return PotionFluid.of(amount, potion); + } + + public static ItemStack fillBottle(ItemStack stack, FluidStack availableFluid) { + CompoundTag tag = availableFluid.getOrCreateTag(); + if (stack.is(Items.GLASS_BOTTLE)) { + int count = stack.getCount(); + CompoundTag stackTag = stack.getTag(); + stack = new ItemStack(Items.POTION); + stack.setCount(count); + stack.setTag(stackTag); + } + PotionUtils.setPotion(stack, PotionUtils.getPotion(tag)); + PotionUtils.setCustomEffects(stack, PotionUtils.getCustomEffects(tag)); + return stack; + } + + // Modified version of PotionUtils#addPotionTooltip + @OnlyIn(Dist.CLIENT) + public static void addPotionTooltip(FluidStack fs, Consumer tooltip) { + List list = PotionUtils.getAllEffects(fs.getOrCreateTag()); + List> modifiers = Lists.newArrayList(); + if (list.isEmpty()) { + tooltip.accept(Component.translatable("effect.none").withStyle(ChatFormatting.GRAY)); + } else { + for (MobEffectInstance effectInstance : list) { + MutableComponent name = Component.translatable(effectInstance.getDescriptionId()); + MobEffect effect = effectInstance.getEffect(); + Map map = effect.getAttributeModifiers(); + if (!map.isEmpty()) { + for (Map.Entry entry : map.entrySet()) { + AttributeModifier modifier = entry.getValue(); + AttributeModifier mutated = new AttributeModifier(modifier.getName(), + effect.getAttributeModifierValue(effectInstance.getAmplifier(), modifier), + modifier.getOperation()); + modifiers.add(new Tuple<>( + entry.getKey().getDescriptionId(), + mutated)); + } + } + + if (effectInstance.getAmplifier() > 0) { + name = Component.translatable("potion.withAmplifier", name, + Component.translatable("potion.potency." + effectInstance.getAmplifier()));; + } + + if (!effectInstance.endsWithin(20)) { + name = Component.translatable("potion.withDuration", name, + MobEffectUtil.formatDuration(effectInstance, 1.0f)); + + } + + tooltip.accept(name.withStyle(effect.getCategory() + .getTooltipFormatting())); + } + } + + if (!modifiers.isEmpty()) { + tooltip.accept(Component.empty()); + tooltip.accept(Component.translatable("potion.whenDrank").withStyle(ChatFormatting.DARK_PURPLE)); + + for (Tuple tuple : modifiers) { + AttributeModifier modifier2 = tuple.getB(); + double d0 = modifier2.getAmount(); + double d1; + if (modifier2.getOperation() != AttributeModifier.Operation.MULTIPLY_BASE && + modifier2.getOperation() != AttributeModifier.Operation.MULTIPLY_TOTAL) { + d1 = modifier2.getAmount(); + } else { + d1 = modifier2.getAmount() * 100.0D; + } + + if (d0 > 0.0D) { + tooltip.accept(Component.translatable( + "attribute.modifier.plus." + modifier2.getOperation() + .toValue(), + ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), + Component.translatable(tuple.getA())) + .withStyle(ChatFormatting.BLUE)); + } else if (d0 < 0.0D) { + d1 = d1 * -1.0D; + tooltip.accept(Component.translatable( + "attribute.modifier.take." + modifier2.getOperation() + .toValue(), + ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), + Component.translatable(tuple.getA())) + .withStyle(ChatFormatting.RED)); + } + } + } + } + + public static Component formatDuration(MobEffectInstance effect) { + if (effect.isInfiniteDuration()) { + return Component.translatable("effect.duration.infinite"); + } else { + int time = effect.getDuration(); + Instant start = Instant.now(); + Instant max = Instant.now().plusSeconds(time / 20); + Duration durationMax = Duration.between(start, max); + + Component unit; + + if (durationMax.getSeconds() <= 60) { + time = GTMath.saturatedCast(durationMax.getSeconds()); + unit = Component.translatable("item.gtceu.battery.charge_unit.second"); + } else if (durationMax.toMinutes() <= 60) { + time = GTMath.saturatedCast(durationMax.toMinutes()); + unit = Component.translatable("item.gtceu.battery.charge_unit.minute"); + } else { + time = GTMath.saturatedCast(durationMax.toHours()); + unit = Component.translatable("item.gtceu.battery.charge_unit.hour"); + } + + return Component.literal(FormattingUtil.formatNumbers(time)).append(unit); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/trait/customlogic/BreweryLogic.java b/src/main/java/com/gregtechceu/gtceu/common/machine/trait/customlogic/BreweryLogic.java new file mode 100644 index 0000000000..2a3ca77a78 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/trait/customlogic/BreweryLogic.java @@ -0,0 +1,192 @@ +package com.gregtechceu.gtceu.common.machine.trait.customlogic; + +import com.gregtechceu.gtceu.api.capability.recipe.FluidRecipeCapability; +import com.gregtechceu.gtceu.api.capability.recipe.IO; +import com.gregtechceu.gtceu.api.capability.recipe.IRecipeCapabilityHolder; +import com.gregtechceu.gtceu.api.capability.recipe.ItemRecipeCapability; +import com.gregtechceu.gtceu.api.data.tag.TagUtil; +import com.gregtechceu.gtceu.api.recipe.GTRecipe; +import com.gregtechceu.gtceu.api.recipe.GTRecipeType; +import com.gregtechceu.gtceu.api.recipe.ingredient.FluidIngredient; +import com.gregtechceu.gtceu.api.transfer.fluid.FluidHandlerList; +import com.gregtechceu.gtceu.common.data.GTRecipeTypes; +import com.gregtechceu.gtceu.common.fluid.potion.PotionFluidHelper; +import com.gregtechceu.gtceu.core.mixins.PotionBrewingAccessor; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionBrewing; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraftforge.common.brewing.BrewingRecipe; +import net.minecraftforge.common.brewing.BrewingRecipeRegistry; +import net.minecraftforge.common.brewing.IBrewingRecipe; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; + +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Objects; + +import static com.gregtechceu.gtceu.api.GTValues.*; + +@SuppressWarnings("deprecation") +public class BreweryLogic implements GTRecipeType.ICustomRecipeLogic { + + @Override + public @Nullable GTRecipe createCustomRecipe(IRecipeCapabilityHolder holder) { + var itemInputs = Objects + .requireNonNullElseGet(holder.getCapabilitiesProxy().get(IO.IN, ItemRecipeCapability.CAP), + ArrayList::new) + .stream() + .filter(IItemHandlerModifiable.class::isInstance) + .map(IItemHandlerModifiable.class::cast) + .toArray(IItemHandlerModifiable[]::new); + + var fluidInputs = Objects + .requireNonNullElseGet(holder.getCapabilitiesProxy().get(IO.IN, FluidRecipeCapability.CAP), + ArrayList::new) + .stream() + .filter(IFluidHandler.class::isInstance).map(IFluidHandler.class::cast) + .toArray(IFluidHandler[]::new); + + var combinedItemInputs = new CombinedInvWrapper(itemInputs); + var combinedFluidInputs = new FluidHandlerList(fluidInputs); + for (int i = 0; i < combinedItemInputs.getSlots(); i++) { + ItemStack item = combinedItemInputs.getStackInSlot(i); + if (!item.isEmpty()) { + for (PotionBrewing.Mix mix : PotionBrewingAccessor.getPotionMixes()) { + // test item ingredient first + if (!mix.ingredient.test(item)) { + continue; + } + FluidStack fromFluid = PotionFluidHelper.getFluidFromPotion(mix.from.get(), + PotionFluidHelper.MB_PER_RECIPE); + var fromTag = TagUtil + .createFluidTag(BuiltInRegistries.FLUID.getKey(fromFluid.getFluid()).getPath()); + + // then match fluid input + boolean found = false; + for (int j = 0; j < combinedFluidInputs.getTanks(); ++j) { + FluidStack contained = combinedFluidInputs.getFluidInTank(j); + if (!contained.isEmpty() && + contained.getFluid().is(fromTag) && + Objects.equals(fromFluid.getTag(), contained.getTag())) { + found = true; + break; + } + } + if (!found) { + continue; + } + + FluidStack toFluid = PotionFluidHelper.getFluidFromPotion(mix.to.get(), + PotionFluidHelper.MB_PER_RECIPE); + + return GTRecipeTypes.BREWING_RECIPES.recipeBuilder("potion_vanilla_" + mix.to.get().getName("")) + .inputItems(mix.ingredient) + .inputFluids(fromFluid) + .outputFluids(toFluid) + .duration(400) + // is this a good voltage? + .EUt(VHA[MV]) + .buildRawRecipe(); + } + + for (IBrewingRecipe recipe : BrewingRecipeRegistry.getRecipes()) { + if (!(recipe instanceof BrewingRecipe impl)) { + continue; + } + + FluidIngredient fromFluid = PotionFluidHelper.getPotionFluidIngredientFrom(impl.getInput(), + PotionFluidHelper.MB_PER_RECIPE); + + boolean found = false; + for (int j = 0; j < combinedFluidInputs.getTanks(); ++j) { + FluidStack contained = combinedFluidInputs.getFluidInTank(j); + if (!contained.isEmpty() && !fromFluid.test(contained)) { + found = true; + break; + } + } + if (!found) { + continue; + } + + FluidStack toFluid = PotionFluidHelper.getFluidFromPotionItem(impl.getOutput(), + PotionFluidHelper.MB_PER_RECIPE); + + String name = toFluid.getFluid().builtInRegistryHolder().key().location().getPath(); + Potion output = PotionUtils.getPotion(impl.getOutput()); + if (output != null) { + name = output.getName(""); + } + + return GTRecipeTypes.BREWING_RECIPES.recipeBuilder("potion_forge_" + name) + .inputItems(impl.getIngredient()) + .inputFluids(fromFluid) + .outputFluids(toFluid) + .duration(400) + .EUt(VHA[MV]) + .buildRawRecipe(); + + } + } + } + return null; + } + + @Override + public void buildRepresentativeRecipes() { + int index = 0; + for (PotionBrewing.Mix mix : PotionBrewingAccessor.getPotionMixes()) { + FluidStack fromFluid = PotionFluidHelper.getFluidFromPotion(mix.from.get(), + PotionFluidHelper.MB_PER_RECIPE); + FluidStack toFluid = PotionFluidHelper.getFluidFromPotion(mix.to.get(), PotionFluidHelper.MB_PER_RECIPE); + + GTRecipe recipe = GTRecipeTypes.BREWING_RECIPES + .recipeBuilder("potion_vanilla_" + mix.to.get().getName("") + "_" + index++) + .inputItems(mix.ingredient) + .inputFluids(fromFluid) + .outputFluids(toFluid) + .duration(400) + // is this a good voltage? + .EUt(VHA[MV]) + .buildRawRecipe(); + // for EMI to detect it's a synthetic recipe (not ever in JSON) + recipe.setId(recipe.getId().withPrefix("/")); + GTRecipeTypes.BREWING_RECIPES.addToMainCategory(recipe); + } + + for (IBrewingRecipe brewingRecipe : BrewingRecipeRegistry.getRecipes()) { + if (!(brewingRecipe instanceof BrewingRecipe impl)) { + continue; + } + + FluidIngredient fromFluid = PotionFluidHelper.getPotionFluidIngredientFrom(impl.getInput(), + PotionFluidHelper.MB_PER_RECIPE); + FluidStack toFluid = PotionFluidHelper.getFluidFromPotionItem(impl.getOutput(), + PotionFluidHelper.MB_PER_RECIPE); + + String name = toFluid.getFluid().builtInRegistryHolder().key().location().getPath(); + Potion output = PotionUtils.getPotion(impl.getOutput()); + if (output != null) { + name = output.getName(""); + } + + GTRecipe recipe = GTRecipeTypes.BREWING_RECIPES.recipeBuilder("potion_forge_" + name + "_" + index++) + .inputItems(impl.getIngredient()) + .inputFluids(fromFluid) + .outputFluids(toFluid) + .duration(400) + .EUt(VHA[MV]) + .buildRawRecipe(); + // for EMI to detect it's a synthetic recipe (not ever in JSON) + recipe.setId(recipe.getId().withPrefix("/")); + GTRecipeTypes.BREWING_RECIPES.addToMainCategory(recipe); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/trait/customlogic/FormingPressLogic.java b/src/main/java/com/gregtechceu/gtceu/common/machine/trait/customlogic/FormingPressLogic.java index bb7dc1c8c1..e42ece913c 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/trait/customlogic/FormingPressLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/trait/customlogic/FormingPressLogic.java @@ -90,13 +90,15 @@ public void buildRepresentativeRecipes() { toName.setHoverName(Component.translatable("gtceu.forming_press.naming.to_name")); ItemStack named = new ItemStack(Items.NAME_TAG); named.setHoverName(Component.translatable("gtceu.forming_press.naming.named")); - var recipe = GTRecipeTypes.FORMING_PRESS_RECIPES.recipeBuilder("copy") + GTRecipe recipe = GTRecipeTypes.FORMING_PRESS_RECIPES.recipeBuilder("name_item") .notConsumable(press) .inputItems(toName) .outputItems(named) .duration(40) .EUt(4) .buildRawRecipe(); + // for EMI to detect it's a synthetic recipe (not ever in JSON) + recipe.setId(recipe.getId().withPrefix("/")); GTRecipeTypes.FORMING_PRESS_RECIPES.addToMainCategory(recipe); } } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/PotionBrewingAccessor.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/PotionBrewingAccessor.java new file mode 100644 index 0000000000..417afd387e --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/PotionBrewingAccessor.java @@ -0,0 +1,18 @@ +package com.gregtechceu.gtceu.core.mixins; + +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionBrewing; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(PotionBrewing.class) +public interface PotionBrewingAccessor { + + @Accessor("POTION_MIXES") + public static List> getPotionMixes() { + throw new AssertionError(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/emi/FluidEmiStackMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/emi/FluidEmiStackMixin.java index b4b0f82908..05d2e8f6c0 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/emi/FluidEmiStackMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/emi/FluidEmiStackMixin.java @@ -1,10 +1,13 @@ package com.gregtechceu.gtceu.core.mixins.emi; import com.gregtechceu.gtceu.client.TooltipsHandler; +import com.gregtechceu.gtceu.utils.GTMath; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.material.Fluid; +import net.minecraftforge.fluids.FluidStack; import com.llamalad7.mixinextras.sugar.Local; import dev.emi.emi.api.render.EmiTooltipComponents; @@ -25,6 +28,9 @@ public class FluidEmiStackMixin { @Shadow @Final private Fluid fluid; + @Shadow + @Final + private CompoundTag nbt; @Inject(method = "getTooltip", at = @At(value = "INVOKE", target = "Ldev/emi/emi/EmiPort;getFluidRegistry()Lnet/minecraft/core/Registry;"), @@ -32,8 +38,9 @@ public class FluidEmiStackMixin { require = 0) private void gtceu$addFluidTooltip(CallbackInfoReturnable> cir, @Local List list) { - TooltipsHandler.appendFluidTooltips(this.fluid, - ((EmiStack) (Object) this).getAmount(), + TooltipsHandler.appendFluidTooltips(new FluidStack(this.fluid, + Math.max(GTMath.saturatedCast(((EmiStack) (Object) this).getAmount()), 1), + nbt), text -> list.add(EmiTooltipComponents.of(text)), TooltipFlag.NORMAL); } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/jei/FluidHelperMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/jei/FluidHelperMixin.java index d69a8dca13..747d71d711 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/jei/FluidHelperMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/jei/FluidHelperMixin.java @@ -21,6 +21,6 @@ public class FluidHelperMixin { require = 0) private void gtceu$injectFluidTooltips(ITooltipBuilder tooltip, FluidStack ingredient, TooltipFlag tooltipFlag, CallbackInfo ci) { - TooltipsHandler.appendFluidTooltips(ingredient.getFluid(), ingredient.getAmount(), tooltip::add, tooltipFlag); + TooltipsHandler.appendFluidTooltips(ingredient, tooltip::add, tooltipFlag); } } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/rei/FluidEntryRendererMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/rei/FluidEntryRendererMixin.java index 1795f3f438..c9e34e48b0 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/rei/FluidEntryRendererMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/rei/FluidEntryRendererMixin.java @@ -1,6 +1,7 @@ package com.gregtechceu.gtceu.core.mixins.rei; import com.gregtechceu.gtceu.client.TooltipsHandler; +import com.gregtechceu.gtceu.utils.GTMath; import dev.architectury.fluid.FluidStack; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; @@ -21,7 +22,9 @@ public class FluidEntryRendererMixin { require = 0) private void gtceu$addMaterialTooltip(EntryStack entry, TooltipContext context, CallbackInfoReturnable cir) { - TooltipsHandler.appendFluidTooltips(entry.getValue().getFluid(), entry.getValue().getAmount(), + FluidStack stack = entry.getValue(); + TooltipsHandler.appendFluidTooltips(new net.minecraftforge.fluids.FluidStack(stack.getFluid(), + GTMath.saturatedCast(stack.getAmount()), stack.getTag()), cir.getReturnValue()::add, context.getFlag()); } diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/IntegrationLang.java b/src/main/java/com/gregtechceu/gtceu/data/lang/IntegrationLang.java index 3a18359b67..72acbdbc3a 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/IntegrationLang.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/IntegrationLang.java @@ -40,6 +40,8 @@ private static void initRecipeViewerLang(RegistrateLangProvider provider) { String name = GTRegistries.BEDROCK_FLUID_DEFINITIONS.getKey(fluid).getPath(); provider.add("gtceu.jei.bedrock_fluid." + name, RegistrateLangProvider.toEnglishName(name)); } + + provider.add("gtceu.rei.group.potion_fluids", "Potion Fluids"); } /** Jade, TheOneProbe, WTHIT */ diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/CustomTags.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/CustomTags.java index d3a8e9855a..f262be66ba 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/CustomTags.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/CustomTags.java @@ -138,4 +138,5 @@ public class CustomTags { public static final TagKey LIGHTER_FLUIDS = TagUtil.createFluidTag("lighter_fluid"); public static final TagKey MOLTEN_FLUIDS = TagUtil.createFluidTag("molten"); + public static final TagKey POTION_FLUIDS = TagUtil.createFluidTag("potion"); } diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/GTRecipeBuilder.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/GTRecipeBuilder.java index dd0be37943..9abb9358d3 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/GTRecipeBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/builder/GTRecipeBuilder.java @@ -904,13 +904,14 @@ public GTRecipeBuilder chancedTickInputLogic(RecipeCapability cap, ChanceLogi public GTRecipeBuilder inputFluids(FluidStack input) { return input(FluidRecipeCapability.CAP, FluidIngredient.of( - TagUtil.createFluidTag(BuiltInRegistries.FLUID.getKey(input.getFluid()).getPath()), input.getAmount())); + TagUtil.createFluidTag(BuiltInRegistries.FLUID.getKey(input.getFluid()).getPath()), + input.getAmount(), input.getTag())); } public GTRecipeBuilder inputFluids(FluidStack... inputs) { return input(FluidRecipeCapability.CAP, Arrays.stream(inputs).map(fluid -> FluidIngredient.of( TagUtil.createFluidTag(BuiltInRegistries.FLUID.getKey(fluid.getFluid()).getPath()), - fluid.getAmount())).toArray(FluidIngredient[]::new)); + fluid.getAmount(), fluid.getTag())).toArray(FluidIngredient[]::new)); } public GTRecipeBuilder inputFluids(FluidIngredient... inputs) { diff --git a/src/main/java/com/gregtechceu/gtceu/forge/ForgeCommonEventListener.java b/src/main/java/com/gregtechceu/gtceu/forge/ForgeCommonEventListener.java index af70b7c113..0660903260 100644 --- a/src/main/java/com/gregtechceu/gtceu/forge/ForgeCommonEventListener.java +++ b/src/main/java/com/gregtechceu/gtceu/forge/ForgeCommonEventListener.java @@ -20,6 +20,7 @@ import com.gregtechceu.gtceu.api.item.armor.ArmorComponentItem; import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.api.machine.feature.IInteractedMachine; +import com.gregtechceu.gtceu.api.misc.forge.FilteredFluidHandlerItemStack; import com.gregtechceu.gtceu.api.pattern.MultiblockWorldSavedData; import com.gregtechceu.gtceu.api.registry.GTRegistries; import com.gregtechceu.gtceu.common.capability.EnvironmentalHazardSavedData; @@ -33,6 +34,7 @@ import com.gregtechceu.gtceu.common.data.GTItems; import com.gregtechceu.gtceu.common.data.GTMachines; import com.gregtechceu.gtceu.common.data.machines.GTAEMachines; +import com.gregtechceu.gtceu.common.fluid.potion.PotionFluidHelper; import com.gregtechceu.gtceu.common.item.ToggleEnergyConsumerBehavior; import com.gregtechceu.gtceu.common.item.armor.IJetpack; import com.gregtechceu.gtceu.common.network.GTNetwork; @@ -63,6 +65,9 @@ import net.minecraft.world.entity.monster.Zombie; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.PotionItem; +import net.minecraft.world.item.alchemy.PotionUtils; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.common.capabilities.Capability; @@ -85,6 +90,10 @@ import net.minecraftforge.event.server.ServerStoppingEvent; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; +import net.minecraftforge.fluids.capability.templates.FluidHandlerItemStack; import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.items.IItemHandler; @@ -110,8 +119,8 @@ public class ForgeCommonEventListener { @SubscribeEvent public static void registerItemStackCapabilities(AttachCapabilitiesEvent event) { - if (event.getObject().getItem() instanceof IComponentItem componentItem) { - final ItemStack itemStack = event.getObject(); + final ItemStack itemStack = event.getObject(); + if (itemStack.getItem() instanceof IComponentItem componentItem) { event.addCapability(GTCEu.id("capability"), new ICapabilityProvider() { @NotNull @@ -120,9 +129,7 @@ public LazyOptional getCapability(@NotNull Capability cap, @Nullable D return componentItem.getCapability(itemStack, cap); } }); - } - if (event.getObject().getItem() instanceof DrumMachineItem drumMachineItem) { - final ItemStack itemStack = event.getObject(); + } else if (itemStack.getItem() instanceof DrumMachineItem drumMachineItem) { event.addCapability(GTCEu.id("fluid"), new ICapabilityProvider() { @Override @@ -131,6 +138,44 @@ public LazyOptional getCapability(@NotNull Capability cap, @Nullable D return drumMachineItem.getCapability(itemStack, capability); } }); + } else if (itemStack.getItem() instanceof PotionItem) { + LazyOptional handler = LazyOptional.of(() -> { + var fluidHandler = new FluidHandlerItemStack.SwapEmpty(itemStack, new ItemStack(Items.GLASS_BOTTLE), + PotionFluidHelper.BOTTLE_AMOUNT); + fluidHandler.fill(PotionFluidHelper.getFluidFromPotionItem(itemStack, PotionFluidHelper.BOTTLE_AMOUNT), + IFluidHandler.FluidAction.EXECUTE); + return fluidHandler; + }); + event.addCapability(GTCEu.id("potion_item_handler"), new ICapabilityProvider() { + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, + @Nullable Direction side) { + return ForgeCapabilities.FLUID_HANDLER_ITEM.orEmpty(cap, handler); + } + }); + } else if (itemStack.is(Items.GLASS_BOTTLE)) { + LazyOptional handler = LazyOptional.of(() -> new FilteredFluidHandlerItemStack(itemStack, + 250, s -> s.getFluid().is(CustomTags.POTION_FLUIDS)) { + + @Override + protected void setFluid(FluidStack fluid) { + super.setFluid(fluid); + if (!fluid.isEmpty()) { + container = PotionUtils.setPotion(new ItemStack(Items.POTION), + PotionUtils.getPotion(fluid.getTag())); + } + } + }); + event.addCapability(GTCEu.id("bottle_item_handler"), new ICapabilityProvider() { + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, + @Nullable Direction side) { + return ForgeCapabilities.FLUID_HANDLER_ITEM.orEmpty(cap, handler); + } + }); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/integration/ae2/gui/widget/list/AEFluidDisplayWidget.java b/src/main/java/com/gregtechceu/gtceu/integration/ae2/gui/widget/list/AEFluidDisplayWidget.java index 53f2e7dea7..cc1e11d916 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/ae2/gui/widget/list/AEFluidDisplayWidget.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/ae2/gui/widget/list/AEFluidDisplayWidget.java @@ -77,8 +77,7 @@ public void drawInForeground(@NotNull GuiGraphics graphics, int mouseX, int mous List tooltips = new ArrayList<>(); tooltips.add(fluidStack.getDisplayName()); tooltips.add(Component.literal(String.format("%,d mB", fluid.amount()))); - TooltipsHandler.appendFluidTooltips(fluidStack.getFluid(), fluidStack.getAmount(), tooltips::add, - TooltipFlag.NORMAL); + TooltipsHandler.appendFluidTooltips(fluidStack, tooltips::add, TooltipFlag.NORMAL); graphics.renderTooltip(Minecraft.getInstance().font, tooltips, Optional.empty(), mouseX, mouseY); } } diff --git a/src/main/java/com/gregtechceu/gtceu/integration/emi/GTEMIPlugin.java b/src/main/java/com/gregtechceu/gtceu/integration/emi/GTEMIPlugin.java index 5e63424960..d731cb9377 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/emi/GTEMIPlugin.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/emi/GTEMIPlugin.java @@ -4,9 +4,12 @@ import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.recipe.category.GTRecipeCategory; import com.gregtechceu.gtceu.api.registry.GTRegistries; +import com.gregtechceu.gtceu.common.data.GTFluids; import com.gregtechceu.gtceu.common.data.GTItems; import com.gregtechceu.gtceu.common.data.GTMachines; import com.gregtechceu.gtceu.common.data.GTRecipeTypes; +import com.gregtechceu.gtceu.common.fluid.potion.PotionFluid; +import com.gregtechceu.gtceu.common.fluid.potion.PotionFluidHelper; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.integration.emi.circuit.GTProgrammedCircuitCategory; import com.gregtechceu.gtceu.integration.emi.multipage.MultiblockInfoEmiCategory; @@ -22,6 +25,11 @@ import com.lowdragmc.lowdraglib.Platform; import com.lowdragmc.lowdraglib.gui.modular.ModularUIContainer; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraftforge.fluids.FluidStack; + import appeng.menu.me.items.PatternEncodingTermMenu; import de.mari_023.ae2wtlib.wet.WETMenu; import dev.emi.emi.api.EmiEntrypoint; @@ -88,5 +96,15 @@ public void register(EmiRegistry registry) { // Comparators registry.setDefaultComparison(GTItems.PROGRAMMED_CIRCUIT.asItem(), Comparison.compareNbt()); + + Comparison potionComparison = Comparison.compareData(stack -> PotionUtils.getPotion(stack.getNbt())); + PotionFluid potionFluid = GTFluids.POTION.get(); + registry.setDefaultComparison(potionFluid.getSource(), potionComparison); + registry.setDefaultComparison(potionFluid.getFlowing(), potionComparison); + + for (Potion potion : BuiltInRegistries.POTION) { + FluidStack stack = PotionFluidHelper.getFluidFromPotion(potion, PotionFluidHelper.BOTTLE_AMOUNT); + registry.addEmiStack(EmiStack.of(stack.getFluid(), stack.getTag())); + } } } diff --git a/src/main/java/com/gregtechceu/gtceu/integration/jei/GTJEIPlugin.java b/src/main/java/com/gregtechceu/gtceu/integration/jei/GTJEIPlugin.java index f5c71b1837..6916cd0010 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/jei/GTJEIPlugin.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/jei/GTJEIPlugin.java @@ -3,9 +3,11 @@ import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.recipe.category.GTRecipeCategory; import com.gregtechceu.gtceu.api.registry.GTRegistries; +import com.gregtechceu.gtceu.common.data.GTFluids; import com.gregtechceu.gtceu.common.data.GTItems; import com.gregtechceu.gtceu.common.data.GTMachines; import com.gregtechceu.gtceu.common.data.GTRecipeTypes; +import com.gregtechceu.gtceu.common.fluid.potion.PotionFluid; import com.gregtechceu.gtceu.common.item.IntCircuitBehaviour; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.integration.jei.circuit.GTProgrammedCircuitCategory; @@ -15,19 +17,27 @@ import com.gregtechceu.gtceu.integration.jei.orevein.GTBedrockOreInfoCategory; import com.gregtechceu.gtceu.integration.jei.orevein.GTOreVeinInfoCategory; import com.gregtechceu.gtceu.integration.jei.recipe.GTRecipeJEICategory; +import com.gregtechceu.gtceu.integration.jei.subtype.PotionFluidSubtypeInterpreter; import com.lowdragmc.lowdraglib.LDLib; import com.lowdragmc.lowdraglib.Platform; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraftforge.fluids.FluidStack; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; +import mezz.jei.api.forge.ForgeTypes; import mezz.jei.api.helpers.IJeiHelpers; +import mezz.jei.api.helpers.IPlatformFluidHelper; import mezz.jei.api.registration.*; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import javax.annotation.ParametersAreNonnullByDefault; @@ -108,4 +118,23 @@ public void registerIngredients(@NotNull IModIngredientRegistration registry) { public void registerItemSubtypes(ISubtypeRegistration registration) { registration.useNbtForSubtypes(GTItems.PROGRAMMED_CIRCUIT.asItem()); } + + @Override + public void registerFluidSubtypes(ISubtypeRegistration registration, + IPlatformFluidHelper platformFluidHelper) { + PotionFluidSubtypeInterpreter interpreter = new PotionFluidSubtypeInterpreter(); + PotionFluid potionFluid = GTFluids.POTION.get(); + registration.registerSubtypeInterpreter(ForgeTypes.FLUID_STACK, potionFluid.getSource(), interpreter); + registration.registerSubtypeInterpreter(ForgeTypes.FLUID_STACK, potionFluid.getFlowing(), interpreter); + } + + @Override + public void registerExtraIngredients(IExtraIngredientRegistration registration) { + Collection potionFluids = new ArrayList<>(BuiltInRegistries.POTION.size()); + for (Potion potion : BuiltInRegistries.POTION) { + FluidStack potionFluid = PotionFluid.of(1000, potion); + potionFluids.add(potionFluid); + } + registration.addExtraIngredients(ForgeTypes.FLUID_STACK, potionFluids); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/integration/jei/subtype/PotionFluidSubtypeInterpreter.java b/src/main/java/com/gregtechceu/gtceu/integration/jei/subtype/PotionFluidSubtypeInterpreter.java new file mode 100644 index 0000000000..0313ac87aa --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/jei/subtype/PotionFluidSubtypeInterpreter.java @@ -0,0 +1,39 @@ +package com.gregtechceu.gtceu.integration.jei.subtype; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraftforge.fluids.FluidStack; + +import mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter; +import mezz.jei.api.ingredients.subtypes.UidContext; + +import java.util.List; + +/* From JEI's Potion item subtype interpreter */ +public class PotionFluidSubtypeInterpreter implements IIngredientSubtypeInterpreter { + + @Override + public String apply(FluidStack ingredient, UidContext context) { + if (!ingredient.hasTag()) + return IIngredientSubtypeInterpreter.NONE; + + CompoundTag tag = ingredient.getOrCreateTag(); + Potion potionType = PotionUtils.getPotion(tag); + String potionTypeString = potionType.getName(""); + + StringBuilder stringBuilder = new StringBuilder(potionTypeString); + List effects = PotionUtils.getCustomEffects(tag); + + for (MobEffectInstance effect : potionType.getEffects()) { + stringBuilder.append(";") + .append(effect); + } + for (MobEffectInstance effect : effects) { + stringBuilder.append(";") + .append(effect); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/rei/GTREIPlugin.java b/src/main/java/com/gregtechceu/gtceu/integration/rei/GTREIPlugin.java index 0e65588518..49a5975b52 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/rei/GTREIPlugin.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/rei/GTREIPlugin.java @@ -5,10 +5,9 @@ import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.api.recipe.category.GTRecipeCategory; import com.gregtechceu.gtceu.api.registry.GTRegistries; -import com.gregtechceu.gtceu.common.data.GTBlocks; -import com.gregtechceu.gtceu.common.data.GTItems; -import com.gregtechceu.gtceu.common.data.GTMachines; -import com.gregtechceu.gtceu.common.data.GTRecipeTypes; +import com.gregtechceu.gtceu.common.data.*; +import com.gregtechceu.gtceu.common.fluid.potion.PotionFluid; +import com.gregtechceu.gtceu.common.fluid.potion.PotionFluidHelper; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.integration.rei.circuit.GTProgrammedCircuitCategory; import com.gregtechceu.gtceu.integration.rei.multipage.MultiblockInfoDisplayCategory; @@ -20,13 +19,19 @@ import com.lowdragmc.lowdraglib.Platform; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; +import net.minecraft.world.item.alchemy.Potion; import net.minecraft.world.level.ItemLike; +import net.minecraftforge.fluids.FluidStack; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry; +import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.comparison.FluidComparatorRegistry; import me.shedaniel.rei.api.common.entry.comparison.ItemComparatorRegistry; import me.shedaniel.rei.api.common.util.EntryIngredients; import me.shedaniel.rei.api.common.util.EntryStacks; @@ -34,7 +39,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; /** * @author KilaBash @@ -103,10 +107,10 @@ public void registerCollapsibleEntries(CollapsibleEntryRegistry registry) { var material = cell.getKey(); List items = new ArrayList<>(); for (var t : value.entrySet()) { - var name = t.getKey().name; - if (Objects.equals(name, TagPrefix.frameGt.name) || - Objects.equals(name, TagPrefix.block.name) || - Objects.equals(name, TagPrefix.rawOreBlock.name)) + var prefix = t.getKey(); + if (prefix == TagPrefix.frameGt || + prefix == TagPrefix.block || + prefix == TagPrefix.rawOreBlock) continue; items.add(t.getValue()); @@ -117,6 +121,14 @@ public void registerCollapsibleEntries(CollapsibleEntryRegistry registry) { registry.group(GTCEu.id("ore/" + name), Component.translatable("tagprefix.stone", label), EntryIngredients.ofItems(items)); } + + List> stacks = new ArrayList<>(BuiltInRegistries.POTION.size()); + for (Potion potion : BuiltInRegistries.POTION) { + FluidStack stack = PotionFluidHelper.getFluidFromPotion(potion, PotionFluidHelper.BOTTLE_AMOUNT); + stacks.add(EntryStacks + .of(dev.architectury.fluid.FluidStack.create(stack.getFluid(), stack.getAmount(), stack.getTag()))); + } + registry.group(GTCEu.id("potion_fluids"), Component.translatable("gtceu.rei.group.potion_fluids"), stacks); } @Override @@ -124,6 +136,22 @@ public void registerItemComparators(ItemComparatorRegistry registry) { registry.registerNbt(GTItems.PROGRAMMED_CIRCUIT.asItem()); } + @Override + public void registerFluidComparators(FluidComparatorRegistry registry) { + PotionFluid potionFluid = GTFluids.POTION.get(); + registry.registerNbt(potionFluid.getSource()); + registry.registerNbt(potionFluid.getFlowing()); + } + + @Override + public void registerEntries(EntryRegistry registry) { + for (Potion potion : BuiltInRegistries.POTION) { + FluidStack stack = PotionFluidHelper.getFluidFromPotion(potion, PotionFluidHelper.BOTTLE_AMOUNT); + registry.addEntry(EntryStacks.of( + dev.architectury.fluid.FluidStack.create(stack.getFluid(), stack.getAmount(), stack.getTag()))); + } + } + private static String toUpperAllWords(String text) { StringBuilder result = new StringBuilder(); result.append(text.substring(0, 1).toUpperCase()); diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/fluid/FluidEntryList.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/fluid/FluidEntryList.java new file mode 100644 index 0000000000..a010139668 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/fluid/FluidEntryList.java @@ -0,0 +1,12 @@ +package com.gregtechceu.gtceu.integration.xei.entry.fluid; + +import net.minecraftforge.fluids.FluidStack; + +import java.util.List; + +public sealed interface FluidEntryList permits FluidStackList, FluidTagList { + + List getStacks(); + + boolean isEmpty(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/fluid/FluidStackList.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/fluid/FluidStackList.java new file mode 100644 index 0000000000..c24e5ecb76 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/fluid/FluidStackList.java @@ -0,0 +1,51 @@ +package com.gregtechceu.gtceu.integration.xei.entry.fluid; + +import net.minecraftforge.fluids.FluidStack; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; + +public final class FluidStackList implements FluidEntryList { + + private final List stacks; + + public FluidStackList() { + this.stacks = new ArrayList<>(); + } + + public static FluidStackList of(FluidStack stack) { + var list = new FluidStackList(); + list.add(stack); + return list; + } + + public static FluidStackList of(Collection coll) { + var list = new FluidStackList(); + list.addAll(coll); + return list; + } + + public void add(FluidStack stack) { + stacks.add(stack); + } + + public void addAll(Collection list) { + stacks.addAll(list); + } + + @Override + public boolean isEmpty() { + return stacks.isEmpty(); + } + + @Override + public List getStacks() { + return stacks; + } + + public Stream stream() { + return stacks.stream(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/fluid/FluidTagList.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/fluid/FluidTagList.java new file mode 100644 index 0000000000..032eead252 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/fluid/FluidTagList.java @@ -0,0 +1,56 @@ +package com.gregtechceu.gtceu.integration.xei.entry.fluid; + +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.material.Fluid; +import net.minecraftforge.fluids.FluidStack; + +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +public final class FluidTagList implements FluidEntryList { + + @Getter + private final List entries = new ArrayList<>(); + + public static FluidTagList of(@NotNull TagKey tag, int amount, @Nullable CompoundTag nbt) { + var list = new FluidTagList(); + list.add(tag, amount, nbt); + return list; + } + + public void add(FluidTagEntry entry) { + entries.add(entry); + } + + public void add(@NotNull TagKey tag, int amount, @Nullable CompoundTag nbt) { + add(new FluidTagEntry(tag, amount, nbt)); + } + + @Override + public boolean isEmpty() { + return entries.isEmpty(); + } + + @Override + public List getStacks() { + return entries.stream() + .flatMap(FluidTagEntry::stacks) + .toList(); + } + + public record FluidTagEntry(@NotNull TagKey tag, int amount, @Nullable CompoundTag nbt) { + + public Stream stacks() { + return BuiltInRegistries.FLUID.getTag(tag).map(HolderSet.ListBacked::stream).orElseGet(Stream::empty) + .map(holder -> new FluidStack(holder.get(), amount, nbt)); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/item/ItemEntryList.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/item/ItemEntryList.java new file mode 100644 index 0000000000..7b4f8f9883 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/item/ItemEntryList.java @@ -0,0 +1,12 @@ +package com.gregtechceu.gtceu.integration.xei.entry.item; + +import net.minecraft.world.item.ItemStack; + +import java.util.List; + +public sealed interface ItemEntryList permits ItemStackList, ItemTagList { + + List getStacks(); + + boolean isEmpty(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/item/ItemStackList.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/item/ItemStackList.java new file mode 100644 index 0000000000..f6d336f979 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/item/ItemStackList.java @@ -0,0 +1,55 @@ +package com.gregtechceu.gtceu.integration.xei.entry.item; + +import net.minecraft.world.item.ItemStack; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; + +public final class ItemStackList implements ItemEntryList { + + private final List stacks; + + public ItemStackList() { + this.stacks = new ArrayList<>(); + } + + public ItemStackList(List list) { + this.stacks = new ArrayList<>(list); + } + + public static ItemStackList of(ItemStack stack) { + var list = new ItemStackList(); + list.add(stack); + return list; + } + + public static ItemStackList of(Collection coll) { + var list = new ItemStackList(); + list.addAll(coll); + return list; + } + + public void add(ItemStack stack) { + stacks.add(stack); + } + + public void addAll(Collection list) { + stacks.addAll(list); + } + + @Override + public boolean isEmpty() { + return stacks.isEmpty(); + } + + @Override + public List getStacks() { + return stacks; + } + + public Stream stream() { + return stacks.stream(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/item/ItemTagList.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/item/ItemTagList.java new file mode 100644 index 0000000000..881c0dd3ab --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/entry/item/ItemTagList.java @@ -0,0 +1,63 @@ +package com.gregtechceu.gtceu.integration.xei.entry.item; + +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +public final class ItemTagList implements ItemEntryList { + + @Getter + private final List entries = new ArrayList<>(); + + public static ItemTagList of(@NotNull TagKey tag, int amount, @Nullable CompoundTag nbt) { + var list = new ItemTagList(); + list.add(tag, amount, nbt); + return list; + } + + public void add(ItemTagEntry entry) { + entries.add(entry); + } + + public void add(@NotNull TagKey tag, int amount, @Nullable CompoundTag nbt) { + add(new ItemTagEntry(tag, amount, nbt)); + } + + @Override + public boolean isEmpty() { + return entries.isEmpty(); + } + + @Override + public List getStacks() { + return entries.stream() + .flatMap(ItemTagEntry::stacks) + .toList(); + } + + public record ItemTagEntry(@NotNull TagKey tag, int amount, @Nullable CompoundTag nbt) { + + public Stream stacks() { + return BuiltInRegistries.ITEM.getTag(tag).map(HolderSet.ListBacked::stream).orElseGet(Stream::empty) + .map(holder -> stackWithTag(holder, amount, nbt)); + } + } + + private static ItemStack stackWithTag(Holder holder, int amount, @Nullable CompoundTag nbt) { + ItemStack stack = new ItemStack(holder.value(), amount); + stack.setTag(nbt); + return stack; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/fluid/CycleFluidEntryHandler.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/fluid/CycleFluidEntryHandler.java new file mode 100644 index 0000000000..059f60ddc5 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/fluid/CycleFluidEntryHandler.java @@ -0,0 +1,101 @@ +package com.gregtechceu.gtceu.integration.xei.handlers.fluid; + +import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidEntryList; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidStackList; + +import net.minecraftforge.fluids.FluidStack; + +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class CycleFluidEntryHandler implements IFluidHandlerModifiable { + + @Getter + private final List entries; + + private List> unwrapped = null; + + public CycleFluidEntryHandler(List entries) { + this.entries = new ArrayList<>(entries); + } + + public List> getUnwrapped() { + if (unwrapped == null) { + unwrapped = entries.stream() + .map(CycleFluidEntryHandler::getStacksNullable) + .collect(Collectors.toCollection(ArrayList::new)); + } + return unwrapped; + } + + private static List getStacksNullable(FluidEntryList list) { + if (list == null) return null; + return list.getStacks(); + } + + public FluidEntryList getEntry(int index) { + return entries.get(index); + } + + @Override + public int getTanks() { + return entries.size(); + } + + @NotNull + @Override + public FluidStack getFluidInTank(int tank) { + List stackList = getUnwrapped().get(tank); + return stackList == null || stackList.isEmpty() ? FluidStack.EMPTY : + stackList.get(Math.abs((int) (System.currentTimeMillis() / 1000) % stackList.size())); + } + + @Override + public void setFluidInTank(int tank, @NotNull FluidStack fluidStack) { + if (tank >= 0 && tank < entries.size()) { + entries.set(tank, FluidStackList.of(fluidStack)); + unwrapped = null; + } + } + + @Override + public int getTankCapacity(int tank) { + return getFluidInTank(tank).getAmount(); + } + + @Override + public boolean isFluidValid(int tank, @NotNull FluidStack stack) { + return true; + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + return 0; + } + + @Override + public boolean supportsFill(int tank) { + return false; + } + + @NotNull + @Override + public FluidStack drain(FluidStack resource, FluidAction action) { + return FluidStack.EMPTY; + } + + @Override + public @NotNull FluidStack drain(int maxDrain, FluidAction action) { + return FluidStack.EMPTY; + } + + @Override + public boolean supportsDrain(int tank) { + return false; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/transfer/fluid/CycleFluidHandler.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/fluid/CycleFluidStackHandler.java similarity index 66% rename from src/main/java/com/gregtechceu/gtceu/api/transfer/fluid/CycleFluidHandler.java rename to src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/fluid/CycleFluidStackHandler.java index abb57b44ff..bb12e23cc9 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/transfer/fluid/CycleFluidHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/fluid/CycleFluidStackHandler.java @@ -1,21 +1,24 @@ -package com.gregtechceu.gtceu.api.transfer.fluid; +package com.gregtechceu.gtceu.integration.xei.handlers.fluid; + +import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidStackList; import net.minecraftforge.fluids.FluidStack; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.List; -public class CycleFluidHandler implements IFluidHandlerModifiable { - - private List> stacks; +public class CycleFluidStackHandler implements IFluidHandlerModifiable { - public CycleFluidHandler(List> stacks) { - this.updateStacks(stacks); - } + private final List stacks; - public void updateStacks(List> stacks) { - this.stacks = stacks; + public CycleFluidStackHandler(List> stacks) { + this.stacks = new ArrayList<>(); + for (var list : stacks) { + this.stacks.add(FluidStackList.of(list)); + } } @Override @@ -26,7 +29,7 @@ public int getTanks() { @NotNull @Override public FluidStack getFluidInTank(int tank) { - List stackList = this.stacks.get(tank); + List stackList = stacks.get(tank).getStacks(); return stackList != null && !stackList.isEmpty() ? stackList.get(Math.abs((int) (System.currentTimeMillis() / 1000L) % stackList.size())) : FluidStack.EMPTY; @@ -35,7 +38,7 @@ public FluidStack getFluidInTank(int tank) { @Override public void setFluidInTank(int tank, @NotNull FluidStack fluidStack) { if (tank >= 0 && tank < this.stacks.size()) { - this.stacks.set(tank, List.of(fluidStack)); + this.stacks.set(tank, FluidStackList.of(fluidStack)); } } @@ -75,7 +78,7 @@ public boolean supportsDrain(int tank) { return false; } - public List getStackList(int i) { + public FluidStackList getStackList(int i) { return this.stacks.get(i); } } diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/item/CycleItemEntryHandler.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/item/CycleItemEntryHandler.java new file mode 100644 index 0000000000..5dac3e5391 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/item/CycleItemEntryHandler.java @@ -0,0 +1,86 @@ +package com.gregtechceu.gtceu.integration.xei.handlers.item; + +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemEntryList; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemStackList; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandlerModifiable; + +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class CycleItemEntryHandler implements IItemHandlerModifiable { + + @Getter + private final List entries; + private List> unwrapped = null; + + public CycleItemEntryHandler(List entries) { + this.entries = new ArrayList<>(entries); + } + + public List> getUnwrapped() { + if (unwrapped == null) { + unwrapped = entries.stream() + .map(CycleItemEntryHandler::getStacksNullable) + .collect(Collectors.toCollection(ArrayList::new)); + } + return unwrapped; + } + + private static List getStacksNullable(ItemEntryList list) { + if (list == null) return null; + return list.getStacks(); + } + + public ItemEntryList getEntry(int index) { + return entries.get(index); + } + + @Override + public int getSlots() { + return entries.size(); + } + + @NotNull + @Override + public ItemStack getStackInSlot(int slot) { + List stackList = getUnwrapped().get(slot); + return stackList == null || stackList.isEmpty() ? ItemStack.EMPTY : + stackList.get(Math.abs((int) (System.currentTimeMillis() / 1000) % stackList.size())); + } + + @Override + public void setStackInSlot(int index, ItemStack stack) { + if (index >= 0 && index < entries.size()) { + entries.set(index, ItemStackList.of(stack)); + unwrapped = null; + } + } + + @NotNull + @Override + public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + return stack; + } + + @NotNull + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + return ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + return Integer.MAX_VALUE; + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return true; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/transfer/item/CycleItemStackHandler.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/item/CycleItemStackHandler.java similarity index 68% rename from src/main/java/com/gregtechceu/gtceu/api/transfer/item/CycleItemStackHandler.java rename to src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/item/CycleItemStackHandler.java index 1231cb2f04..755bbaa65f 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/transfer/item/CycleItemStackHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/handlers/item/CycleItemStackHandler.java @@ -1,24 +1,26 @@ -package com.gregtechceu.gtceu.api.transfer.item; +package com.gregtechceu.gtceu.integration.xei.handlers.item; + +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemStackList; import net.minecraft.world.item.ItemStack; import net.minecraftforge.items.IItemHandlerModifiable; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.List; import javax.annotation.Nonnull; public class CycleItemStackHandler implements IItemHandlerModifiable { - private List> stacks; + private final List stacks; public CycleItemStackHandler(List> stacks) { - updateStacks(stacks); - } - - public void updateStacks(List> stacks) { - this.stacks = stacks; + this.stacks = new ArrayList<>(); + for (var list : stacks) { + this.stacks.add(ItemStackList.of(list)); + } } @Override @@ -29,19 +31,19 @@ public int getSlots() { @Nonnull @Override public ItemStack getStackInSlot(int i) { - List stackList = stacks.get(i); + List stackList = stacks.get(i).getStacks(); return stackList == null || stackList.isEmpty() ? ItemStack.EMPTY : stackList.get(Math.abs((int) (System.currentTimeMillis() / 1000) % stackList.size())); } @Override - public void setStackInSlot(int index, ItemStack stack) { + public void setStackInSlot(int index, @NotNull ItemStack stack) { if (index >= 0 && index < stacks.size()) { - stacks.set(index, List.of(stack)); + stacks.set(index, ItemStackList.of(stack)); } } - public List getStackList(int i) { + public ItemStackList getStackList(int i) { return stacks.get(i); } diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/widgets/GTOreByProduct.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/widgets/GTOreByProduct.java index 6801ba44dd..c8a2912a8c 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/xei/widgets/GTOreByProduct.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/widgets/GTOreByProduct.java @@ -11,20 +11,21 @@ import com.gregtechceu.gtceu.api.recipe.content.Content; import com.gregtechceu.gtceu.common.data.GTMachines; import com.gregtechceu.gtceu.common.data.GTMaterials; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidEntryList; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidStackList; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidTagList; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemEntryList; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemStackList; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemTagList; import com.gregtechceu.gtceu.utils.FormattingUtil; import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.fluids.FluidStack; import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; import com.mojang.datafixers.util.Pair; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; @@ -47,9 +48,9 @@ public static void addOreByProductPrefix(TagPrefix orePrefix) { private static ImmutableList ALWAYS_MACHINES; private final Int2ObjectMap chances = new Int2ObjectOpenHashMap<>(); - protected final List, Integer>>, List>> itemInputs = new ArrayList<>(); + protected final List itemInputs = new ArrayList<>(); protected final NonNullList itemOutputs = NonNullList.create(); - protected final List, Integer>>, List>> fluidInputs = new ArrayList<>(); + protected final List fluidInputs = new ArrayList<>(); private boolean hasDirectSmelt = false; private boolean hasChemBath = false; private boolean hasSeparator = false; @@ -92,13 +93,13 @@ public GTOreByProduct(Material material) { Pair washedIn = property.getWashedIn(); List separatedInto = property.getSeparatedInto(); - List, Integer>> oreStacks = new ArrayList<>(); + ItemTagList oreStacks = new ItemTagList(); for (TagPrefix prefix : ORES) { // get all ores with the relevant oredicts instead of just the first unified ore - oreStacks.add(Pair.of(ChemicalHelper.getTag(prefix, material), 1)); + oreStacks.add(ChemicalHelper.getTag(prefix, material), 1, null); } - oreStacks.add(Pair.of(ChemicalHelper.getTag(TagPrefix.rawOre, material), 1)); - itemInputs.add(Either.left(oreStacks)); + oreStacks.add(ChemicalHelper.getTag(TagPrefix.rawOre, material), 1, null); + itemInputs.add(oreStacks); // set up machines as inputs List simpleWashers = new ArrayList<>(); @@ -116,9 +117,9 @@ public GTOreByProduct(Material material) { addToInputs(stack); } // same amount of lines as a for loop :trol: - itemInputs.add(Either.right(simpleWashers)); - itemInputs.add(Either.right(simpleWashers)); - itemInputs.add(Either.right(simpleWashers)); + itemInputs.add(ItemStackList.of(simpleWashers)); + itemInputs.add(ItemStackList.of(simpleWashers)); + itemInputs.add(ItemStackList.of(simpleWashers)); if (washedIn != null && washedIn.getFirst() != null) { hasChemBath = true; @@ -141,9 +142,7 @@ public GTOreByProduct(Material material) { // add prefixes that should count as inputs to input lists (they will not be displayed in actual page) for (TagPrefix prefix : IN_PROCESSING_STEPS) { - List, Integer>> tempList = new ArrayList<>(); - tempList.add(Pair.of(ChemicalHelper.getTag(prefix, material), 1)); - itemInputs.add(Either.left(tempList)); + itemInputs.add(ItemTagList.of(ChemicalHelper.getTag(prefix, material), 1, null)); } // total number of inputs added @@ -193,10 +192,10 @@ public GTOreByProduct(Material material) { addToOutputs(material, TagPrefix.crushedPurified, 1); addToOutputs(byproducts[0], TagPrefix.dust, 1); addChance(3333, 0); - List, Integer>> fluidStacks = new ArrayList<>(); - fluidStacks.add(Pair.of(GTMaterials.Water.getFluidTag(), 1000)); - fluidStacks.add(Pair.of(GTMaterials.DistilledWater.getFluidTag(), 100)); - fluidInputs.add(Either.left(fluidStacks)); + FluidTagList tagList = new FluidTagList(); + tagList.add(GTMaterials.Water.getFluidTag(), 1000, null); + tagList.add(GTMaterials.DistilledWater.getFluidTag(), 100, null); + fluidInputs.add(tagList); // TC crushed/crushed purified -> centrifuged addToOutputs(material, TagPrefix.crushedRefined, 1); @@ -233,14 +232,10 @@ public GTOreByProduct(Material material) { addToOutputs(material, TagPrefix.crushedPurified, 1); addToOutputs(byproducts[3], TagPrefix.dust, byproductMultiplier); addChance(7000, 580); - List, Integer>> washedFluid = new ArrayList<>(); - // noinspection DataFlowIssue - washedFluid.add(Pair.of(washedIn.getFirst().getFluidTag(), washedIn.getSecond())); - fluidInputs.add(Either.left(washedFluid)); + fluidInputs.add(FluidTagList.of(washedIn.getFirst().getFluidTag(), washedIn.getSecond(), null)); } else { addEmptyOutputs(2); - List washedFluid = new ArrayList<>(); - fluidInputs.add(Either.right(washedFluid)); + fluidInputs.add(new FluidStackList()); } // electromagnetic separator @@ -339,9 +334,7 @@ private void addEmptyOutputs(int amount) { } private void addToInputs(ItemStack stack) { - List tempList = new ArrayList<>(); - tempList.add(stack); - itemInputs.add(Either.right(tempList)); + itemInputs.add(ItemStackList.of(stack)); } private void addChance(int base, int tier) { diff --git a/src/main/java/com/gregtechceu/gtceu/integration/xei/widgets/GTOreByProductWidget.java b/src/main/java/com/gregtechceu/gtceu/integration/xei/widgets/GTOreByProductWidget.java index 072f4b2543..0452e7399b 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/xei/widgets/GTOreByProductWidget.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/xei/widgets/GTOreByProductWidget.java @@ -6,9 +6,11 @@ import com.gregtechceu.gtceu.api.gui.widget.TankWidget; import com.gregtechceu.gtceu.api.recipe.content.Content; import com.gregtechceu.gtceu.api.transfer.fluid.CustomFluidTank; -import com.gregtechceu.gtceu.api.transfer.fluid.TagOrCycleFluidHandler; import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler; -import com.gregtechceu.gtceu.api.transfer.item.TagOrCycleItemStackHandler; +import com.gregtechceu.gtceu.integration.xei.entry.fluid.FluidEntryList; +import com.gregtechceu.gtceu.integration.xei.entry.item.ItemEntryList; +import com.gregtechceu.gtceu.integration.xei.handlers.fluid.CycleFluidEntryHandler; +import com.gregtechceu.gtceu.integration.xei.handlers.item.CycleItemEntryHandler; import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; @@ -16,19 +18,12 @@ import com.lowdragmc.lowdraglib.jei.IngredientIO; import net.minecraft.core.NonNullList; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.fluids.FluidStack; import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; -import com.mojang.datafixers.util.Pair; import java.util.ArrayList; import java.util.List; -import java.util.function.Function; public class GTOreByProductWidget extends WidgetGroup { @@ -120,8 +115,8 @@ public void setRecipe(GTOreByProduct recipeWrapper) { addWidget(new ImageWidget(0, 0, 176, 166, GuiTextures.OREBY_SIFT)); } - List, Integer>>, List>> itemInputs = recipeWrapper.itemInputs; - TagOrCycleItemStackHandler itemInputsHandler = new TagOrCycleItemStackHandler(itemInputs); + List itemInputs = recipeWrapper.itemInputs; + CycleItemEntryHandler itemInputsHandler = new CycleItemEntryHandler(itemInputs); WidgetGroup itemStackGroup = new WidgetGroup(); for (int i = 0; i < ITEM_INPUT_LOCATIONS.size(); i += 2) { final int finalI = i; @@ -162,12 +157,12 @@ public void setRecipe(GTOreByProduct recipeWrapper) { itemOutputExists.add(true); } - List, Integer>>, List>> fluidInputs = recipeWrapper.fluidInputs; - TagOrCycleFluidHandler fluidInputsHandler = new TagOrCycleFluidHandler(fluidInputs); + List fluidInputs = recipeWrapper.fluidInputs; + CycleFluidEntryHandler fluidInputsHandler = new CycleFluidEntryHandler(fluidInputs); WidgetGroup fluidStackGroup = new WidgetGroup(); for (int i = 0; i < FLUID_LOCATIONS.size(); i += 2) { int slotIndex = i / 2; - if (!fluidInputs.get(slotIndex).map(Function.identity(), Function.identity()).isEmpty()) { + if (!fluidInputs.get(slotIndex).isEmpty()) { var tank = new TankWidget(new CustomFluidTank(fluidInputsHandler.getFluidInTank(slotIndex)), FLUID_LOCATIONS.get(i), FLUID_LOCATIONS.get(i + 1), false, false) .setIngredientIO(IngredientIO.INPUT) diff --git a/src/main/java/com/gregtechceu/gtceu/utils/ItemStackHashStrategy.java b/src/main/java/com/gregtechceu/gtceu/utils/ItemStackHashStrategy.java index cb084b321b..a8f8de1a72 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/ItemStackHashStrategy.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/ItemStackHashStrategy.java @@ -44,6 +44,11 @@ static ItemStackHashStrategy comparingAllButCount() { .build(); } + static ItemStackHashStrategy comparingItem() { + return builder().compareItem(true) + .build(); + } + /** * Builder pattern class for generating customized ItemStackHashStrategy */ diff --git a/src/main/java/com/gregtechceu/gtceu/utils/ResearchManager.java b/src/main/java/com/gregtechceu/gtceu/utils/ResearchManager.java index 378ca529cb..2c8d1b5b49 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/ResearchManager.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/ResearchManager.java @@ -204,13 +204,16 @@ public void buildRepresentativeRecipes() { emptyStick.setHoverName(Component.translatable("gtceu.scanner.copy_stick_empty")); ItemStack resultStick = GTItems.TOOL_DATA_STICK.asStack(); resultStick.setHoverName(Component.translatable("gtceu.scanner.copy_stick_to")); - var recipe = GTRecipeTypes.SCANNER_RECIPES + + GTRecipe recipe = GTRecipeTypes.SCANNER_RECIPES .recipeBuilder("copy_" + GTStringUtils.itemStackToString(copiedStick)) .inputItems(emptyStick) .notConsumable(copiedStick) .outputItems(resultStick) .duration(DURATION).EUt(EUT) .buildRawRecipe(); + // for EMI to detect it's a synthetic recipe (not ever in JSON) + recipe.setId(recipe.getId().withPrefix("/")); GTRecipeTypes.SCANNER_RECIPES.addToMainCategory(recipe); } } diff --git a/src/main/resources/assets/gtceu/textures/block/fluids/fluid.potion.png b/src/main/resources/assets/gtceu/textures/block/fluids/fluid.potion.png new file mode 100644 index 0000000000..8acccc3df0 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/fluids/fluid.potion.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/fluids/fluid.potion.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/fluids/fluid.potion.png.mcmeta new file mode 100644 index 0000000000..36578bcced --- /dev/null +++ b/src/main/resources/assets/gtceu/textures/block/fluids/fluid.potion.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} diff --git a/src/main/resources/gtceu.mixins.json b/src/main/resources/gtceu.mixins.json index 7d668a4318..421eba8583 100644 --- a/src/main/resources/gtceu.mixins.json +++ b/src/main/resources/gtceu.mixins.json @@ -46,6 +46,7 @@ "OreConfigurationMixin", "OreVeinifierMixin", "PartialNBTIngredientAccessor", + "PotionBrewingAccessor", "PrimedTntAccessor", "RecipeManagerAccessor", "RecipeManagerInvoker",