From e345cfa5972bdf288ef48f44008ea0b47620db86 Mon Sep 17 00:00:00 2001 From: Starforcraft Date: Mon, 27 May 2024 16:19:27 +0200 Subject: [PATCH] feat: importer and exporter gametest setup --- .../common/importer/ImporterBlockEntity.java | 7 +- .../common/exporter/ExporterTest.java | 129 ++++++++++ .../common/exporter/ExporterTestPlots.java | 40 +++ .../common/importer/ImporterTest.java | 236 ++++++++++++++++++ .../common/importer/ImporterTestPlots.java | 50 ++++ .../platform/forge/GameTestUtil.java | 37 +++ 6 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/exporter/ExporterTest.java create mode 100644 refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/exporter/ExporterTestPlots.java create mode 100644 refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterTest.java create mode 100644 refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterTestPlots.java diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterBlockEntity.java index 1945dfab1..fab93c5e5 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterBlockEntity.java @@ -20,6 +20,7 @@ import com.refinedmods.refinedstorage2.platform.common.upgrade.UpgradeDestinations; import java.util.List; +import java.util.Set; import java.util.function.LongSupplier; import javax.annotation.Nullable; @@ -57,7 +58,7 @@ public ImporterBlockEntity(final BlockPos pos, final BlockState state) { this.filter = FilterWithFuzzyMode.createAndListenForUniqueFilters( ResourceContainerImpl.createForFilter(), this::setChanged, - mainNode::setFilters + this::setFilters ); this.mainNode.setNormalizer(filter.createNormalizer()); } @@ -96,6 +97,10 @@ public void readConfiguration(final CompoundTag tag) { filter.load(tag); } + void setFilters(final Set filters) { + mainNode.setFilters(filters); + } + boolean isFuzzyMode() { return filter.isFuzzyMode(); } diff --git a/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/exporter/ExporterTest.java b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/exporter/ExporterTest.java new file mode 100644 index 000000000..d89f99fb4 --- /dev/null +++ b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/exporter/ExporterTest.java @@ -0,0 +1,129 @@ +package com.refinedmods.refinedstorage2.platform.common.exporter; + +import com.refinedmods.refinedstorage2.api.resource.ResourceAmount; +import com.refinedmods.refinedstorage2.platform.common.Platform; +import com.refinedmods.refinedstorage2.platform.common.util.IdentifierUtil; + +import java.util.List; + +import net.minecraft.core.Direction; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.LayeredCauldronBlock; +import net.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; + +import static com.refinedmods.refinedstorage2.platform.common.exporter.ExporterTestPlots.preparePlot; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.asResource; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.containerContainsExactly; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.insert; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.networkIsAvailable; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.storageContainsExactly; +import static net.minecraft.world.item.Items.DIAMOND_CHESTPLATE; +import static net.minecraft.world.item.Items.DIRT; +import static net.minecraft.world.item.Items.STONE; +import static net.minecraft.world.level.material.Fluids.WATER; + +@GameTestHolder(IdentifierUtil.MOD_ID) +@PrefixGameTestTemplate(false) +public final class ExporterTest { + private ExporterTest() { + } + + @GameTest(template = "empty_15x15") + public static void shouldExportItem(final GameTestHelper helper) { + preparePlot(helper, true, Direction.EAST, (exporter, pos, sequence) -> { + // Arrange + final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); + damagedDiamondChestplate.setDamageValue(500); + + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + insert(helper, network, DIRT, 10); + insert(helper, network, STONE, 15); + insert(helper, network, asResource(damagedDiamondChestplate), 1); + })); + + // Act + exporter.setFilters(List.of(asResource(DIRT), asResource(DIAMOND_CHESTPLATE.getDefaultInstance()))); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIRT), 1))) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 9), + new ResourceAmount(asResource(STONE), 15), + new ResourceAmount(asResource(damagedDiamondChestplate), 1) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldExportItemFuzzy(final GameTestHelper helper) { + preparePlot(helper, true, Direction.EAST, (exporter, pos, sequence) -> { + // Arrange + final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); + damagedDiamondChestplate.setDamageValue(500); + + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + insert(helper, network, DIRT, 10); + insert(helper, network, STONE, 15); + insert(helper, network, DIAMOND_CHESTPLATE, 1); + insert(helper, network, asResource(damagedDiamondChestplate), 1); + })); + + // Act + exporter.setFuzzyMode(true); + exporter.setFilters(List.of(asResource(DIAMOND_CHESTPLATE))); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()), 1), + new ResourceAmount(asResource(damagedDiamondChestplate), 1))) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(STONE), 15) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldExportFluid(final GameTestHelper helper) { + preparePlot(helper, false, Direction.EAST, (exporter, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + insert(helper, network, DIRT, 10); + insert(helper, network, STONE, 15); + insert(helper, network, WATER, Platform.INSTANCE.getBucketAmount() * 2); + })); + + // Act + exporter.setFilters(List.of(asResource(WATER))); + + // Assert + sequence + .thenWaitUntil(() -> helper.assertBlockProperty(pos.east(), LayeredCauldronBlock.LEVEL, + LayeredCauldronBlock.MAX_FILL_LEVEL)) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(STONE), 15), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()) + )) + .thenSucceed(); + }); + } +} diff --git a/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/exporter/ExporterTestPlots.java b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/exporter/ExporterTestPlots.java new file mode 100644 index 000000000..8cf74448b --- /dev/null +++ b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/exporter/ExporterTestPlots.java @@ -0,0 +1,40 @@ +package com.refinedmods.refinedstorage2.platform.common.exporter; + +import com.refinedmods.refinedstorage2.platform.common.storage.FluidStorageType; +import com.refinedmods.refinedstorage2.platform.common.storage.ItemStorageType; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.gametest.framework.GameTestSequence; +import net.minecraft.world.level.block.Blocks; +import org.apache.commons.lang3.function.TriConsumer; + +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.RSBLOCKS; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.requireBlockEntity; +import static net.minecraft.core.BlockPos.ZERO; + +final class ExporterTestPlots { + private ExporterTestPlots() { + } + + static void preparePlot(final GameTestHelper helper, + final boolean itemTest, + final Direction direction, + final TriConsumer consumer) { + helper.setBlock(ZERO.above(), RSBLOCKS.getCreativeController().getDefault()); + helper.setBlock(ZERO.above().above(), RSBLOCKS.getItemStorageBlock(ItemStorageType.Variant.ONE_K)); + helper.setBlock( + ZERO.above().above().north(), + RSBLOCKS.getFluidStorageBlock(FluidStorageType.Variant.SIXTY_FOUR_B) + ); + final BlockPos exporterPos = ZERO.above().above().above(); + helper.setBlock(exporterPos, RSBLOCKS.getExporter().getDefault().rotated(direction)); + helper.setBlock(exporterPos.east(), itemTest ? Blocks.CHEST : Blocks.CAULDRON); + consumer.accept( + requireBlockEntity(helper, exporterPos, ExporterBlockEntity.class), + exporterPos, + helper.startSequence() + ); + } +} diff --git a/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterTest.java b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterTest.java new file mode 100644 index 000000000..ba22f0e24 --- /dev/null +++ b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterTest.java @@ -0,0 +1,236 @@ +package com.refinedmods.refinedstorage2.platform.common.importer; + +import com.refinedmods.refinedstorage2.api.resource.ResourceAmount; +import com.refinedmods.refinedstorage2.api.resource.filter.FilterMode; +import com.refinedmods.refinedstorage2.platform.common.Platform; +import com.refinedmods.refinedstorage2.platform.common.util.IdentifierUtil; + +import java.util.Set; + +import net.minecraft.core.Direction; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LayeredCauldronBlock; +import net.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; + +import static com.refinedmods.refinedstorage2.platform.common.importer.ImporterTestPlots.prepareChest; +import static com.refinedmods.refinedstorage2.platform.common.importer.ImporterTestPlots.preparePlot; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.asResource; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.containerContainsExactly; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.insert; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.networkIsAvailable; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.storageContainsExactly; +import static net.minecraft.world.item.Items.COBBLESTONE; +import static net.minecraft.world.item.Items.DIAMOND_CHESTPLATE; +import static net.minecraft.world.item.Items.DIRT; +import static net.minecraft.world.item.Items.STONE; +import static net.minecraft.world.level.material.Fluids.WATER; + +@GameTestHolder(IdentifierUtil.MOD_ID) +@PrefixGameTestTemplate(false) +public final class ImporterTest { + private ImporterTest() { + } + + @GameTest(template = "empty_15x15") + public static void shouldImportItem(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (importer, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + insert(helper, network, DIRT, 10); + insert(helper, network, STONE, 15); + })); + + // Act + prepareChest(helper, pos.east(), DIRT.getDefaultInstance(), + COBBLESTONE.getDefaultInstance().copyWithCount(3)); + + // Assert + sequence + .thenWaitUntil(() -> helper.assertContainerEmpty(pos.east())) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 11), + new ResourceAmount(asResource(STONE), 15), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldImportItemBlocklist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (importer, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + insert(helper, network, DIRT, 10); + insert(helper, network, STONE, 15); + })); + + // Act + final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); + damagedDiamondChestplate.setDamageValue(500); + prepareChest(helper, pos.east(), DIRT.getDefaultInstance(), + DIAMOND_CHESTPLATE.getDefaultInstance(), damagedDiamondChestplate); + + importer.setFuzzyMode(false); + importer.setFilters(Set.of(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()))); + importer.setFilterMode(FilterMode.BLOCK); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()), 1))) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 11), + new ResourceAmount(asResource(STONE), 15), + new ResourceAmount(asResource(damagedDiamondChestplate), 1) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldImportItemFuzzyBlocklist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (importer, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + insert(helper, network, DIRT, 10); + insert(helper, network, STONE, 15); + })); + + // Act + final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); + damagedDiamondChestplate.setDamageValue(500); + prepareChest(helper, pos.east(), DIRT.getDefaultInstance(), + DIAMOND_CHESTPLATE.getDefaultInstance(), damagedDiamondChestplate); + + importer.setFuzzyMode(true); + importer.setFilters(Set.of(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()))); + importer.setFilterMode(FilterMode.BLOCK); + + // Assert + sequence + .thenIdle(10) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()), 1), + new ResourceAmount(asResource(damagedDiamondChestplate), 1))) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 11), + new ResourceAmount(asResource(STONE), 15) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldImportItemAllowlist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (importer, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + insert(helper, network, DIRT, 10); + insert(helper, network, STONE, 15); + })); + + // Act + final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); + damagedDiamondChestplate.setDamageValue(500); + prepareChest(helper, pos.east(), DIRT.getDefaultInstance(), + DIAMOND_CHESTPLATE.getDefaultInstance(), damagedDiamondChestplate); + + importer.setFuzzyMode(false); + importer.setFilters(Set.of(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()))); + importer.setFilterMode(FilterMode.ALLOW); + + // Assert + sequence + .thenWaitUntil(() -> helper.assertContainerContains(pos.east(), DIRT)) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIRT), 1), + new ResourceAmount(asResource(damagedDiamondChestplate), 1))) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(STONE), 15), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()), 1) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldImportItemFuzzyAllowlist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (importer, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + insert(helper, network, DIRT, 10); + insert(helper, network, STONE, 15); + })); + + // Act + final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); + damagedDiamondChestplate.setDamageValue(500); + prepareChest(helper, pos.east(), DIRT.getDefaultInstance(), + DIAMOND_CHESTPLATE.getDefaultInstance(), damagedDiamondChestplate); + + importer.setFuzzyMode(true); + importer.setFilters(Set.of(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()))); + importer.setFilterMode(FilterMode.ALLOW); + + // Assert + sequence + .thenWaitUntil(() -> helper.assertContainerContains(pos.east(), DIRT)) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(STONE), 15), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()), 1), + new ResourceAmount(asResource(damagedDiamondChestplate), 1) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldImportFluid(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (importer, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + insert(helper, network, DIRT, 10); + insert(helper, network, STONE, 15); + })); + + // Act + helper.setBlock(pos.east(), Blocks.WATER_CAULDRON.defaultBlockState() + .setValue(LayeredCauldronBlock.LEVEL, LayeredCauldronBlock.MAX_FILL_LEVEL)); + + // Assert + sequence + .thenWaitUntil(() -> helper.assertBlockPresent(Blocks.CAULDRON, pos.east())) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(STONE), 15), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()) + )) + .thenSucceed(); + }); + } +} diff --git a/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterTestPlots.java b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterTestPlots.java new file mode 100644 index 000000000..44a9c357c --- /dev/null +++ b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/common/importer/ImporterTestPlots.java @@ -0,0 +1,50 @@ +package com.refinedmods.refinedstorage2.platform.common.importer; + +import com.refinedmods.refinedstorage2.platform.common.storage.FluidStorageType; +import com.refinedmods.refinedstorage2.platform.common.storage.ItemStorageType; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.gametest.framework.GameTestSequence; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; +import org.apache.commons.lang3.function.TriConsumer; + +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.RSBLOCKS; +import static com.refinedmods.refinedstorage2.platform.forge.GameTestUtil.requireBlockEntity; +import static net.minecraft.core.BlockPos.ZERO; + +final class ImporterTestPlots { + private ImporterTestPlots() { + } + + static void preparePlot(final GameTestHelper helper, + final Direction direction, + final TriConsumer consumer) { + helper.setBlock(ZERO.above(), RSBLOCKS.getCreativeController().getDefault()); + helper.setBlock(ZERO.above().above(), RSBLOCKS.getItemStorageBlock(ItemStorageType.Variant.ONE_K)); + helper.setBlock( + ZERO.above().above().north(), + RSBLOCKS.getFluidStorageBlock(FluidStorageType.Variant.SIXTY_FOUR_B) + ); + final BlockPos importerPos = ZERO.above().above().above(); + helper.setBlock(importerPos, RSBLOCKS.getImporter().getDefault().rotated(direction)); + consumer.accept( + requireBlockEntity(helper, importerPos, ImporterBlockEntity.class), + importerPos, + helper.startSequence() + ); + } + + static void prepareChest(final GameTestHelper helper, + final BlockPos pos, + final ItemStack... stacks) { + helper.setBlock(pos, Blocks.CHEST.defaultBlockState()); + final var chestBlockEntity = requireBlockEntity(helper, pos, BaseContainerBlockEntity.class); + for (int i = 0; i < stacks.length; i++) { + chestBlockEntity.setItem(i, stacks[i]); + } + } +} diff --git a/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/forge/GameTestUtil.java b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/forge/GameTestUtil.java index 5485bc5f1..bdc9b4fe5 100644 --- a/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/forge/GameTestUtil.java +++ b/refinedstorage2-platform-forge/src/test/java/com/refinedmods/refinedstorage2/platform/forge/GameTestUtil.java @@ -14,12 +14,16 @@ import java.util.Arrays; import java.util.function.Consumer; +import java.util.stream.IntStream; import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.gametest.framework.GameTestAssertException; import net.minecraft.gametest.framework.GameTestHelper; import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; @@ -105,6 +109,35 @@ public static void assertFluidPresent(final GameTestHelper helper, ); } + public static Runnable containerContainsExactly(final GameTestHelper helper, + final BlockPos pos, + final ResourceAmount... expected) { + final var containerBlockEntity = requireBlockEntity(helper, pos, BaseContainerBlockEntity.class); + + return () -> { + for (final ResourceAmount expectedStack : expected) { + final boolean contains = IntStream.range(0, containerBlockEntity.getContainerSize()) + .mapToObj(containerBlockEntity::getItem) + .anyMatch(inContainer -> asResource(inContainer).equals(expectedStack.getResource()) + && inContainer.getCount() == expectedStack.getAmount()); + helper.assertTrue(contains, "Expected resource is missing from storage: " + + expectedStack + " with count: " + expectedStack.getAmount()); + } + for (int i = 0; i < containerBlockEntity.getContainerSize(); i++) { + final ItemStack inContainer = containerBlockEntity.getItem(i); + + if (inContainer.getItem() != Items.AIR) { + final boolean wasExpected = Arrays.stream(expected).anyMatch( + expectedStack -> expectedStack.getResource().equals(asResource(inContainer)) + && expectedStack.getAmount() == inContainer.getCount() + ); + helper.assertTrue(wasExpected, "Unexpected resource found in storage: " + + inContainer.getDescriptionId() + " with count: " + inContainer.getCount()); + } + } + }; + } + public static Runnable storageContainsExactly(final GameTestHelper helper, final BlockPos networkPos, final ResourceAmount... expected) { @@ -131,6 +164,10 @@ public static ItemResource asResource(final Item item) { return new ItemResource(item, null); } + public static ItemResource asResource(final ItemStack itemStack) { + return new ItemResource(itemStack.getItem(), itemStack.getTag()); + } + public static FluidResource asResource(final Fluid fluid) { return new FluidResource(fluid, null); }