diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c703844e..4840bb020 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,19 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed +- Fluid & checmical filter can use `amount` instead of `count`. `count` field will be removed in 0.8. +- When filter is invalid, an error will be thrown instead of return a silent ignorable string. + ### Fixed - Fixed support for Refined Storage version 2.0.0 - [#786] Minor performance improvements to the RS Bridges resources iteration - improves the performance with any get*Resource* function - Thanks to @SirYwell! - [#784] Fixed that the energy detector transfer rate limit is not enforced - Fixed an issue where the ME Bridge could void chemicals during exporting/importing - Fixed an issue where export/import fluids and chemicals in the ME Bridge would not detect any remote target peripherals +- Fixed an issue when export/import with slots out of the range will cause error +- Fixed bridges will only export the first item that matches the filter +- [#794] Fixed bridges will only import fluids from the first tank. ## [1.21.1-0.7.55b] - 2025-07-14 diff --git a/build.gradle b/build.gradle index dae9adc6b..f5edf7f58 100644 --- a/build.gradle +++ b/build.gradle @@ -160,9 +160,17 @@ repositories { } maven { name = "Create maven" - url = "https://maven.tterrag.com/" + url = "https://maven.createmod.net" content { includeGroup("com.simibubi.create") + includeGroup("dev.engine-room.flywheel") + includeGroup("net.createmod.ponder") + } + } + maven { + name = "Create Registrate maven" + url = "https://maven.ithundxr.dev/snapshots" + content { includeGroup("com.tterrag.registrate") } } @@ -234,9 +242,6 @@ dependencies { transitive = false } - // Needed for the refined storage mek integration - //compileOnlyApi("dev.emi:emi-neoforge:${emiVersion}") - // Extended requirements // We don't use the api since we need a specific class from mekanism compileOnly "mekanism:Mekanism:${mekanism_version}" @@ -254,6 +259,12 @@ dependencies { compileOnly "curse.maven:ae2things-609977:${ae2things_version}-sources" runtimeOnly "curse.maven:ae2things-609977:${ae2things_version}-sources" + implementation ("com.simibubi.create:create-${minecraft_version}:${create_version}:slim") { transitive = false } + implementation "net.createmod.ponder:Ponder-NeoForge-${minecraft_version}:${ponder_version}" + compileOnly "dev.engine-room.flywheel:flywheel-neoforge-api-${minecraft_version}:${flywheel_version}" + runtimeOnly "dev.engine-room.flywheel:flywheel-neoforge-${minecraft_version}:${flywheel_version}" + implementation "com.tterrag.registrate:Registrate:${registrate_version}" + // Minecolonies compileOnly "com.ldtteam:blockui:${blockui_version}" compileOnly "com.ldtteam:domum-ornamentum:${domumornamentum_version}" diff --git a/gradle.properties b/gradle.properties index 989b7b03e..05eb65466 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ mod_id=advancedperipherals mod_version=0.7.55b minecraft_version=1.21.1 mod_artifact_suffix= -neo_version=21.1.194 +neo_version=21.1.200 parchment_minecraft_version=1.21.1 parchment_mappings_version=2024.11.17 loader_version=4 @@ -30,24 +30,26 @@ cc_version=1.116.0 ae2things_version=5637783 appliedenergistics_version=19.2.13 appliedmekanistics_version=5978711 -refinedstorage_version=2.0.0 -refinedstorage_mekanism_version=1.1.0 +mekanism_version=1.21.1-10.7.15.81 minecolonies_version=1.1.1020-1.21.1-snapshot patchouli_version=1.21-88 -mekanism_version=1.21.1-10.7.15.81 powah_version=6143661 +refinedstorage_mekanism_version=1.1.0 +refinedstorage_version=2.0.0 # Mod dependencies which are needed for other mods # minecolonies -structurize_version=1.0.775-1.21.1-snapshot -multipiston_version=1.2.51-1.21.1-snapshot blockui_version=1.0.199-1.21.1-snapshot domumornamentum_version=1.0.216-snapshot -# refined storage mek integration -emiVersion=1.1.11+1.21 +multipiston_version=1.2.51-1.21.1-snapshot +structurize_version=1.0.775-1.21.1-snapshot # powah cloth_config_version=15.0.127 # Mod dependencies for testing stuff(Only used in the dev environment) +create_version=6.0.8-168 +createadditions_version=5099752minecraft_version = 1.21.1 emi_version=1.1.22+1.21.1 -createadditions_version=5099752 \ No newline at end of file +flywheel_version=1.0.5 +ponder_version=1.0.64 +registrate_version=MC1.21-1.3.0+62 diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/AEApi.java b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/AEApi.java index e80880bcb..6ec34bb49 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/AEApi.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/AEApi.java @@ -99,6 +99,17 @@ public static Pair findAEStackFromFilter(MEStorage monitor, @Nu return Pair.of(0L, null); } + @NotNull + public static List> findAEStacksFromFilter(MEStorage monitor, ItemFilter filter) { + List> items = new ArrayList<>(); + for (Object2LongMap.Entry temp : monitor.getAvailableStacks()) { + if (temp.getKey() instanceof AEItemKey key && filter.test(key.toStack())) { + items.add(Pair.of(temp.getLongValue(), key)); + } + } + return items; + } + @NotNull public static Pair findAEFluidFromStack(MEStorage monitor, @Nullable ICraftingService crafting, FluidStack item) { return findAEFluidFromFilter(monitor, crafting, FluidFilter.fromStack(item)); @@ -122,6 +133,17 @@ public static Pair findAEFluidFromFilter(MEStorage monitor, @N return Pair.of(0L, null); } + @NotNull + public static List> findAEFluidsFromFilter(MEStorage monitor, FluidFilter filter) { + List> fluids = new ArrayList<>(); + for (Object2LongMap.Entry temp : monitor.getAvailableStacks()) { + if (temp.getKey() instanceof AEFluidKey key && filter.test(key.toStack(1))) { + fluids.add(Pair.of(temp.getLongValue(), key)); + } + } + return fluids; + } + @NotNull public static Pair findAEChemicalFromStack(MEStorage monitor, @Nullable ICraftingService crafting, ChemicalStack stack) { return findAEChemicalFromFilter(monitor, crafting, ChemicalFilter.fromStack(stack)); @@ -145,6 +167,17 @@ public static Pair findAEChemicalFromFilter(MEStorage monitor return Pair.of(0L, null); } + @NotNull + public static List> findAEChemicalsFromFilter(MEStorage monitor, ChemicalFilter filter) { + List> chemicals = new ArrayList<>(); + for (Object2LongMap.Entry temp : monitor.getAvailableStacks()) { + if (temp.getKey() instanceof MekanismKey key && filter.test(key.getStack())) { + chemicals.add(Pair.of(temp.getLongValue(), key)); + } + } + return chemicals; + } + /** * Finds a pattern from filters. * diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEChemicalHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEChemicalHandler.java index 89280b950..e2c563da2 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEChemicalHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEChemicalHandler.java @@ -3,16 +3,18 @@ import appeng.api.config.Actionable; import appeng.api.networking.security.IActionSource; import appeng.api.storage.MEStorage; -import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.MEBridgePeripheral; import de.srendi.advancedperipherals.common.util.Pair; import de.srendi.advancedperipherals.common.util.inventory.ChemicalFilter; import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemChemicalHandler; +import de.srendi.advancedperipherals.common.util.inventory.StorageProcessor; import me.ramidzkh.mekae2.ae2.MekanismKey; import mekanism.api.Action; import mekanism.api.chemical.ChemicalStack; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * Used to transfer a chemical between a tank and the ME system. * @@ -32,28 +34,43 @@ public MEChemicalHandler(@NotNull MEStorage storageMonitor, @NotNull IActionSour @NotNull @Override - public ChemicalStack insertChemical(int tank, ChemicalStack resource, @NotNull Action action) { - if (resource.isEmpty()) + public ChemicalStack insertChemical(ChemicalStack resource, @NotNull Action action) { + if (resource.isEmpty()) { return resource; + } ChemicalStack remain = resource.copy(); - long amountInserted = storageMonitor.insert(MekanismKey.of(resource), resource.getAmount(), action == Action.SIMULATE ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); + long amountInserted = storageMonitor.insert(MekanismKey.of(resource), resource.getAmount(), action.simulate() ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); remain.setAmount(resource.getAmount() - amountInserted); return remain; } - @NotNull @Override - public ChemicalStack extractChemical(ChemicalFilter filter, long count, Action simulate) { - Pair chemicalKey = AEApi.findAEChemicalFromFilter(storageMonitor, null, filter); - if (chemicalKey.getRight() == null) - return ChemicalStack.EMPTY; - - ChemicalStack extracted = chemicalKey.getRight().getStack(); + public long extractChemicals(ChemicalFilter filter, StorageProcessor.Large processor, Action action) { + List> chemicalKeys = AEApi.findAEChemicalsFromFilter(storageMonitor, filter); + if (chemicalKeys.isEmpty()) { + return 0; + } - long amountExtracted = storageMonitor.extract(chemicalKey.getRight(), count, simulate == Action.SIMULATE ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); - extracted.setAmount(amountExtracted); - AdvancedPeripherals.debug("Extracted chemical: " + extracted + " from filter: " + filter); - return extracted; + long needs = filter.getAmount(); + for (Pair pair : chemicalKeys) { + MekanismKey chemicalKey = pair.right(); + long amount = storageMonitor.extract(chemicalKey, needs, Actionable.SIMULATE, actionSource); + if (amount == 0) { + continue; + } + long extracted = processor.process(chemicalKey.getStack().copyWithAmount(amount)); + if (extracted == 0) { + continue; + } + needs -= extracted; + if (action.execute()) { + storageMonitor.extract(chemicalKey, extracted, Actionable.MODULATE, actionSource); + } + if (needs <= 0) { + break; + } + } + return filter.getAmount() - needs; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEFluidHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEFluidHandler.java index 91c2f121b..89ad22284 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEFluidHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEFluidHandler.java @@ -8,9 +8,12 @@ import de.srendi.advancedperipherals.common.util.Pair; import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemFluidHandler; +import de.srendi.advancedperipherals.common.util.inventory.StorageProcessor; import net.neoforged.neoforge.fluids.FluidStack; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * Used to transfer item between an inventory and the ME system. * @@ -30,21 +33,39 @@ public MEFluidHandler(@NotNull MEStorage storageMonitor, @NotNull IActionSource @Override public int fill(FluidStack resource, FluidAction action) { - if (resource.isEmpty()) + if (resource.isEmpty()) { return 0; + } AEFluidKey itemKey = AEFluidKey.of(resource.getFluid()); - long inserted = storageMonitor.insert(itemKey, resource.getAmount(), action == FluidAction.SIMULATE ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); - - return (int) Math.min(inserted, Integer.MAX_VALUE); + // should never overflow + return (int) (storageMonitor.insert(itemKey, resource.getAmount(), action.simulate() ? Actionable.SIMULATE : Actionable.MODULATE, actionSource)); } - @NotNull @Override - public FluidStack drain(FluidFilter filter, FluidAction simulate) { - Pair fluidKey = AEApi.findAEFluidFromFilter(storageMonitor, null, filter); - if (fluidKey.getRight() == null) - return FluidStack.EMPTY; - long extracted = storageMonitor.extract(fluidKey.getRight(), filter.getCount(), simulate == FluidAction.SIMULATE ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); - return new FluidStack(fluidKey.getRight().getFluid(), (int) Math.min(extracted, Integer.MAX_VALUE)); + public int extractFluids(FluidFilter filter, StorageProcessor processor, FluidAction action) { + List> fluidKeys = AEApi.findAEFluidsFromFilter(storageMonitor, filter); + if (fluidKeys.isEmpty()) { + return 0; + } + int needs = filter.getAmount(); + for (Pair pair : fluidKeys) { + AEFluidKey fluidKey = pair.right(); + int amount = (int) storageMonitor.extract(fluidKey, needs, Actionable.SIMULATE, actionSource); + if (amount == 0) { + continue; + } + int extracted = processor.process(new FluidStack(fluidKey.getFluid(), amount)); + if (extracted == 0) { + continue; + } + needs -= extracted; + if (action.execute()) { + storageMonitor.extract(fluidKey, extracted, Actionable.MODULATE, actionSource); + } + if (needs <= 0) { + break; + } + } + return filter.getAmount() - needs; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEItemHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEItemHandler.java index bc34d07f4..f6f03d0cb 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEItemHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MEItemHandler.java @@ -8,9 +8,12 @@ import de.srendi.advancedperipherals.common.util.Pair; import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemItemHandler; import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; +import de.srendi.advancedperipherals.common.util.inventory.StorageProcessor; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * Used to transfer item between an inventory and the ME system. * @@ -30,25 +33,38 @@ public MEItemHandler(@NotNull MEStorage storageMonitor, @NotNull IActionSource a @NotNull @Override - public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + public ItemStack insertItem(@NotNull ItemStack stack, boolean simulate) { AEItemKey itemKey = AEItemKey.of(stack); long inserted = storageMonitor.insert(itemKey, stack.getCount(), simulate ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); - ItemStack insertedStack = stack.copy(); // Safe to cast here, the amount will never be higher than 64 - insertedStack.setCount(insertedStack.getCount() - (int) inserted); - return insertedStack; + return stack.copyWithCount(stack.getCount() - (int) inserted); } @Override - public ItemStack extractItem(ItemFilter filter, int count, boolean simulate) { - Pair itemKey = AEApi.findAEStackFromFilter(storageMonitor, null, filter); - if (itemKey.getRight() == null) - return ItemStack.EMPTY; - long extracted = storageMonitor.extract(itemKey.getRight(), count, simulate ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); - // Safe to cast here, the amount will never be higher than 64 - ItemStack stack = itemKey.getRight().toStack(); - stack.setCount((int) extracted); - return stack; + public int extractItems(ItemFilter filter, StorageProcessor processor, boolean simulate) { + List> itemKeys = AEApi.findAEStacksFromFilter(storageMonitor, filter); + if (itemKeys.isEmpty()) { + return 0; + } + int needs = filter.getCount(); + for (Pair pair : itemKeys) { + AEItemKey itemKey = pair.right(); + int count = (int) storageMonitor.extract(itemKey, needs, Actionable.SIMULATE, actionSource); + if (count == 0) { + continue; + } + int extracted = processor.process(itemKey.toStack().copyWithCount(count)); + if (extracted == 0) { + continue; + } + needs -= extracted; + if (!simulate) { + storageMonitor.extract(itemKey, extracted, Actionable.MODULATE, actionSource); + } + if (needs <= 0) { + break; + } + } + return filter.getCount() - needs; } - } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MEBridgePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MEBridgePeripheral.java index 6580dd5a6..c97aace58 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MEBridgePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MEBridgePeripheral.java @@ -732,7 +732,7 @@ public final MethodResult craftFluid(IComputerAccess computer, IArguments argume if (stack.getRight() == null && stack.getLeft() == 0) return MethodResult.of(false, StatusConstants.NOT_CRAFTABLE.toString()); - AECraftJob job = new AECraftJob(owner.getLevel(), computer, node, stack.getRight(), parsedFilter.getCount(), bridge, target); + AECraftJob job = new AECraftJob(owner.getLevel(), computer, node, stack.getRight(), parsedFilter.getAmount(), bridge, target); bridge.addJob(job); return MethodResult.of(job.withCPU(target)); } @@ -763,7 +763,7 @@ public MethodResult craftChemical(IComputerAccess computer, IArguments arguments if (stack.getRight() == null && stack.getLeft() == 0) return MethodResult.of(false, StatusConstants.NOT_CRAFTABLE.toString()); - AECraftJob job = new AECraftJob(owner.getLevel(), computer, node, stack.getRight(), parsedFilter.getCount(), bridge, target); + AECraftJob job = new AECraftJob(owner.getLevel(), computer, node, stack.getRight(), parsedFilter.getAmount(), bridge, target); bridge.addJob(job); return MethodResult.of(job.withCPU(target)); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RSBridgePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RSBridgePeripheral.java index 2b027ad3c..6220e10a8 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RSBridgePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RSBridgePeripheral.java @@ -710,7 +710,7 @@ public final MethodResult craftFluid(IComputerAccess computer, IArguments argume if (filter.rightPresent()) return MethodResult.of(null, filter.getRight()); - RSCraftJob job = new RSCraftJob(computer, getLevel(), filter.getLeft().getCount(), VariantUtil.ofFluidStack(filter.getLeft().toFluidStack()), getNetwork().getComponent(AutocraftingNetworkComponent.class)); + RSCraftJob job = new RSCraftJob(computer, getLevel(), filter.getLeft().getAmount(), VariantUtil.ofFluidStack(filter.getLeft().toFluidStack()), getNetwork().getComponent(AutocraftingNetworkComponent.class)); bridge.addJob(job); return MethodResult.of(job); } @@ -728,7 +728,7 @@ public final MethodResult craftChemical(IComputerAccess computer, IArguments arg if (filter.rightPresent()) return MethodResult.of(null, filter.getRight()); - RSCraftJob job = new RSCraftJob(computer, getLevel(), filter.getLeft().getCount(), ChemicalResource.ofChemicalStack(filter.getLeft().toChemicalStack()), getNetwork().getComponent(AutocraftingNetworkComponent.class)); + RSCraftJob job = new RSCraftJob(computer, getLevel(), filter.getLeft().getAmount(), ChemicalResource.ofChemicalStack(filter.getLeft().toChemicalStack()), getNetwork().getComponent(AutocraftingNetworkComponent.class)); bridge.addJob(job); return MethodResult.of(job); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSApi.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSApi.java index 59307eb42..07b82091c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSApi.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSApi.java @@ -86,6 +86,17 @@ public static ItemResource getItem(Network network, ItemFilter filter) { return null; } + public static List getItems(Network network, ItemFilter filter) { + List items = new ArrayList<>(); + StorageNetworkComponent storage = network.getComponent(StorageNetworkComponent.class); + for (ResourceAmount resourceAmount : storage.getAll()) { + if (resourceAmount.resource() instanceof ItemResource itemResource && filter.test(itemResource.toItemStack())) { + items.add(itemResource); + } + } + return items; + } + /** * Returns the first fluid parsed to a lua object which fits to the filter * @@ -104,6 +115,17 @@ public static FluidResource getFluid(Network network, FluidFilter filter) { return null; } + public static List getFluids(Network network, FluidFilter filter) { + List fluids = new ArrayList<>(); + StorageNetworkComponent storage = network.getComponent(StorageNetworkComponent.class); + for (ResourceAmount resourceAmount : storage.getAll()) { + if (resourceAmount.resource() instanceof FluidResource fluidResource && filter.test(VariantUtil.toFluidStack(fluidResource, resourceAmount.amount()))) { + fluids.add(fluidResource); + } + } + return fluids; + } + /** * Returns the first chemical parsed to a lua object which fits to the filter * @@ -122,6 +144,17 @@ public static ChemicalResource getChemical(Network network, ChemicalFilter filte return null; } + public static List getChemicals(Network network, ChemicalFilter filter) { + List chemicals = new ArrayList<>(); + StorageNetworkComponent storage = network.getComponent(StorageNetworkComponent.class); + for (ResourceAmount resourceAmount : storage.getAll()) { + if (resourceAmount.resource() instanceof ChemicalResource chemicalResource && filter.test(ChemicalUtil.toChemicalStack(chemicalResource.chemical(), resourceAmount.amount()))) { + chemicals.add(chemicalResource); + } + } + return chemicals; + } + /** * Returns the first item parsed to a lua object which fits to the filter * diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSChemicalHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSChemicalHandler.java index 5d287837e..70bfe4a46 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSChemicalHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSChemicalHandler.java @@ -5,13 +5,15 @@ import com.refinedmods.refinedstorage.api.network.storage.StorageNetworkComponent; import com.refinedmods.refinedstorage.api.storage.Actor; import com.refinedmods.refinedstorage.mekanism.ChemicalResource; -import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.util.inventory.ChemicalFilter; import de.srendi.advancedperipherals.common.util.inventory.ChemicalUtil; import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemChemicalHandler; +import de.srendi.advancedperipherals.common.util.inventory.StorageProcessor; import mekanism.api.chemical.ChemicalStack; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class RSChemicalHandler implements IStorageSystemChemicalHandler { @NotNull @@ -25,27 +27,40 @@ public RSChemicalHandler(@NotNull Network network) { @NotNull @Override - public ChemicalStack insertChemical(int tank, ChemicalStack resource, @NotNull mekanism.api.Action action) { + public ChemicalStack insertChemical(ChemicalStack resource, @NotNull mekanism.api.Action action) { if (resource.isEmpty()) return resource; - long amountInserted = component.insert(ChemicalResource.ofChemicalStack(resource), resource.getAmount(), action == mekanism.api.Action.SIMULATE ? Action.SIMULATE : Action.EXECUTE, Actor.EMPTY); + long amountInserted = component.insert(ChemicalResource.ofChemicalStack(resource), resource.getAmount(), action.simulate() ? Action.SIMULATE : Action.EXECUTE, Actor.EMPTY); ChemicalStack remain = resource.copyWithAmount(resource.getAmount() - amountInserted); return remain; } @Override - public ChemicalStack extractChemical(ChemicalFilter filter, long count, mekanism.api.Action simulate) { - AdvancedPeripherals.debug("Trying to extract chemical from filter: " + filter); - ChemicalResource chemical = RSApi.getChemical(network, filter); - if (chemical == null) - return ChemicalStack.EMPTY; - - long amountExtracted = component.extract(chemical, filter.getCount(), simulate == mekanism.api.Action.SIMULATE ? Action.SIMULATE : Action.EXECUTE, Actor.EMPTY); - ChemicalStack extracted = ChemicalUtil.toChemicalStack(chemical.chemical(), amountExtracted); + public long extractChemicals(ChemicalFilter filter, StorageProcessor.Large processor, mekanism.api.Action action) { + List chemicals = RSApi.getChemicals(network, filter); + if (chemicals.isEmpty()) { + return 0; + } - AdvancedPeripherals.debug("Extracted chemical: " + extracted + " from filter: " + filter); - return extracted; + long needs = filter.getAmount(); + for (ChemicalResource chemical : chemicals) { + long amount = component.extract(chemical, needs, Action.SIMULATE, Actor.EMPTY); + if (amount == 0) { + continue; + } + long extracted = processor.process(ChemicalUtil.toChemicalStack(chemical.chemical(), amount)); + if (extracted == 0) { + continue; + } + needs -= extracted; + if (action.execute()) { + component.extract(chemical, extracted, Action.EXECUTE, Actor.EMPTY);; + } + if (needs <= 0) { + break; + } + } + return filter.getAmount() - needs; } - } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSFluidHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSFluidHandler.java index e0fb3362e..15d76ae3d 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSFluidHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSFluidHandler.java @@ -6,12 +6,14 @@ import com.refinedmods.refinedstorage.api.storage.Actor; import com.refinedmods.refinedstorage.common.support.resource.FluidResource; import com.refinedmods.refinedstorage.neoforge.support.resource.VariantUtil; -import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemFluidHandler; +import de.srendi.advancedperipherals.common.util.inventory.StorageProcessor; import net.neoforged.neoforge.fluids.FluidStack; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class RSFluidHandler implements IStorageSystemFluidHandler { @NotNull @@ -25,24 +27,37 @@ public RSFluidHandler(@NotNull Network network) { @Override public int fill(FluidStack resource, @NotNull FluidAction action) { - if (resource.isEmpty()) + if (resource.isEmpty()) { return 0; - long inserted = component.insert(VariantUtil.ofFluidStack(resource), resource.getAmount(), action == FluidAction.SIMULATE ? Action.SIMULATE : Action.EXECUTE, Actor.EMPTY); - return (int) (resource.getAmount() - inserted); + } + // should never overflow + return (int) (component.insert(VariantUtil.ofFluidStack(resource), resource.getAmount(), action.simulate() ? Action.SIMULATE : Action.EXECUTE, Actor.EMPTY)); } - @NotNull @Override - public FluidStack drain(FluidFilter filter, FluidAction simulate) { - AdvancedPeripherals.debug("Trying to extract fluid from filter: " + filter); - FluidResource fluid = RSApi.getFluid(network, filter); - if (fluid == null) - return FluidStack.EMPTY; - - long amountExtracted = component.extract(fluid, filter.getCount(), simulate == FluidAction.SIMULATE ? Action.SIMULATE : Action.EXECUTE, Actor.EMPTY); - FluidStack extracted = VariantUtil.toFluidStack(fluid, (int) amountExtracted); - - AdvancedPeripherals.debug("Extracted fluid: " + extracted + " from filter: " + filter); - return extracted; + public int extractFluids(FluidFilter filter, StorageProcessor processor, FluidAction action) { + List fluids = RSApi.getFluids(network, filter); + if (fluids.isEmpty()) { + return 0; + } + int needs = filter.getAmount(); + for (FluidResource fluid : fluids) { + int amount = (int) component.extract(fluid, needs, Action.SIMULATE, Actor.EMPTY); + if (amount == 0) { + continue; + } + int extracted = processor.process(VariantUtil.toFluidStack(fluid, amount)); + if (extracted == 0) { + continue; + } + needs -= extracted; + if (action.execute()) { + component.extract(fluid, extracted, Action.EXECUTE, Actor.EMPTY);; + } + if (needs <= 0) { + break; + } + } + return filter.getAmount() - needs; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSItemHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSItemHandler.java index 7753a3701..3cabea48d 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSItemHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSItemHandler.java @@ -4,13 +4,15 @@ import com.refinedmods.refinedstorage.api.network.storage.StorageNetworkComponent; import com.refinedmods.refinedstorage.api.storage.Actor; import com.refinedmods.refinedstorage.common.support.resource.ItemResource; -import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemItemHandler; import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; +import de.srendi.advancedperipherals.common.util.inventory.StorageProcessor; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.NotNull; import com.refinedmods.refinedstorage.api.core.Action; +import java.util.List; + /** * Used to transfer item between an inventory and the RS system. * @@ -29,24 +31,36 @@ public RSItemHandler(@NotNull Network network) { @NotNull @Override - public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + public ItemStack insertItem(@NotNull ItemStack stack, boolean simulate) { long insertedAmount = component.insert(ItemResource.ofItemStack(stack), stack.getCount(), simulate ? Action.SIMULATE : Action.EXECUTE, Actor.EMPTY); ItemStack remain = stack.copyWithCount((int) (stack.getCount() - insertedAmount)); return remain; } @Override - public ItemStack extractItem(ItemFilter filter, int count, boolean simulate) { - AdvancedPeripherals.debug("Trying to extract item from filter: " + filter); - ItemResource itemResource = RSApi.getItem(network, filter); - if (itemResource == null) - return ItemStack.EMPTY; - - long extractedAmount = component.extract(itemResource, count, simulate ? Action.SIMULATE : Action.EXECUTE, Actor.EMPTY); - ItemStack extracted = itemResource.toItemStack(extractedAmount); - - AdvancedPeripherals.debug("Extracted item: " + extracted + " from filter: " + filter); - return extracted; + public int extractItems(ItemFilter filter, StorageProcessor processor, boolean simulate) { + List items = RSApi.getItems(network, filter); + if (items.isEmpty()) { + return 0; + } + int needs = filter.getCount(); + for (ItemResource itemResource : items) { + int amount = (int) component.extract(itemResource, needs, Action.SIMULATE, Actor.EMPTY); + if (amount == 0) { + continue; + } + int extracted = processor.process(itemResource.toItemStack(amount)); + if (extracted == 0) { + continue; + } + needs -= extracted; + if (!simulate) { + component.extract(itemResource, extracted, Action.EXECUTE, Actor.EMPTY); + } + if (needs <= 0) { + break; + } + } + return filter.getCount() - needs; } - } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/Pair.java b/src/main/java/de/srendi/advancedperipherals/common/util/Pair.java index 46398d900..486f52b43 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/Pair.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/Pair.java @@ -4,15 +4,7 @@ import java.util.function.Consumer; import java.util.function.Function; -public class Pair { - private final T left; - private final V right; - - public Pair(T left, V right) { - this.left = left; - this.right = right; - } - +public record Pair(T left, V right) { public static Pair onlyRight(V right) { return new Pair<>(null, right); } @@ -25,10 +17,12 @@ public static Pair of(T left, V right) { return new Pair<>(left, right); } + // TODO: replace by left() in 0.8 public T getLeft() { return left; } + // TODO: replace by right() in 0.8 public V getRight() { return right; } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ChemicalFilter.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ChemicalFilter.java index f6abe65fb..58ec04d3c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ChemicalFilter.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ChemicalFilter.java @@ -22,7 +22,7 @@ public class ChemicalFilter extends GenericFilter { private Holder chemical = MekanismAPI.EMPTY_CHEMICAL.getAsHolder(); private TagKey tag = null; - private long count = 1000; + private long amount = 1000; private String fingerprint = ""; public int fromSlot = -1; public int toSlot = -1; @@ -30,7 +30,7 @@ public class ChemicalFilter extends GenericFilter { private ChemicalFilter() { } - public static Pair parse(LuaTable item) { + public static Pair parse(LuaTable item) throws LuaException { // If the map is empty, return a filter without any filters if (item.isEmpty()) return Pair.of(EMPTY, null); @@ -38,44 +38,27 @@ public static Pair parse(LuaTable item) { ChemicalFilter chemicalFilter = createEmpty(); if (item.containsKey("name")) { - try { - String name = item.getString("name"); - if (name.startsWith("#")) { - chemicalFilter.tag = TagKey.create(MekanismAPI.CHEMICAL_REGISTRY_NAME, ResourceLocation.parse(name.substring(1))); - } else if ((chemicalFilter.chemical = MekanismAPI.CHEMICAL_REGISTRY.getHolder(ResourceLocation.parse(name)).orElse(null)) == null) { - return Pair.of(null, "CHEMICAL_NOT_FOUND"); - } - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_ITEM"); + String name = item.getString("name"); + if (name.startsWith("#")) { + chemicalFilter.tag = TagKey.create(MekanismAPI.CHEMICAL_REGISTRY_NAME, ResourceLocation.parse(name.substring(1))); + } else if ((chemicalFilter.chemical = MekanismAPI.CHEMICAL_REGISTRY.getHolder(ResourceLocation.parse(name)).orElse(null)) == null) { + return Pair.of(null, "CHEMICAL_NOT_FOUND"); } } if (item.containsKey("fingerprint")) { - try { - chemicalFilter.fingerprint = item.getString("fingerprint"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_FINGERPRINT"); - } + chemicalFilter.fingerprint = item.getString("fingerprint"); } if (item.containsKey("fromSlot")) { - try { - chemicalFilter.fromSlot = item.getInt( "fromSlot"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_FROMSLOT"); - } + chemicalFilter.fromSlot = item.getInt("fromSlot"); } if (item.containsKey("toSlot")) { - try { - chemicalFilter.toSlot = item.getInt( "toSlot"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_TOSLOT"); - } + chemicalFilter.toSlot = item.getInt("toSlot"); } - if (item.containsKey("count")) { - try { - chemicalFilter.count = item.getInt( "count"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_COUNT"); - } + // TODO: rename count to amount in 0.8 + if (item.containsKey("amount")) { + chemicalFilter.amount = item.getLong("amount"); + } else if (item.containsKey("count")) { + chemicalFilter.amount = item.getLong("count"); } AdvancedPeripherals.debug("Parsed item filter: " + chemicalFilter); @@ -83,8 +66,13 @@ public static Pair parse(LuaTable item) { } public static ChemicalFilter fromStack(ChemicalStack stack) { + return fromStackWithAmount(stack, stack.getAmount()); + } + + public static ChemicalFilter fromStackWithAmount(ChemicalStack stack, long amount) { ChemicalFilter filter = createEmpty(); filter.chemical = stack.getChemicalHolder(); + filter.amount = amount; return filter; } @@ -111,8 +99,26 @@ public boolean testRS(ResourceAmount resourceAmount) { return false; } + @Override + public ChemicalFilter copy() { + ChemicalFilter newFilter = new ChemicalFilter(); + newFilter.chemical = this.chemical; + newFilter.tag = this.tag; + newFilter.amount = this.amount; + newFilter.fingerprint = this.fingerprint; + newFilter.fromSlot = this.fromSlot; + newFilter.toSlot = this.toSlot; + return newFilter; + } + + public ChemicalFilter copyWithAmount(long amount) { + ChemicalFilter newFilter = this.copy(); + newFilter.amount = amount; + return newFilter; + } + public ChemicalStack toChemicalStack() { - return new ChemicalStack(chemical, count); + return new ChemicalStack(chemical, amount); } public boolean test(ChemicalStack stack) { @@ -134,8 +140,8 @@ public boolean test(ChemicalStack stack) { return true; } - public long getCount() { - return count; + public long getAmount() { + return amount; } public Holder getChemical() { @@ -155,7 +161,7 @@ public String toString() { return "ChemicalFilter{" + "item=" + chemical.getRegisteredName() + ", tag=" + tag + - ", count=" + count + + ", amount=" + amount + ", fingerprint='" + fingerprint + '\'' + ", fromSlot=" + fromSlot + ", toSlot=" + toSlot + diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ChemicalUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ChemicalUtil.java index 962187060..3abd901e2 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ChemicalUtil.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ChemicalUtil.java @@ -21,67 +21,73 @@ import org.jetbrains.annotations.Nullable; import java.util.Objects; +import java.util.stream.IntStream; public class ChemicalUtil { public static long moveChemical(IChemicalHandler inventoryFrom, IChemicalHandler inventoryTo, ChemicalFilter filter) { - if (inventoryFrom == null) return 0; + if (inventoryFrom == null) { + return 0; + } - long amount = filter.getCount(); - long transferableAmount = 0; + int fromSlot = filter.getFromSlot(); + int toSlot = filter.getToSlot(); - // The logic changes with storage systems since these systems do not have slots - if (inventoryFrom instanceof IStorageSystemChemicalHandler storageSystemHandler) { - ChemicalStack extracted = storageSystemHandler.extractChemical(filter, amount, Action.SIMULATE); - amount = Math.min(amount, extracted.getAmount()); - if (amount > 0) { - ChemicalStack remaining; - int toSlot = filter.getToSlot(); - if (toSlot >= 0) { - remaining = inventoryTo.insertChemical(toSlot, extracted, Action.EXECUTE); - } else { - remaining = inventoryTo.insertChemical(extracted, Action.EXECUTE); - } - amount -= remaining.getAmount(); - } - if (amount > 0) { - transferableAmount += storageSystemHandler.extractChemical(filter, amount, Action.EXECUTE).getAmount(); - } - return transferableAmount; + if (!(inventoryFrom instanceof IStorageSystemChemicalHandler) && fromSlot >= inventoryFrom.getChemicalTanks()) { + return 0; + } + if (!(inventoryTo instanceof IStorageSystemChemicalHandler) && toSlot >= inventoryTo.getChemicalTanks()) { + return 0; } - if (inventoryTo instanceof IStorageSystemChemicalHandler storageSystemHandler) { - int fromSlot = filter.getFromSlot(); - if (fromSlot >= 0) { - transferableAmount = importChemical(inventoryFrom, filter, storageSystemHandler, amount, fromSlot); - } else { - int tanks = inventoryFrom.getChemicalTanks(); - for (int i = 0; amount > 0 && i < tanks; i++) { - long imported = importChemical(inventoryFrom, filter, storageSystemHandler, amount, i); - transferableAmount += imported; - amount -= imported; - } - } - return transferableAmount; + long needs = filter.getAmount(); + if (needs <= 0) { + return 0; } - return transferableAmount; - } + ChemicalInserter inserter = inventoryTo instanceof IStorageSystemChemicalHandler storageTo + ? (stack) -> storageTo.insertChemical(stack, Action.EXECUTE) + : toSlot < 0 + ? (stack) -> inventoryTo.insertChemical(stack, Action.EXECUTE) + : (stack) -> inventoryTo.insertChemical(toSlot, stack, Action.EXECUTE); + + // The logic changes with storage systems since these systems do not have slots + if (inventoryFrom instanceof IStorageSystemChemicalHandler storageFrom) { + return storageFrom.extractChemicals( + filter, + (extracted) -> extracted.getAmount() - inserter.insertChemical(extracted).getAmount(), + Action.EXECUTE + ); + } + + int[] fromSlots = ( + fromSlot >= 0 + ? IntStream.of(fromSlot) + : IntStream.range(0, inventoryFrom.getChemicalTanks()) + ) + .filter((i) -> filter.test(inventoryFrom.getChemicalInTank(i))) + .toArray(); + if (fromSlots.length == 0) { + return 0; + } - private static long importChemical(IChemicalHandler inventoryFrom, ChemicalFilter filter, IStorageSystemChemicalHandler storageSystemHandler, long amount, int tank) { - long transferableAmount = 0; - ChemicalStack chemicalInTank = inventoryFrom.getChemicalInTank(tank); - if (filter.test(chemicalInTank)) { - ChemicalStack extracted = inventoryFrom.extractChemical(tank, amount, Action.SIMULATE); - if (!extracted.isEmpty()) { - long remaining = storageSystemHandler.insertChemical(extracted, Action.EXECUTE).getAmount(); - long extracting = extracted.getAmount() - remaining; - if (extracting > 0) { - transferableAmount += inventoryFrom.extractChemical(tank, extracting, Action.EXECUTE).getAmount(); - } + for (int i : fromSlots) { + ChemicalStack extracted = inventoryFrom.extractChemical(i, needs, Action.SIMULATE); + if (extracted.isEmpty()) { + continue; + } + ChemicalStack remaining = inserter.insertChemical(extracted); + long inserted = extracted.getAmount() - remaining.getAmount(); + if (inserted == 0) { + continue; + } + needs -= inserted; + inventoryFrom.extractChemical(i, inserted, Action.SIMULATE); + if (needs <= 0) { + break; } } - return transferableAmount; + return filter.getAmount() - needs; } public static IChemicalHandler extractHandler(@Nullable Object object, @Nullable Level level, @Nullable BlockPos pos, @Nullable Direction direction) { @@ -144,4 +150,9 @@ public static ResourceLocation getRegistryKey(Chemical chemical) { public static ResourceLocation getRegistryKey(ChemicalStack chemicalStack) { return MekanismAPI.CHEMICAL_REGISTRY.getKey(chemicalStack.getChemical()); } + + @FunctionalInterface + private interface ChemicalInserter { + ChemicalStack insertChemical(ChemicalStack stack); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidFilter.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidFilter.java index 62e82cb5b..4ca590957 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidFilter.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidFilter.java @@ -29,14 +29,14 @@ public class FluidFilter extends GenericFilter { private Fluid fluid = Fluids.EMPTY; private TagKey tag = null; private Tag componentsAsNbt = null; - private PatchedDataComponentMap components; - private int count = 1000; + private PatchedDataComponentMap components = null; + private int amount = 1000; private String fingerprint = ""; private FluidFilter() { } - public static Pair parse(LuaTable item) { + public static Pair parse(LuaTable item) throws LuaException { // If the map is empty, return a filter without any filters if (item.isEmpty()) return Pair.of(EMPTY, null); @@ -44,41 +44,35 @@ public static Pair parse(LuaTable item) { FluidFilter fluidFilter = createEmpty(); if (item.containsKey("name")) { - try { - String name = item.getString("name"); - if (name.startsWith("#")) { - fluidFilter.tag = TagKey.create(Registries.FLUID, ResourceLocation.parse(name.substring(1))); - } else if ((fluidFilter.fluid = ItemUtil.getRegistryEntry(name, BuiltInRegistries.FLUID)) == null) { + String name = item.getString("name"); + if (name.startsWith("#")) { + fluidFilter.tag = TagKey.create(Registries.FLUID, ResourceLocation.parse(name.substring(1))); + } else { + fluidFilter.fluid = ItemUtil.getRegistryEntry(name, BuiltInRegistries.FLUID); + if (fluidFilter.fluid == null) { return Pair.of(null, "FLUID_NOT_FOUND"); } - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_FLUID"); } } if (item.containsKey("components")) { try { - fluidFilter.componentsAsNbt = NBTUtil.fromText(item.getString( "components")); - } catch (LuaException luaException) { + fluidFilter.componentsAsNbt = NBTUtil.fromText(item.getString("components")); + } catch (LuaException e1) { try { fluidFilter.componentsAsNbt = NBTUtil.fromText(item.getTable("components").toString()); - } catch (LuaException e) { - return Pair.of(null, "NO_VALID_COMPONENTS"); + } catch (LuaException e2) { + throw new LuaException("bad field \"components\", expect NBT string or table"); } } } if (item.containsKey("fingerprint")) { - try { - fluidFilter.fingerprint = item.getString("fingerprint"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_FINGERPRINT"); - } + fluidFilter.fingerprint = item.getString("fingerprint"); } - if (item.containsKey("count")) { - try { - fluidFilter.count = item.getInt("count"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_COUNT"); - } + // TODO: rename count to amount in 0.8 + if (item.containsKey("amount")) { + fluidFilter.amount = item.getInt("amount"); + } else if (item.containsKey("count")) { + fluidFilter.amount = item.getInt("count"); } AdvancedPeripherals.debug("Parsed fluid filter: " + fluidFilter); @@ -86,8 +80,13 @@ public static Pair parse(LuaTable item) { } public static FluidFilter fromStack(FluidStack stack) { + return fromStackWithAmount(stack, stack.getAmount()); + } + + public static FluidFilter fromStackWithAmount(FluidStack stack, int amount) { FluidFilter filter = createEmpty(); filter.fluid = stack.getFluid(); + filter.amount = amount; filter.componentsAsNbt = DataComponentUtil.toNbt(stack.getComponentsPatch()); filter.components = stack.getComponents(); return filter; @@ -103,8 +102,9 @@ public boolean isEmpty() { @Override public boolean testAE(GenericStack genericStack) { - if (!APAddon.AE2.isLoaded()) + if (!APAddon.AE2.isLoaded()) { return false; + } if (genericStack.what() instanceof AEFluidKey aeFluidKey) { return test(aeFluidKey.toStack(1)); @@ -114,8 +114,9 @@ public boolean testAE(GenericStack genericStack) { @Override public boolean testRS(ResourceAmount resourceAmount) { - if (!APAddon.REFINEDSTORAGE.isLoaded()) + if (!APAddon.REFINEDSTORAGE.isLoaded()) { return false; + } if (resourceAmount.resource() instanceof FluidResource fluidResource) { return test(VariantUtil.toFluidStack(fluidResource, 1)); @@ -123,19 +124,32 @@ public boolean testRS(ResourceAmount resourceAmount) { return false; } + @Override + public FluidFilter copy() { + FluidFilter newFilter = new FluidFilter(); + newFilter.fluid = this.fluid; + newFilter.tag = this.tag; + newFilter.componentsAsNbt = this.componentsAsNbt; + newFilter.components = this.components; + newFilter.amount = this.amount; + newFilter.fingerprint = this.fingerprint; + return newFilter; + } + + public FluidFilter copyWithAmount(int amount) { + FluidFilter newFilter = this.copy(); + newFilter.amount = amount; + return newFilter; + } + public FluidStack toFluidStack() { - var result = new FluidStack(fluid, count); + FluidStack result = new FluidStack(fluid, amount); if (componentsAsNbt != null) { result.applyComponents(components); } return result; } - public FluidFilter setCount(int count) { - this.count = count; - return this; - } - public boolean test(FluidStack stack) { if (!fingerprint.isEmpty()) { String testFingerprint = FluidUtil.getFingerprint(stack); @@ -154,8 +168,8 @@ public boolean test(FluidStack stack) { return true; } - public int getCount() { - return count; + public int getAmount() { + return amount; } public Fluid getFluid() { @@ -172,7 +186,7 @@ public String toString() { "fluid=" + FluidUtil.getRegistryKey(fluid) + ", tag=" + tag + ", components=" + componentsAsNbt + - ", count=" + count + + ", amount=" + amount + ", fingerprint='" + fingerprint + '\'' + '}'; } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidUtil.java index 9463c7939..0e01b0274 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidUtil.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidUtil.java @@ -27,38 +27,43 @@ private FluidUtil() { } public static int moveFluid(IFluidHandler inventoryFrom, IFluidHandler inventoryTo, FluidFilter filter) { - if (inventoryFrom == null) return 0; + if (inventoryFrom == null) { + return 0; + } - int amount = filter.getCount(); - int transferableAmount = 0; + int needs = filter.getAmount(); + if (needs <= 0) { + return 0; + } // The logic changes with storage systems since these systems do not have slots - if (inventoryFrom instanceof IStorageSystemFluidHandler storageSystemHandler) { - FluidStack extracted = storageSystemHandler.drain(filter, IFluidHandler.FluidAction.SIMULATE); - int inserted = inventoryTo.fill(extracted, IFluidHandler.FluidAction.EXECUTE); - - transferableAmount += storageSystemHandler.drain(filter.setCount(inserted), IFluidHandler.FluidAction.EXECUTE).getAmount(); - - return transferableAmount; + if (inventoryFrom instanceof IStorageSystemFluidHandler storageFrom) { + return storageFrom.extractFluids( + filter, + (extracted) -> inventoryTo.fill(extracted, IFluidHandler.FluidAction.EXECUTE), + IFluidHandler.FluidAction.EXECUTE + ); } - if (inventoryTo instanceof IStorageSystemFluidHandler storageSystemHandler) { - if (filter.test(inventoryFrom.getFluidInTank(0))) { - FluidStack toExtract = inventoryFrom.getFluidInTank(0).copy(); - toExtract.setAmount(amount); - FluidStack extracted = inventoryFrom.drain(toExtract, IFluidHandler.FluidAction.SIMULATE); - if (extracted.isEmpty()) - return 0; - int inserted = storageSystemHandler.fill(extracted, IFluidHandler.FluidAction.EXECUTE); - - extracted.setAmount(inserted); - transferableAmount += inventoryFrom.drain(extracted, IFluidHandler.FluidAction.EXECUTE).getAmount(); + for (int i = 0; i < inventoryFrom.getTanks() && needs >= 0; i++) { + FluidStack stack = inventoryFrom.getFluidInTank(i); + if (!filter.test(stack)) { + continue; } - - return transferableAmount; + FluidStack extracted = inventoryFrom.drain(stack.copyWithAmount(needs), IFluidHandler.FluidAction.SIMULATE); + if (extracted.isEmpty()) { + continue; + } + int inserted = inventoryTo.fill(extracted, IFluidHandler.FluidAction.EXECUTE); + if (inserted == 0) { + continue; + } + needs -= inserted; + extracted.setAmount(inserted); + inventoryFrom.drain(extracted, IFluidHandler.FluidAction.EXECUTE); } - return transferableAmount; + return filter.getAmount() - needs; } public static IFluidHandler extractHandler(@Nullable Object object, @Nullable Level level, @Nullable BlockPos pos, @Nullable Direction direction) { @@ -76,8 +81,7 @@ public static IFluidHandler extractHandler(@Nullable Object object, @Nullable Le @Nullable public static IFluidHandler getHandlerFromDirection(@NotNull String direction, @NotNull IPeripheralOwner owner) throws LuaException { - Level level = owner.getLevel(); - Objects.requireNonNull(level); + Level level = Objects.requireNonNull(owner.getLevel()); Direction relativeDirection = CoordUtil.getDirection(owner.getOrientation(), direction); if (relativeDirection == null) return null; @@ -115,6 +119,6 @@ public static ResourceLocation getRegistryKey(Fluid fluid) { } public static ResourceLocation getRegistryKey(FluidStack fluid) { - return BuiltInRegistries.FLUID.getKey(fluid.copy().getFluid()); + return BuiltInRegistries.FLUID.getKey(fluid.getFluid()); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/GenericFilter.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/GenericFilter.java index fb2732029..cdd9a8432 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/GenericFilter.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/GenericFilter.java @@ -2,6 +2,7 @@ import appeng.api.stacks.GenericStack; import com.refinedmods.refinedstorage.api.resource.ResourceAmount; +import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaTable; import de.srendi.advancedperipherals.common.addons.APAddon; import de.srendi.advancedperipherals.common.addons.mekanism.Mekanism; @@ -10,7 +11,7 @@ public abstract class GenericFilter { - private static final GenericFilter EMPTY = new GenericFilter<>() { + private static final GenericFilter EMPTY = new GenericFilter() { @Override public boolean isEmpty() { return true; @@ -30,8 +31,17 @@ public boolean testRS(ResourceAmount resourceAmount) { public boolean test(Object toTest) { return false; } + + @Override + public GenericFilter copy() { + return this; + } }; + public static GenericFilter empty() { + return (GenericFilter) EMPTY; + } + /** * Try to parse a raw filter table to any existing filter type. Could be a fluid filter, an item filter, maybe something else * in the future. @@ -41,33 +51,40 @@ public boolean test(Object toTest) { * * @param rawFilter The raw filter, which is a map of strings and objects * @return A pair of the parsed filter and an error message, if there is one + * @throws LuaException If the filter table has incorrect format */ - public static Pair, String> parseGeneric(LuaTable rawFilter) { - - if (rawFilter.containsKey("type") && rawFilter.get("type") instanceof String type) { - if (type.equals("item")) - return ItemFilter.parse(rawFilter); - if (type.equals("fluid")) - return FluidFilter.parse(rawFilter); - if (type.equals("chemical") && APAddon.MEKANISM.isLoaded()) - return ChemicalFilter.parse(rawFilter); + public static Pair, String> parseGeneric(LuaTable rawFilter) throws LuaException { + if (rawFilter.containsKey("type")) { + String type = rawFilter.getString("type"); + return switch (type) { + case "item" -> ItemFilter.parse(rawFilter); + case "fluid" -> FluidFilter.parse(rawFilter); + case "chemical" -> { + if (!APAddon.MEKANISM.isLoaded()) { + throw new LuaException("cannot use chemical filter: Mekanism is required"); + } + yield ChemicalFilter.parse(rawFilter); + } + default -> throw new LuaException("unexpected filter type " + type); + }; } if (!rawFilter.containsKey("name")) - return Pair.of(empty(), "NO_NAME_OR_TYPE"); + throw new LuaException("Generic filter requires either field \"type\" or \"name\""); - String name = rawFilter.get("name").toString(); + String name = rawFilter.getString("name"); // Let's check in which registry this thing is if (ItemUtil.getRegistryEntry(name, BuiltInRegistries.ITEM) != null) { return ItemFilter.parse(rawFilter); - } else if (ItemUtil.getRegistryEntry(name, BuiltInRegistries.FLUID) != null) { + } + if (ItemUtil.getRegistryEntry(name, BuiltInRegistries.FLUID) != null) { return FluidFilter.parse(rawFilter); - } else if (APAddon.MEKANISM.isLoaded() && ItemUtil.getRegistryEntry(name, Mekanism.getChemicalRegistry()) != null) { + } + if (APAddon.MEKANISM.isLoaded() && ItemUtil.getRegistryEntry(name, Mekanism.getChemicalRegistry()) != null) { return ChemicalFilter.parse(rawFilter); - } else { - // If the name is in neither of the registries, we will just return an empty filter - return Pair.of(empty(), "NO_VALID_FILTER_TYPE"); } + // If the name is in neither of the registries, we will just return an empty filter + return Pair.of(empty(), "NO_VALID_FILTER_TYPE"); } public abstract boolean isEmpty(); @@ -80,8 +97,5 @@ public static Pair, String> parseGeneric(LuaTable empty() { - return EMPTY; - } - + public abstract GenericFilter copy(); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemChemicalHandler.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemChemicalHandler.java index a87de0b8a..548817e61 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemChemicalHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemChemicalHandler.java @@ -12,11 +12,11 @@ public interface IStorageSystemChemicalHandler extends IChemicalHandler { * stack sizes greater than 64. * * @param filter The parsed filter - * @param count The amount to extract + * @param processor The extractation processor * @param simulate Should this action be simulated - * @return extracted from the slot, must be empty if nothing can be extracted. The returned ItemStack can be safely modified after, so item handlers should return a new or copied stack. + * @return extracted chemical amount */ - ChemicalStack extractChemical(ChemicalFilter filter, long count, Action simulate); + long extractChemicals(ChemicalFilter filter, StorageProcessor.Large processor, Action action); @Override default int getChemicalTanks() { @@ -30,27 +30,35 @@ default long getChemicalTankCapacity(int tank) { @Override default ChemicalStack getChemicalInTank(int tank) { - return ChemicalStack.EMPTY; + throw new UnsupportedOperationException(); + } + + @Override + ChemicalStack insertChemical(ChemicalStack resource, Action action); + + @Override + default ChemicalStack insertChemical(int tank, ChemicalStack resource, Action action) { + return this.insertChemical(resource, action); } @Override default ChemicalStack extractChemical(long amount, Action action) { - return ChemicalStack.EMPTY; + throw new UnsupportedOperationException(); } @Override default ChemicalStack extractChemical(ChemicalStack stack, Action action) { - return ChemicalStack.EMPTY; + throw new UnsupportedOperationException(); } @Override default ChemicalStack extractChemical(int tank, long amount, Action action) { - return ChemicalStack.EMPTY; + throw new UnsupportedOperationException(); } @Override default void setChemicalInTank(int tank, ChemicalStack stack) { - + throw new UnsupportedOperationException(); } @Override diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemFluidHandler.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemFluidHandler.java index 183f3e9fd..58e090cd9 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemFluidHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemFluidHandler.java @@ -9,53 +9,52 @@ public interface IStorageSystemFluidHandler extends IFluidHandler { /** * Used to extract an item from the system via a peripheral. - * Uses a filter to find the right item. The amount should never be greater than 64 - * stack sizes greater than 64. + * Uses a filter to find the right item. * * @param filter The parsed filter + * @param processor The extractation processor * @param simulate Should this action be simulated - * @return extracted from the slot, must be empty if nothing can be extracted. The returned ItemStack can be safely modified after, so item handlers should return a new or copied stack. + * @return extracted fluid amount */ - @NotNull - FluidStack drain(FluidFilter filter, FluidAction simulate); + int extractFluids(FluidFilter filter, StorageProcessor processor, FluidAction action); @Override default int getTanks() { return 1; } - /* - These 5 methods are ignored in our transferring logic. Storage Systems do not respect tanks directly and to extract we need a filter + /** + * These 5 methods below are ignored in our transferring logic. + * Storage Systems do not respect tanks directly and to extract we need a filter */ @NotNull @Override default FluidStack drain(int maxDrain, FluidAction action) { - return FluidStack.EMPTY; - + throw new UnsupportedOperationException(); } @NotNull @Override default FluidStack drain(FluidStack resource, FluidAction action) { - return FluidStack.EMPTY; + throw new UnsupportedOperationException(); } @NotNull @Override default FluidStack getFluidInTank(int tank) { - return FluidStack.EMPTY; + throw new UnsupportedOperationException(); } @Override default boolean isFluidValid(int tank, @NotNull FluidStack stack) { - return false; + throw new UnsupportedOperationException(); } @Override default int getTankCapacity(int tank) { - return 0; + throw new UnsupportedOperationException(); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemItemHandler.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemItemHandler.java index 896e0c4ee..fb93c723f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemItemHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemItemHandler.java @@ -6,46 +6,54 @@ public interface IStorageSystemItemHandler extends IItemHandler { + ItemStack insertItem(ItemStack stack, boolean simulate); + /** * Used to extract an item from the system via a peripheral. * Uses a filter to find the right item. The amount should never be greater than 64 * stack sizes greater than 64. * * @param filter The parsed filter - * @param count The amount to extract + * @param processor The extractation processor * @param simulate Should this action be simulated - * @return extracted from the slot, must be empty if nothing can be extracted. The returned ItemStack can be safely modified after, so item handlers should return a new or copied stack. + * @return extracted item count */ - ItemStack extractItem(ItemFilter filter, int count, boolean simulate); + int extractItems(ItemFilter filter, StorageProcessor processor, boolean simulate); - /* - These 5 methods are ignored in our transferring logic. Storage Systems do not respect slots and to extract we need a filter + /** + * These 6 methods below are ignored in our transferring logic. + * Storage Systems do not respect slots and to extract we need a filter */ @Override default int getSlots() { - return 0; + throw new UnsupportedOperationException(); } @Override default int getSlotLimit(int slot) { - return 0; + throw new UnsupportedOperationException(); + } + + @Override + default ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + throw new UnsupportedOperationException(); } @NotNull @Override default ItemStack extractItem(int slot, int amount, boolean simulate) { - return ItemStack.EMPTY; + throw new UnsupportedOperationException(); } @NotNull @Override default ItemStack getStackInSlot(int slot) { - return ItemStack.EMPTY; + throw new UnsupportedOperationException(); } @Override default boolean isItemValid(int slot, @NotNull ItemStack stack) { - return false; + throw new UnsupportedOperationException(); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/InventoryUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/InventoryUtil.java index e8a6fb7a1..cac579e8b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/InventoryUtil.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/InventoryUtil.java @@ -19,6 +19,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Objects; +import java.util.stream.IntStream; public class InventoryUtil { @@ -26,10 +27,12 @@ private InventoryUtil() { } public static IItemHandler extractHandler(@Nullable Object object, @Nullable Level level, @Nullable BlockPos pos, @Nullable Direction direction) { - if (object instanceof IItemHandler itemHandler) + if (object instanceof IItemHandler itemHandler) { return itemHandler; - if (object instanceof Container container) + } + if (object instanceof Container container) { return new InvWrapper(container); + } if (object instanceof BlockEntity blockEntity && level == null && pos == null) { pos = blockEntity.getBlockPos(); level = blockEntity.getLevel(); @@ -41,91 +44,91 @@ public static IItemHandler extractHandler(@Nullable Object object, @Nullable Lev } public static int moveItem(IItemHandler inventoryFrom, IItemHandler inventoryTo, ItemFilter filter) { - if (inventoryFrom == null) return 0; + if (inventoryFrom == null) { + return 0; + } int fromSlot = filter.getFromSlot(); int toSlot = filter.getToSlot(); - int amount = filter.getCount(); - int transferableAmount = 0; + if (!(inventoryFrom instanceof IStorageSystemItemHandler) && fromSlot >= inventoryFrom.getSlots()) { + return 0; + } + if (!(inventoryTo instanceof IStorageSystemItemHandler) && toSlot >= inventoryTo.getSlots()) { + return 0; + } + + int needs = filter.getCount(); + if (needs <= 0) { + return 0; + } + + ItemInserter inserter = inventoryTo instanceof IStorageSystemItemHandler storageTo + ? (stack) -> storageTo.insertItem(stack, false) + : toSlot < 0 + ? (stack) -> ItemHandlerHelper.insertItem(inventoryTo, stack, false) + : (stack) -> inventoryTo.insertItem(toSlot, stack, false); // The logic changes with storage systems since these systems do not have slots - if (inventoryFrom instanceof IStorageSystemItemHandler storageSystemHandler) { - for (int i = toSlot == -1 ? 0 : toSlot; i < (toSlot == -1 ? inventoryTo.getSlots() : toSlot + 1); i++) { - ItemStack extracted = storageSystemHandler.extractItem(filter, filter.getCount(), true); - if (extracted.isEmpty()) - continue; - ItemStack inserted; - if (toSlot == -1) { - inserted = ItemHandlerHelper.insertItem(inventoryTo, extracted, false); - } else { - inserted = inventoryTo.insertItem(toSlot, extracted, false); - } - amount -= extracted.getCount() - inserted.getCount(); - transferableAmount += storageSystemHandler.extractItem(filter, extracted.getCount() - inserted.getCount(), false).getCount(); - if (transferableAmount >= filter.getCount()) - break; - } - return transferableAmount; + if (inventoryFrom instanceof IStorageSystemItemHandler storageFrom) { + return storageFrom.extractItems(filter, (extracted) -> extracted.getCount() - inserter.insertItem(extracted).getCount(), false); } - if (inventoryTo instanceof IStorageSystemItemHandler storageSystemHandler) { - for (int i = fromSlot == -1 ? 0 : fromSlot; i < (fromSlot == -1 ? inventoryFrom.getSlots() : fromSlot + 1); i++) { - if (filter.test(inventoryFrom.getStackInSlot(i))) { - ItemStack extracted = inventoryFrom.extractItem(i, amount - transferableAmount, true); - if (extracted.isEmpty()) - continue; - ItemStack remaining = storageSystemHandler.insertItem(toSlot, extracted, false); - - amount -= remaining.getCount(); - transferableAmount += inventoryFrom.extractItem(i, extracted.getCount() - remaining.getCount(), false).getCount(); - if (transferableAmount >= filter.getCount()) - break; - } - } - return transferableAmount; + int[] fromSlots = ( + fromSlot >= 0 + ? IntStream.of(fromSlot) + : IntStream.range(0, inventoryFrom.getSlots()) + ) + .filter((i) -> filter.test(inventoryFrom.getStackInSlot(i))) + .toArray(); + if (fromSlots.length == 0) { + return 0; } - for (int i = fromSlot == -1 ? 0 : fromSlot; i < (fromSlot == -1 ? inventoryFrom.getSlots() : fromSlot + 1); i++) { - if (filter.test(inventoryFrom.getStackInSlot(i))) { - ItemStack extracted = inventoryFrom.extractItem(i, amount - transferableAmount, true); - if (extracted.isEmpty()) - continue; - ItemStack inserted; - if (toSlot == -1) { - inserted = ItemHandlerHelper.insertItem(inventoryTo, extracted, false); - } else { - inserted = inventoryTo.insertItem(toSlot, extracted, false); - } - amount -= inserted.getCount(); - transferableAmount += inventoryFrom.extractItem(i, extracted.getCount() - inserted.getCount(), false).getCount(); - if (transferableAmount >= filter.getCount()) - break; + for (int i : fromSlots) { + ItemStack extracted = inventoryFrom.extractItem(i, needs, true); + if (extracted.isEmpty()) { + continue; + } + ItemStack remaining = inserter.insertItem(extracted); + int inserted = extracted.getCount() - remaining.getCount(); + if (inserted == 0) { + continue; + } + needs -= inserted; + inventoryFrom.extractItem(i, inserted, false); + if (needs <= 0) { + break; } } - return transferableAmount; + return filter.getCount() - needs; } @Nullable public static IItemHandler getHandlerFromName(@NotNull IComputerAccess access, String name) throws LuaException { IPeripheral location = access.getAvailablePeripheral(name); - if (location == null) + if (location == null) { return null; - + } return extractHandler(location.getTarget(), null, null, null); } @Nullable public static IItemHandler getHandlerFromDirection(@NotNull String direction, @NotNull IPeripheralOwner owner) throws LuaException { - Level level = owner.getLevel(); - Objects.requireNonNull(level); + Level level = Objects.requireNonNull(owner.getLevel()); Direction relativeDirection = CoordUtil.getDirection(owner.getOrientation(), direction); - if (relativeDirection == null) + if (relativeDirection == null) { return null; + } BlockEntity target = level.getBlockEntity(owner.getPos().relative(relativeDirection)); - if (target == null) + if (target == null) { return null; - + } return extractHandler(target, level, target.getBlockPos(), relativeDirection.getOpposite()); } + + @FunctionalInterface + private interface ItemInserter { + ItemStack insertItem(ItemStack stack); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemFilter.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemFilter.java index cbe073ab8..6fb4cb695 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemFilter.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemFilter.java @@ -38,7 +38,7 @@ public class ItemFilter extends GenericFilter { private ItemFilter() { } - public static Pair parse(LuaTable item) { + public static Pair parse(LuaTable item) throws LuaException { // If the map is empty, return a filter without any filters if (item.isEmpty()) return Pair.of(EMPTY, null); @@ -46,55 +46,35 @@ public static Pair parse(LuaTable item) { ItemFilter itemFilter = createEmpty(); if (item.containsKey("name")) { - try { - String name = item.getString("name"); - if (name.startsWith("#")) { - itemFilter.tag = TagKey.create(Registries.ITEM, ResourceLocation.parse(name.substring(1))); - } else if ((itemFilter.item = ItemUtil.getRegistryEntry(name, BuiltInRegistries.ITEM)) == null) { - return Pair.of(null, "ITEM_NOT_FOUND"); - } - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_ITEM"); + String name = item.getString("name"); + if (name.startsWith("#")) { + itemFilter.tag = TagKey.create(Registries.ITEM, ResourceLocation.parse(name.substring(1))); + } else if ((itemFilter.item = ItemUtil.getRegistryEntry(name, BuiltInRegistries.ITEM)) == null) { + return Pair.of(null, "ITEM_NOT_FOUND"); } } if (item.containsKey("components")) { try { itemFilter.componentsAsNbt = NBTUtil.fromText(item.getString("components")); - } catch (LuaException luaException) { + } catch (LuaException e1) { try { itemFilter.componentsAsNbt = NBTUtil.fromText(item.getTable("components").toString()); - } catch (LuaException e) { - return Pair.of(null, "NO_VALID_COMPONENTS"); + } catch (LuaException e2) { + throw new LuaException("bad field \"components\", expect NBT string or table"); } } } if (item.containsKey("fingerprint")) { - try { - itemFilter.fingerprint = item.getString("fingerprint"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_FINGERPRINT"); - } + itemFilter.fingerprint = item.getString("fingerprint"); } if (item.containsKey("fromSlot")) { - try { - itemFilter.fromSlot = item.getInt("fromSlot"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_FROMSLOT"); - } + itemFilter.fromSlot = item.getInt("fromSlot"); } if (item.containsKey("toSlot")) { - try { - itemFilter.toSlot = item.getInt( "toSlot"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_TOSLOT"); - } + itemFilter.toSlot = item.getInt("toSlot"); } if (item.containsKey("count")) { - try { - itemFilter.count = item.getInt( "count"); - } catch (LuaException luaException) { - return Pair.of(null, "NO_VALID_COUNT"); - } + itemFilter.count = item.getInt("count"); } AdvancedPeripherals.debug("Parsed item filter: " + itemFilter); @@ -102,8 +82,13 @@ public static Pair parse(LuaTable item) { } public static ItemFilter fromStack(ItemStack stack) { + return fromStackWithCount(stack, stack.getCount()); + } + + public static ItemFilter fromStackWithCount(ItemStack stack, int count) { ItemFilter filter = createEmpty(); filter.item = stack.getItem(); + filter.count = count; filter.componentsAsNbt = DataComponentUtil.toNbt(stack.getComponentsPatch()); filter.components = (PatchedDataComponentMap) stack.getComponents(); return filter; @@ -139,6 +124,26 @@ public boolean testRS(ResourceAmount resourceAmount) { return false; } + @Override + public ItemFilter copy() { + ItemFilter newFilter = new ItemFilter(); + newFilter.item = this.item; + newFilter.tag = this.tag; + newFilter.componentsAsNbt = this.componentsAsNbt; + newFilter.components = this.components; + newFilter.count = this.count; + newFilter.fingerprint = this.fingerprint; + newFilter.fromSlot = this.fromSlot; + newFilter.toSlot = this.toSlot; + return newFilter; + } + + public ItemFilter copyWithCount(int count) { + ItemFilter newFilter = this.copy(); + newFilter.count = count; + return newFilter; + } + public ItemStack toItemStack() { var result = new ItemStack(item, count); if (components != null) { diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/StorageProcessor.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/StorageProcessor.java new file mode 100644 index 000000000..c099c96c6 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/StorageProcessor.java @@ -0,0 +1,22 @@ +package de.srendi.advancedperipherals.common.util.inventory; + +@FunctionalInterface +public interface StorageProcessor { + /** + * Process a storage content + * + * @param stack the original content, should not be modified + * @return consumed amount. + */ + int process(T stack); + + interface Large { + /** + * Process a storage content + * + * @param stack the original content, should not be modified + * @return consumed amount. + */ + long process(T stack); + } +}