Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distinct Fluid Behaviour and Recipe Runner Refactor #2544

Draft
wants to merge 30 commits into
base: 1.20.1
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dec00eb
refactor recipe handling functions outside of GTRecipe
YoungOnionMC Dec 11, 2024
f111ae8
tables tables tables tables tables tables tables tables tables tables…
YoungOnionMC Dec 12, 2024
d644eda
stuff kinda works
YoungOnionMC Dec 12, 2024
c7db522
some recipe action stuff, gotta fix handler map still
YoungOnionMC Dec 13, 2024
8a613b6
distinctness works in item and dual hatches :lets:
YoungOnionMC Dec 14, 2024
9ffec46
add back non distinct searching
YoungOnionMC Dec 14, 2024
dd8f671
spotless
YoungOnionMC Dec 14, 2024
b45c7a8
fix npe
YoungOnionMC Dec 14, 2024
aa06ec4
refactor the static recipe helper methods into recipe helper, also fi…
YoungOnionMC Dec 15, 2024
b03f3b0
mfw glue sticks
YoungOnionMC Dec 15, 2024
6d56c73
removal of ui names and slot names from content
YoungOnionMC Dec 15, 2024
cf1292c
Merge branch '1.20.1' of https://github.com/GregTechCEu/GregTech-Mode…
YoungOnionMC Dec 15, 2024
4846134
fix miner capability map npeing
YoungOnionMC Dec 15, 2024
d0b83f7
minor change
YoungOnionMC Dec 15, 2024
766e253
Merge branch '1.20.1' of https://github.com/GregTechCEu/GregTech-Mode…
YoungOnionMC Dec 22, 2024
7a64fa8
atleast no more merge conflicts 🥺
YoungOnionMC Dec 22, 2024
ef7addf
thinking emoji
YoungOnionMC Dec 22, 2024
3e53242
recipe runner cleanup
YoungOnionMC Dec 28, 2024
fc669d0
Merge branch 'main' into yo/distinctness
krossgg Jan 22, 2025
a6288cd
Fix merge issues
krossgg Jan 23, 2025
d9fe9dd
Remove extra 'fuel' recipe references
krossgg Jan 23, 2025
44bb424
here you go
krossgg Jan 23, 2025
be65600
only sort for non-tick outputs
krossgg Jan 25, 2025
401a253
doesn't include null RHL in the handler map
YoungOnionMC Jan 26, 2025
c0d8345
Downgrade journeymap-api (#2790)
krossgg Jan 26, 2025
627a974
pattern buffer 😍
krossgg Jan 31, 2025
9f1613c
Merge branch 'main' into yo/distinctness
krossgg Jan 31, 2025
888838f
Fix custom recipe logics
krossgg Feb 1, 2025
da82525
Merge branch 'main' into yo/distinctness
krossgg Feb 1, 2025
1563b22
Merge branch 'main' into yo/distinctness
krossgg Feb 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/generated/resources/assets/gtceu/lang/en_ud.json
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,7 @@
"config.gtceu.option.machines": "sǝuıɥɔɐɯ",
"config.gtceu.option.machinesEmissiveTextures": "sǝɹnʇxǝ⟘ǝʌıssıɯƎsǝuıɥɔɐɯ",
"config.gtceu.option.meHatchEnergyUsage": "ǝbɐs∩ʎbɹǝuƎɥɔʇɐHǝɯ",
"config.gtceu.option.minerSpeed": "pǝǝdSɹǝuıɯ",
"config.gtceu.option.minimap": "dɐɯıuıɯ",
"config.gtceu.option.nanoSaber": "ɹǝqɐSouɐu",
"config.gtceu.option.nanoSaberBaseDamage": "ǝbɐɯɐᗡǝsɐᗺɹǝqɐSouɐu",
Expand Down Expand Up @@ -3516,6 +3517,7 @@
"gtceu.top.allow_output_input": "ʇnduI ʍoןןⱯ",
"gtceu.top.auto_output": "ʇndʇnO oʇnⱯ",
"gtceu.top.buffer_bound_pos": "%s :Z '%s :ʎ '%s :X - o⟘ punoᗺ",
"gtceu.top.buffer_not_bound": "punoᗺ ʎןʇuǝɹɹnƆ ʇoN ɹǝɟɟnᗺ",
"gtceu.top.cable_amperage": " :ǝbɐɹǝdɯⱯ",
"gtceu.top.cable_voltage": " :ǝbɐʇןoΛ",
"gtceu.top.convert_eu": "ɹ§ƎℲɔ§ >- ɹ§∩Ǝǝ§ buıʇɹǝʌuoƆ",
Expand Down
2 changes: 2 additions & 0 deletions src/generated/resources/assets/gtceu/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,7 @@
"config.gtceu.option.machines": "machines",
"config.gtceu.option.machinesEmissiveTextures": "machinesEmissiveTextures",
"config.gtceu.option.meHatchEnergyUsage": "meHatchEnergyUsage",
"config.gtceu.option.minerSpeed": "minerSpeed",
"config.gtceu.option.minimap": "minimap",
"config.gtceu.option.nanoSaber": "nanoSaber",
"config.gtceu.option.nanoSaberBaseDamage": "nanoSaberBaseDamage",
Expand Down Expand Up @@ -3516,6 +3517,7 @@
"gtceu.top.allow_output_input": "Allow Input",
"gtceu.top.auto_output": "Auto Output",
"gtceu.top.buffer_bound_pos": "Bound To - X: %s, Y: %s, Z: %s",
"gtceu.top.buffer_not_bound": "Buffer Not Currently Bound",
"gtceu.top.cable_amperage": "Amperage: ",
"gtceu.top.cable_voltage": "Voltage: ",
"gtceu.top.convert_eu": "Converting §eEU§r -> §cFE§r",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public int getMaxParallelRatio(IRecipeCapabilityHolder holder, GTRecipe recipe,
*/
public static List<Content> makeEUContent(Long eu) {
return List.of(
new Content(eu, ChanceLogic.getMaxChancedValue(), ChanceLogic.getMaxChancedValue(), 0, null, null));
new Content(eu, ChanceLogic.getMaxChancedValue(), ChanceLogic.getMaxChancedValue(), 0));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,7 @@ public int limitParallel(GTRecipe recipe, IRecipeCapabilityHolder holder, int mu
int maxMultiplier = multiplier;

OverlayedTankHandler overlayedFluidHandler = new OverlayedTankHandler(
Objects.requireNonNullElseGet(
holder.getCapabilitiesProxy().get(IO.OUT, FluidRecipeCapability.CAP),
Collections::emptyList)
.stream()
holder.getCapabilitiesFlat(IO.OUT, FluidRecipeCapability.CAP).stream()
.filter(NotifiableFluidTank.class::isInstance)
.map(NotifiableFluidTank.class::cast)
.toList());
Expand Down Expand Up @@ -200,10 +197,7 @@ public int limitParallel(GTRecipe recipe, IRecipeCapabilityHolder holder, int mu
@Override
public int getMaxParallelRatio(IRecipeCapabilityHolder holder, GTRecipe recipe, int parallelAmount) {
// Find all the fluids in the combined Fluid Input inventories and create oversized FluidStacks
Map<FluidKey, Integer> fluidStacks = Objects
.requireNonNullElseGet(holder.getCapabilitiesProxy().get(IO.IN, FluidRecipeCapability.CAP),
Collections::<IRecipeHandler<?>>emptyList)
.stream()
Map<FluidKey, Integer> fluidStacks = holder.getCapabilitiesFlat(IO.IN, FluidRecipeCapability.CAP).stream()
.map(container -> container.getContents().stream().filter(FluidStack.class::isInstance)
.map(FluidStack.class::cast).toList())
.flatMap(container -> GTHashMaps.fromFluidCollection(container).entrySet().stream())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,43 @@
package com.gregtechceu.gtceu.api.capability.recipe;

import com.google.common.collect.Table;
import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerList;

import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

public interface IRecipeCapabilityHolder {

default boolean hasProxies() {
default boolean hasCapabilityProxies() {
return !getCapabilitiesProxy().isEmpty();
}

@NotNull
Table<IO, RecipeCapability<?>, List<IRecipeHandler<?>>> getCapabilitiesProxy();
Map<IO, List<RecipeHandlerList>> getCapabilitiesProxy();

Map<IO, Map<RecipeCapability<?>, List<IRecipeHandler<?>>>> getCapabilitiesFlat();

default List<RecipeHandlerList> getCapabilitiesForIO(IO io) {
return getCapabilitiesProxy().getOrDefault(io, Collections.emptyList());
}

default List<IRecipeHandler<?>> getCapabilitiesFlat(IO io, RecipeCapability<?> cap) {
return getCapabilitiesFlat()
.getOrDefault(io, Collections.emptyMap())
.getOrDefault(cap, Collections.emptyList());
}

default void addHandlerList(RecipeHandlerList handler) {
if (handler == RecipeHandlerList.NO_DATA) return;
IO io = handler.getHandlerIO();
getCapabilitiesProxy().computeIfAbsent(io, i -> new ArrayList<>()).add(handler);
var inner = getCapabilitiesFlat().computeIfAbsent(io, i -> new Reference2ObjectOpenHashMap<>());
for (var entry : handler.getHandlerMap().entrySet()) {
inner.computeIfAbsent(entry.getKey(), c -> new ArrayList<>()).addAll(entry.getValue());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
import com.gregtechceu.gtceu.api.recipe.GTRecipe;

import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.jetbrains.annotations.Nullable;

import java.util.Comparator;
import java.util.List;
import java.util.Set;

/**
* @author KilaBash
Expand Down Expand Up @@ -35,21 +33,12 @@ public interface IRecipeHandler<K> extends IFilteredHandler<K> {
* @param io the IO type of this recipe. always be one of the {@link IO#IN} or {@link IO#OUT}
* @param recipe recipe.
* @param left left contents for to be handled.
* @param slotName specific slot name.
* @param simulate simulate.
* @return left contents for continue handling by other proxies.
* <br>
* null - nothing left. handling successful/finish. you should always return null as a handling-done mark.
*/
List<K> handleRecipeInner(IO io, GTRecipe recipe, List<K> left, @Nullable String slotName, boolean simulate);

/**
* Slot name, it makes sense if recipe contents specify a slot name.
*/
@Nullable
default Set<String> getSlotNames() {
return null;
}
List<K> handleRecipeInner(IO io, GTRecipe recipe, List<K> left, boolean simulate);

/**
* container size, if it has one. otherwise -1.
Expand Down Expand Up @@ -80,12 +69,12 @@ default K copyContent(Object content) {
return getCapability().copyInner((K) content);
}

default List<K> handleRecipe(IO io, GTRecipe recipe, List<?> left, @Nullable String slotName, boolean simulate) {
default List<K> handleRecipe(IO io, GTRecipe recipe, List<?> left, boolean simulate) {
List<K> contents = new ObjectArrayList<>(left.size());
for (Object leftObj : left) {
contents.add(copyContent(leftObj));
}
return handleRecipeInner(io, recipe, contents, slotName, simulate);
return handleRecipeInner(io, recipe, contents, simulate);
}

default void preWorking(IRecipeCapabilityHolder holder, IO io, GTRecipe recipe) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,7 @@ public int limitParallel(GTRecipe recipe, IRecipeCapabilityHolder holder, int mu
int maxMultiplier = multiplier;

OverlayedItemHandler itemHandler = new OverlayedItemHandler(new CombinedInvWrapper(
Objects.requireNonNullElseGet(holder.getCapabilitiesProxy().get(IO.OUT, ItemRecipeCapability.CAP),
Collections::emptyList)
.stream()
holder.getCapabilitiesFlat(IO.OUT, ItemRecipeCapability.CAP).stream()
.filter(IItemHandlerModifiable.class::isInstance)
.map(IItemHandlerModifiable.class::cast)
.toArray(IItemHandlerModifiable[]::new)));
Expand Down Expand Up @@ -382,10 +380,7 @@ private Object2IntMap<ItemStack> getIngredientStacks(IRecipeCapabilityHolder hol
ItemStackHashStrategy.comparingAllButCount());
Object2IntMap<ItemStack> result = new Object2IntOpenHashMap<>();

List<IRecipeHandler<?>> recipeHandlerList = Objects
.requireNonNullElseGet(holder.getCapabilitiesProxy().get(IO.IN, ItemRecipeCapability.CAP),
Collections::<IRecipeHandler<?>>emptyList)
.stream()
var recipeHandlerList = holder.getCapabilitiesFlat(IO.IN, ItemRecipeCapability.CAP).stream()
.filter(handler -> !handler.isProxy()).toList();

for (IRecipeHandler<?> container : recipeHandlerList) {
Expand Down
33 changes: 18 additions & 15 deletions src/main/java/com/gregtechceu/gtceu/api/item/tool/ToolHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
import com.gregtechceu.gtceu.api.item.IGTTool;
import com.gregtechceu.gtceu.api.item.tool.aoe.AoESymmetrical;
import com.gregtechceu.gtceu.api.machine.trait.NotifiableItemStackHandler;
import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerList;
import com.gregtechceu.gtceu.api.recipe.GTRecipe;
import com.gregtechceu.gtceu.api.recipe.RecipeHelper;
import com.gregtechceu.gtceu.api.recipe.content.Content;
import com.gregtechceu.gtceu.api.recipe.ingredient.SizedIngredient;
import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler;
Expand Down Expand Up @@ -64,8 +66,6 @@

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Table;
import com.google.common.collect.Tables;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -412,22 +412,25 @@ public static void applyHammerDropConversion(ServerLevel world, BlockPos pos, It
// Stack lists can be immutable going into Recipe#matches barring no rewrites
// Search for forge hammer recipes from all drops individually (only LV or under)

Table<IO, RecipeCapability<?>, List<IRecipeHandler<?>>> caps = Tables
.newCustomTable(new EnumMap<>(IO.class), IdentityHashMap::new);
Map<IO, List<RecipeHandlerList>> caps = new IdentityHashMap<>();
DummyMachineBlockEntity be = new DummyMachineBlockEntity(GTValues.LV,
GTRecipeTypes.FORGE_HAMMER_RECIPES, GTMachineUtils.defaultTankSizeFunction, caps);
caps.put(IO.IN, EURecipeCapability.CAP, List.of(new InfiniteEnergyContainer(be.getMetaMachine(),
GTValues.V[GTValues.LV], GTValues.V[GTValues.LV], 1, GTValues.V[GTValues.LV], 1)));
caps.put(IO.IN, ItemRecipeCapability.CAP, List.of(new NotifiableItemStackHandler(be.getMetaMachine(), 1,
IO.IN, IO.IN, (slots) -> new CustomItemStackHandler(silktouchDrop))));
caps.put(IO.OUT, ItemRecipeCapability.CAP,
List.of(new NotifiableItemStackHandler(be.getMetaMachine(), 2, IO.OUT)));
be.getMetaMachine().reinitializeCapabilities(caps);

Iterator<GTRecipe> hammerRecipes = GTRecipeTypes.FORGE_HAMMER_RECIPES.searchRecipe(be.metaMachine);
RecipeHandlerList dummyInputs = new RecipeHandlerList(IO.IN);
dummyInputs.addHandlers(
new InfiniteEnergyContainer(be.getMetaMachine(), GTValues.V[GTValues.LV],
GTValues.V[GTValues.LV], 1, GTValues.V[GTValues.LV], 1),
new NotifiableItemStackHandler(be.getMetaMachine(), 1, IO.IN, IO.IN,
(slots) -> new CustomItemStackHandler(silktouchDrop)));

RecipeHandlerList dummyOutputs = RecipeHandlerList.of(IO.OUT,
new NotifiableItemStackHandler(be.getMetaMachine(), 2, IO.OUT));
be.getMetaMachine().reinitializeHandlers(List.of(dummyInputs, dummyOutputs));

Iterator<GTRecipe> hammerRecipes = GTRecipeTypes.FORGE_HAMMER_RECIPES.searchRecipe(be.metaMachine,
r -> RecipeHelper.matchContents(be.metaMachine, r).isSuccess());
GTRecipe hammerRecipe = hammerRecipes == null || !hammerRecipes.hasNext() ? null : hammerRecipes.next();
if (hammerRecipe != null && hammerRecipe.handleRecipeIO(IO.IN, be.metaMachine,
be.getMetaMachine().recipeLogic.getChanceCaches())) {
if (hammerRecipe != null && RecipeHelper.handleRecipeIO(IO.IN, be.metaMachine, hammerRecipe,
be.getMetaMachine().recipeLogic.getChanceCaches()).isSuccess()) {
drops.clear();
TagPrefix prefix = ChemicalHelper.getPrefix(silktouchDrop.getItem());
if (prefix == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted;
import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder;

import com.google.common.collect.Table;
import com.google.common.collect.Tables;
import com.mojang.blaze3d.MethodsReturnNonnullByDefault;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import lombok.Getter;
Expand Down Expand Up @@ -67,7 +65,9 @@ public abstract class WorkableTieredMachine extends TieredEnergyMachine implemen
@Persisted
public final NotifiableComputationContainer exportComputation;
@Getter
protected final Table<IO, RecipeCapability<?>, List<IRecipeHandler<?>>> capabilitiesProxy;
protected final Map<IO, List<RecipeHandlerList>> capabilitiesProxy;
@Getter
protected Map<IO, Map<RecipeCapability<?>, List<IRecipeHandler<?>>>> capabilitiesFlat;
@Persisted
@Getter
protected int overclockTier;
Expand All @@ -86,7 +86,8 @@ public WorkableTieredMachine(IMachineBlockEntity holder, int tier, Int2IntFuncti
this.recipeTypes = getDefinition().getRecipeTypes();
this.activeRecipeType = 0;
this.tankScalingFunction = tankScalingFunction;
this.capabilitiesProxy = Tables.newCustomTable(new EnumMap<>(IO.class), IdentityHashMap::new);
this.capabilitiesProxy = new EnumMap<>(IO.class);
this.capabilitiesFlat = new EnumMap<>(IO.class);
this.traitSubscriptions = new ArrayList<>();
this.recipeLogic = createRecipeLogic(args);
this.importItems = createImportItemHandler(args);
Expand Down Expand Up @@ -162,22 +163,30 @@ protected RecipeLogic createRecipeLogic(Object... args) {
@Override
public void onLoad() {
super.onLoad();
// attach self traits
Map<IO, List<IRecipeHandler<?>>> ioTraits = new EnumMap<>(IO.class);

for (MachineTrait trait : getTraits()) {
if (trait instanceof IRecipeHandlerTrait<?> handlerTrait) {
if (!capabilitiesProxy.contains(handlerTrait.getHandlerIO(), handlerTrait.getCapability())) {
capabilitiesProxy.put(handlerTrait.getHandlerIO(), handlerTrait.getCapability(), new ArrayList<>());
}
capabilitiesProxy.get(handlerTrait.getHandlerIO(), handlerTrait.getCapability()).add(handlerTrait);
traitSubscriptions.add(handlerTrait.addChangedListener(recipeLogic::updateTickSubscription));
ioTraits.computeIfAbsent(handlerTrait.getHandlerIO(), i -> new ArrayList<>()).add(handlerTrait);
}
}

for (var entry : ioTraits.entrySet()) {
RecipeHandlerList handlerList = new RecipeHandlerList(entry.getKey());
handlerList.addHandlers(entry.getValue());
this.addHandlerList(handlerList);
traitSubscriptions.addAll(handlerList.addChangeListeners(recipeLogic::updateTickSubscription));
}
}

@Override
public void onUnload() {
super.onUnload();
traitSubscriptions.forEach(ISubscription::unsubscribe);
traitSubscriptions.clear();
capabilitiesProxy.clear();
capabilitiesFlat.clear();
recipeLogic.inValid();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic;
import com.gregtechceu.gtceu.api.recipe.GTRecipe;
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
import com.gregtechceu.gtceu.api.recipe.RecipeHelper;
import com.gregtechceu.gtceu.config.ConfigHolder;

import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -45,7 +46,7 @@ default void notifyStatusChanged(RecipeLogic.Status oldStatus, RecipeLogic.Statu
RecipeLogic getRecipeLogic();

default GTRecipe fullModifyRecipe(GTRecipe recipe) {
return doModifyRecipe(recipe.trimRecipeOutputs(this.getOutputLimits()));
return doModifyRecipe(RecipeHelper.trimRecipeOutputs(recipe, this.getOutputLimits()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.gregtechceu.gtceu.api.machine.feature.IFancyUIMachine;
import com.gregtechceu.gtceu.api.machine.feature.IMachineFeature;
import com.gregtechceu.gtceu.api.machine.multiblock.WorkableMultiblockMachine;
import com.gregtechceu.gtceu.api.machine.trait.IRecipeHandlerTrait;
import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerList;
import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic;
import com.gregtechceu.gtceu.api.recipe.GTRecipe;

Expand Down Expand Up @@ -64,7 +64,7 @@ default boolean canShared() {
/**
* Get all available traits for recipe logic.
*/
List<IRecipeHandlerTrait> getRecipeHandlers();
List<RecipeHandlerList> getRecipeHandlers();

/**
* whether its base model can be replaced by controller when it is formed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,17 +192,17 @@ public long getOverclockVoltage() {

public EnergyContainerList getEnergyContainer() {
List<IEnergyContainer> containers = new ArrayList<>();
var capabilities = capabilitiesProxy.get(IO.IN, EURecipeCapability.CAP);
if (capabilities != null) {
for (IRecipeHandler<?> handler : capabilities) {
var handlers = getCapabilitiesFlat(IO.IN, EURecipeCapability.CAP);
if (!handlers.isEmpty()) {
for (IRecipeHandler<?> handler : handlers) {
if (handler instanceof IEnergyContainer container) {
containers.add(container);
}
}
} else {
capabilities = capabilitiesProxy.get(IO.OUT, EURecipeCapability.CAP);
if (capabilities != null) {
for (IRecipeHandler<?> handler : capabilities) {
handlers = getCapabilitiesFlat(IO.OUT, EURecipeCapability.CAP);
if (!handlers.isEmpty()) {
for (IRecipeHandler<?> handler : handlers) {
if (handler instanceof IEnergyContainer container) {
containers.add(container);
}
Expand Down
Loading