From b6113478d23f0096cadfb60cce5fc305e6470f59 Mon Sep 17 00:00:00 2001 From: Starforcraft Date: Sat, 3 Aug 2024 10:39:33 +0200 Subject: [PATCH] feat: external storage gametest --- .../AbstractExternalStorageBlockEntity.java | 29 + .../ExternalStorageWorkRate.java | 42 +- ...ctBaseNetworkNodeContainerBlockEntity.java | 6 +- .../refinedstorage/common/GameTestUtil.java | 161 +++- .../common/exporter/ExporterTest.java | 12 +- .../common/importer/ImporterTest.java | 30 +- .../common/importer/ImporterTestPlots.java | 28 - .../ExternalStorageFluidTest.java | 344 ++++++++ .../ExternalStorageItemTest.java | 799 ++++++++++++++++++ .../ExternalStorageTestPlots.java | 54 ++ 10 files changed, 1429 insertions(+), 76 deletions(-) create mode 100644 refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageFluidTest.java create mode 100644 refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageItemTest.java create mode 100644 refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageTestPlots.java diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/externalstorage/AbstractExternalStorageBlockEntity.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/externalstorage/AbstractExternalStorageBlockEntity.java index 1a1b0778c..adc39467e 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/externalstorage/AbstractExternalStorageBlockEntity.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/externalstorage/AbstractExternalStorageBlockEntity.java @@ -1,6 +1,9 @@ package com.refinedmods.refinedstorage.common.storage.externalstorage; import com.refinedmods.refinedstorage.api.network.impl.node.externalstorage.ExternalStorageNetworkNode; +import com.refinedmods.refinedstorage.api.resource.ResourceKey; +import com.refinedmods.refinedstorage.api.resource.filter.FilterMode; +import com.refinedmods.refinedstorage.api.storage.AccessMode; import com.refinedmods.refinedstorage.common.Platform; import com.refinedmods.refinedstorage.common.api.RefinedStorageApi; import com.refinedmods.refinedstorage.common.content.BlockEntities; @@ -13,6 +16,7 @@ import com.refinedmods.refinedstorage.common.support.resource.ResourceContainerData; import com.refinedmods.refinedstorage.common.support.resource.ResourceContainerImpl; +import java.util.Set; import javax.annotation.Nullable; import net.minecraft.core.BlockPos; @@ -145,6 +149,31 @@ public void readConfiguration(final CompoundTag tag, final HolderLookup.Provider configContainer.load(tag); } + void setFilters(final Set filters) { + mainNetworkNode.getStorageConfiguration().setFilters(filters); + } + + void setFilterMode(final FilterMode mode) { + mainNetworkNode.getStorageConfiguration().setFilterMode(mode); + setChanged(); + } + + void setFuzzyMode(final boolean fuzzyMode) { + filter.setFuzzyMode(fuzzyMode); + } + + void setAccessMode(final AccessMode accessMode) { + mainNetworkNode.getStorageConfiguration().setAccessMode(accessMode); + } + + void setPriority(final int priority) { + mainNetworkNode.getStorageConfiguration().setPriority(priority); + } + + void setVoidExcess(final boolean voidExcess) { + mainNetworkNode.getStorageConfiguration().setVoidExcess(voidExcess); + } + @Override public ResourceContainerData getMenuData() { return ResourceContainerData.of(filter.getFilterContainer()); diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageWorkRate.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageWorkRate.java index 99f46938e..b6a9fc28e 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageWorkRate.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageWorkRate.java @@ -1,40 +1,42 @@ package com.refinedmods.refinedstorage.common.storage.externalstorage; -import com.google.common.util.concurrent.RateLimiter; - class ExternalStorageWorkRate { - private static final double[] RATE_LIMITERS = new double[] { - 0.5D, // slowest, every 2 sec - 0.75D, // faster - 1D, // medium, every 1 sec - 2D, // faster, every 0.5 sec - 3D // fastest + private static final int[] OPERATION_COUNTS = new int[] { + 40, // slowest, every 2 sec + 30, // faster, every 1.5 sec + 20, // medium, every 1 sec + 10, // faster, every 0.5 sec + 5 // fastest, every 0.25 sec }; private int idx = 2; // medium - private final RateLimiter rateLimiter = RateLimiter.create(RATE_LIMITERS[idx]); + private int counter = 0; + private int threshold = OPERATION_COUNTS[idx]; boolean canDoWork() { - return rateLimiter.tryAcquire(); + counter++; + if (counter >= threshold) { + counter = 0; + return true; + } + return false; } void faster() { - if (idx + 1 >= RATE_LIMITERS.length) { - return; + if (idx + 1 < OPERATION_COUNTS.length) { + idx++; + updateThreshold(); } - idx++; - updateRate(); } void slower() { - if (idx - 1 < 0) { - return; + if (idx - 1 >= 0) { + idx--; + updateThreshold(); } - idx--; - updateRate(); } - private void updateRate() { - rateLimiter.setRate(RATE_LIMITERS[idx]); + private void updateThreshold() { + threshold = OPERATION_COUNTS[idx]; } } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/network/AbstractBaseNetworkNodeContainerBlockEntity.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/network/AbstractBaseNetworkNodeContainerBlockEntity.java index 26a995eb1..5f2a3dd74 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/network/AbstractBaseNetworkNodeContainerBlockEntity.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/network/AbstractBaseNetworkNodeContainerBlockEntity.java @@ -17,7 +17,6 @@ import java.util.UUID; import javax.annotation.Nullable; -import com.google.common.util.concurrent.RateLimiter; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.HolderLookup; @@ -46,10 +45,11 @@ public abstract class AbstractBaseNetworkNodeContainerBlockEntity { // Arrange - final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); - damagedDiamondChestplate.setDamageValue(500); + final ItemStack damagedDiamondChestplate = getItemAsDamaged(DIAMOND_CHESTPLATE.getDefaultInstance(), 500); sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { insert(helper, network, DIRT, 10); @@ -116,8 +116,7 @@ public static void shouldExportItemWithStackUpgrade(final GameTestHelper helper) public static void shouldExportItemFuzzy(final GameTestHelper helper) { ExporterTestPlots.preparePlot(helper, Blocks.CHEST, Direction.EAST, (exporter, pos, sequence) -> { // Arrange - final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); - damagedDiamondChestplate.setDamageValue(500); + final ItemStack damagedDiamondChestplate = getItemAsDamaged(DIAMOND_CHESTPLATE.getDefaultInstance(), 500); sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { insert(helper, network, DIRT, 10); @@ -202,10 +201,7 @@ public static void shouldExportFluidWithStackUpgrade(final GameTestHelper helper .thenExecute(interfaceContainsExactly( helper, pos.east(), - new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 16), - new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 16), - new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 16), - new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 16) + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 64) )) .thenSucceed(); diff --git a/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/importer/ImporterTest.java b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/importer/ImporterTest.java index 409126da3..f620e86e2 100644 --- a/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/importer/ImporterTest.java +++ b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/importer/ImporterTest.java @@ -20,12 +20,13 @@ import static com.refinedmods.refinedstorage.common.GameTestUtil.asResource; import static com.refinedmods.refinedstorage.common.GameTestUtil.assertInterfaceEmpty; import static com.refinedmods.refinedstorage.common.GameTestUtil.containerContainsExactly; +import static com.refinedmods.refinedstorage.common.GameTestUtil.getItemAsDamaged; import static com.refinedmods.refinedstorage.common.GameTestUtil.insert; import static com.refinedmods.refinedstorage.common.GameTestUtil.interfaceContainsExactly; import static com.refinedmods.refinedstorage.common.GameTestUtil.networkIsAvailable; +import static com.refinedmods.refinedstorage.common.GameTestUtil.prepareChest; +import static com.refinedmods.refinedstorage.common.GameTestUtil.prepareInterface; import static com.refinedmods.refinedstorage.common.GameTestUtil.storageContainsExactly; -import static com.refinedmods.refinedstorage.common.importer.ImporterTestPlots.prepareChest; -import static com.refinedmods.refinedstorage.common.importer.ImporterTestPlots.prepareInterface; import static com.refinedmods.refinedstorage.common.importer.ImporterTestPlots.preparePlot; import static net.minecraft.world.item.Items.COBBLESTONE; import static net.minecraft.world.item.Items.DIAMOND_CHESTPLATE; @@ -87,6 +88,7 @@ public static void shouldImportItemWithStackUpgrade(final GameTestHelper helper) COBBLESTONE.getDefaultInstance().copyWithCount(64), DIRT.getDefaultInstance() ); + importer.addUpgradeItem(RSITEMS.getStackUpgrade()); // Assert @@ -126,13 +128,13 @@ public static void shouldImportItemBlocklist(final GameTestHelper helper) { })); // Act - final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); - damagedDiamondChestplate.setDamageValue(500); + final ItemStack damagedDiamondChestplate = getItemAsDamaged(DIAMOND_CHESTPLATE.getDefaultInstance(), 500); prepareChest( helper, pos.east(), DIRT.getDefaultInstance(), - DIAMOND_CHESTPLATE.getDefaultInstance(), damagedDiamondChestplate + DIAMOND_CHESTPLATE.getDefaultInstance(), + damagedDiamondChestplate ); importer.setFuzzyMode(false); @@ -167,13 +169,13 @@ public static void shouldImportItemFuzzyBlocklist(final GameTestHelper helper) { })); // Act - final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); - damagedDiamondChestplate.setDamageValue(500); + final ItemStack damagedDiamondChestplate = getItemAsDamaged(DIAMOND_CHESTPLATE.getDefaultInstance(), 500); prepareChest( helper, pos.east(), DIRT.getDefaultInstance(), - DIAMOND_CHESTPLATE.getDefaultInstance(), damagedDiamondChestplate + DIAMOND_CHESTPLATE.getDefaultInstance(), + damagedDiamondChestplate ); importer.setFuzzyMode(true); @@ -209,13 +211,13 @@ public static void shouldImportItemAllowlist(final GameTestHelper helper) { })); // Act - final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); - damagedDiamondChestplate.setDamageValue(500); + final ItemStack damagedDiamondChestplate = getItemAsDamaged(DIAMOND_CHESTPLATE.getDefaultInstance(), 500); prepareChest( helper, pos.east(), DIRT.getDefaultInstance(), - DIAMOND_CHESTPLATE.getDefaultInstance(), damagedDiamondChestplate + DIAMOND_CHESTPLATE.getDefaultInstance(), + damagedDiamondChestplate ); importer.setFuzzyMode(false); @@ -252,13 +254,13 @@ public static void shouldImportItemFuzzyAllowlist(final GameTestHelper helper) { })); // Act - final ItemStack damagedDiamondChestplate = DIAMOND_CHESTPLATE.getDefaultInstance(); - damagedDiamondChestplate.setDamageValue(500); + final ItemStack damagedDiamondChestplate = getItemAsDamaged(DIAMOND_CHESTPLATE.getDefaultInstance(), 500); prepareChest( helper, pos.east(), DIRT.getDefaultInstance(), - DIAMOND_CHESTPLATE.getDefaultInstance(), damagedDiamondChestplate + DIAMOND_CHESTPLATE.getDefaultInstance(), + damagedDiamondChestplate ); importer.setFuzzyMode(true); diff --git a/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/importer/ImporterTestPlots.java b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/importer/ImporterTestPlots.java index 898bb6d4f..e3936e55d 100644 --- a/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/importer/ImporterTestPlots.java +++ b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/importer/ImporterTestPlots.java @@ -1,8 +1,5 @@ package com.refinedmods.refinedstorage.common.importer; -import com.refinedmods.refinedstorage.api.resource.ResourceAmount; -import com.refinedmods.refinedstorage.common.iface.ExportedResourcesContainer; -import com.refinedmods.refinedstorage.common.iface.InterfaceBlockEntity; import com.refinedmods.refinedstorage.common.storage.FluidStorageVariant; import com.refinedmods.refinedstorage.common.storage.ItemStorageVariant; @@ -10,9 +7,6 @@ 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.refinedstorage.common.GameTestUtil.RSBLOCKS; @@ -40,26 +34,4 @@ static void preparePlot(final GameTestHelper helper, 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]); - } - } - - static void prepareInterface(final GameTestHelper helper, - final BlockPos pos, - final ResourceAmount... resource) { - helper.setBlock(pos, RSBLOCKS.getInterface()); - final var interfaceBlockEntity = requireBlockEntity(helper, pos, InterfaceBlockEntity.class); - final ExportedResourcesContainer exportedResources = interfaceBlockEntity.getExportedResources(); - - for (int i = 0; i < resource.length; i++) { - exportedResources.set(i, resource[i]); - } - } } diff --git a/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageFluidTest.java b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageFluidTest.java new file mode 100644 index 000000000..0a91639cd --- /dev/null +++ b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageFluidTest.java @@ -0,0 +1,344 @@ +package com.refinedmods.refinedstorage.common.storage.externalstorage; + +import com.refinedmods.refinedstorage.api.resource.ResourceAmount; +import com.refinedmods.refinedstorage.api.resource.filter.FilterMode; +import com.refinedmods.refinedstorage.common.Platform; +import com.refinedmods.refinedstorage.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.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; + +import static com.refinedmods.refinedstorage.common.GameTestUtil.addFluidToInterface; +import static com.refinedmods.refinedstorage.common.GameTestUtil.asResource; +import static com.refinedmods.refinedstorage.common.GameTestUtil.insert; +import static com.refinedmods.refinedstorage.common.GameTestUtil.interfaceContainsExactly; +import static com.refinedmods.refinedstorage.common.GameTestUtil.networkIsAvailable; +import static com.refinedmods.refinedstorage.common.GameTestUtil.prepareInterface; +import static com.refinedmods.refinedstorage.common.GameTestUtil.removeFluidToInterface; +import static com.refinedmods.refinedstorage.common.GameTestUtil.storageContainsExactly; +import static com.refinedmods.refinedstorage.common.storage.externalstorage.ExternalStorageTestPlots.preparePlot; +import static net.minecraft.world.item.Items.STONE; +import static net.minecraft.world.level.material.Fluids.LAVA; +import static net.minecraft.world.level.material.Fluids.WATER; + +@GameTestHolder(IdentifierUtil.MOD_ID) +@PrefixGameTestTemplate(false) +public final class ExternalStorageFluidTest { + private ExternalStorageFluidTest() { + } + + @GameTest(template = "empty_15x15") + public static void shouldExposeFluid(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareInterface( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 16), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 16), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + ); + + // Assert + sequence + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 32), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldInsertFluidAllowlist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareInterface( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 16), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 14), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + ); + + externalStorage.setPriority(1); + externalStorage.setFilters(Set.of(asResource(WATER))); + externalStorage.setFilterMode(FilterMode.ALLOW); + + // Assert + sequence + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 30), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 30), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, WATER, Platform.INSTANCE.getBucketAmount() * 2))) + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 32), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 32), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, LAVA, Platform.INSTANCE.getBucketAmount()))) + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 32), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 32), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldInsertFluidBlocklist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { + })); + + // Act + prepareInterface( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 16), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 14), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + ); + + externalStorage.setPriority(1); + externalStorage.setFilters(Set.of(asResource(WATER))); + externalStorage.setFilterMode(FilterMode.BLOCK); + + // Assert + sequence + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 30), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 30), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, WATER, Platform.INSTANCE.getBucketAmount() * 2))) + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 30), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 32), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, LAVA, Platform.INSTANCE.getBucketAmount()))) + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 30), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount() * 32), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldPropagateExternalFluidExtractions(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareInterface( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + ); + + // Assert + sequence + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenExecute(() -> removeFluidToInterface( + helper, + pos.east(), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldPropagatePartialExternalFluidExtractions(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareInterface( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + ); + + // Assert + sequence + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenExecute(() -> removeFluidToInterface( + helper, + pos.east(), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount()) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldPropagateExternalFluidInsertions(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareInterface( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()) + ); + + // Assert + sequence + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()) + )) + .thenExecute(() -> addFluidToInterface( + helper, + pos.east(), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenWaitUntil(interfaceContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(WATER), Platform.INSTANCE.getBucketAmount()), + new ResourceAmount(asResource(LAVA), Platform.INSTANCE.getBucketAmount() * 2) + )) + .thenSucceed(); + }); + } +} diff --git a/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageItemTest.java b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageItemTest.java new file mode 100644 index 000000000..14497939a --- /dev/null +++ b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageItemTest.java @@ -0,0 +1,799 @@ +package com.refinedmods.refinedstorage.common.storage.externalstorage; + +import com.refinedmods.refinedstorage.api.resource.ResourceAmount; +import com.refinedmods.refinedstorage.api.resource.filter.FilterMode; +import com.refinedmods.refinedstorage.api.storage.AccessMode; +import com.refinedmods.refinedstorage.common.support.RedstoneMode; +import com.refinedmods.refinedstorage.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.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; + +import static com.refinedmods.refinedstorage.common.GameTestUtil.addItemToChest; +import static com.refinedmods.refinedstorage.common.GameTestUtil.asResource; +import static com.refinedmods.refinedstorage.common.GameTestUtil.containerContainsExactly; +import static com.refinedmods.refinedstorage.common.GameTestUtil.createStacks; +import static com.refinedmods.refinedstorage.common.GameTestUtil.extract; +import static com.refinedmods.refinedstorage.common.GameTestUtil.getItemAsDamaged; +import static com.refinedmods.refinedstorage.common.GameTestUtil.insert; +import static com.refinedmods.refinedstorage.common.GameTestUtil.networkIsAvailable; +import static com.refinedmods.refinedstorage.common.GameTestUtil.prepareChest; +import static com.refinedmods.refinedstorage.common.GameTestUtil.removeItemFromChest; +import static com.refinedmods.refinedstorage.common.GameTestUtil.storageContainsExactly; +import static com.refinedmods.refinedstorage.common.storage.externalstorage.ExternalStorageTestPlots.preparePlot; +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; + +@GameTestHolder(IdentifierUtil.MOD_ID) +@PrefixGameTestTemplate(false) +public final class ExternalStorageItemTest { + private ExternalStorageItemTest() { + } + + @GameTest(template = "empty_15x15") + public static void shouldExposeItems(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareChest( + helper, + pos.east(), + DIRT.getDefaultInstance().copyWithCount(10), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + // Assert + sequence + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldInsertItemAllowlist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { })); + + // Act + prepareChest( + helper, + pos.east(), + DIRT.getDefaultInstance().copyWithCount(10), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + externalStorage.setPriority(1); + externalStorage.setFilters(Set.of(asResource(STONE))); + externalStorage.setFilterMode(FilterMode.ALLOW); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(STONE), 2) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(STONE), 2) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, DIRT, 2))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(STONE), 2) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 12), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(STONE), 2) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldInsertItemFuzzyAllowlist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, false, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { })); + + // Act + final ItemStack damagedDiamondChestplate = getItemAsDamaged(DIAMOND_CHESTPLATE.getDefaultInstance(), 500); + prepareChest( + helper, + pos.east(), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + externalStorage.setFuzzyMode(true); + externalStorage.setFilters(Set.of(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()))); + externalStorage.setFilterMode(FilterMode.ALLOW); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, asResource(DIAMOND_CHESTPLATE), 1))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE), 1) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE), 1) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, asResource(damagedDiamondChestplate), 1))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE), 1), + new ResourceAmount(asResource(damagedDiamondChestplate), 1) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE), 1), + new ResourceAmount(asResource(damagedDiamondChestplate), 1) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, asResource(DIRT), 10, false))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE), 1), + new ResourceAmount(asResource(damagedDiamondChestplate), 1) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(DIAMOND_CHESTPLATE), 1), + new ResourceAmount(asResource(damagedDiamondChestplate), 1) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldInsertItemBlocklist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { })); + + // Act + prepareChest( + helper, + pos.east(), + DIRT.getDefaultInstance().copyWithCount(10), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + externalStorage.setPriority(1); + externalStorage.setFilters(Set.of(asResource(STONE))); + externalStorage.setFilterMode(FilterMode.BLOCK); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(STONE), 2) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, DIRT, 2))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIRT), 12), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(DIRT), 12), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(STONE), 2) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldInsertItemFuzzyBlocklist(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, false, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { })); + + // Act + final ItemStack damagedDiamondChestplate = getItemAsDamaged(DIAMOND_CHESTPLATE.getDefaultInstance(), 500); + prepareChest( + helper, + pos.east(), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + externalStorage.setFuzzyMode(true); + externalStorage.setFilters(Set.of(asResource(DIAMOND_CHESTPLATE.getDefaultInstance()))); + externalStorage.setFilterMode(FilterMode.BLOCK); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, asResource(DIAMOND_CHESTPLATE), 1, false))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, asResource(damagedDiamondChestplate), 1, false))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(networkIsAvailable(helper, pos, network -> + insert(helper, network, asResource(DIRT), 10))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(DIRT), 10) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(COBBLESTONE), 3), + new ResourceAmount(asResource(DIRT), 10) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldExtractItem(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareChest( + helper, + pos.east(), + DIRT.getDefaultInstance().copyWithCount(10), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + // Assert + sequence + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenExecute(networkIsAvailable(helper, pos, network -> extract(helper, network, DIRT, 5))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(DIRT), 5), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 5), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldPropagateExternalExtractions(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareChest( + helper, + pos.east(), + STONE.getDefaultInstance().copyWithCount(2), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 4), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenExecute(() -> removeItemFromChest( + helper, + pos.east(), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + )) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 4) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldPropagatePartialExternalExtractions(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareChest( + helper, + pos.east(), + STONE.getDefaultInstance().copyWithCount(2), + DIRT.getDefaultInstance().copyWithCount(10), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 4), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenExecute(() -> removeItemFromChest( + helper, + pos.east(), + DIRT.getDefaultInstance().copyWithCount(5) + )) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 5), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 4), + new ResourceAmount(asResource(DIRT), 5), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldPropagateExternalInsertions(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareChest( + helper, + pos.east(), + STONE.getDefaultInstance().copyWithCount(2), + DIRT.getDefaultInstance().copyWithCount(10) + ); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 10) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 4), + new ResourceAmount(asResource(DIRT), 10) + )) + .thenExecute(() -> addItemToChest( + helper, + pos.east(), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + )) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 4), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldNoLongerExposeItemsWhenExternalBlockIsBroken(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareChest( + helper, + pos.east(), + STONE.getDefaultInstance().copyWithCount(2), + DIRT.getDefaultInstance().copyWithCount(10), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 4), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenExecute(() -> helper.setBlock(pos.east(), Blocks.AIR)) + .thenWaitUntil(() -> helper.assertBlockNotPresent(Blocks.CHEST, pos.east())) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldRespectRedstoneMode(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 2))); + + // Act + prepareChest( + helper, + pos.east(), + STONE.getDefaultInstance().copyWithCount(2), + DIRT.getDefaultInstance().copyWithCount(10), + COBBLESTONE.getDefaultInstance().copyWithCount(3) + ); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 4), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenExecute(() -> externalStorage.setRedstoneMode(RedstoneMode.HIGH)) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 2) + )) + .thenExecute(() -> helper.setBlock(pos.west(), Blocks.REDSTONE_BLOCK)) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 2), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 4), + new ResourceAmount(asResource(DIRT), 10), + new ResourceAmount(asResource(COBBLESTONE), 3) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldVoidExcess(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { })); + + // Act + prepareChest( + helper, + pos.east(), + createStacks(STONE, 64, 27) + ); + + externalStorage.setPriority(1); + externalStorage.setFilters(Set.of(asResource(STONE))); + externalStorage.setFilterMode(FilterMode.ALLOW); + externalStorage.setVoidExcess(true); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 64 * 27) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 64 * 27) + )) + .thenExecute(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 10))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 64 * 27) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 64 * 27) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldRespectInsertAccessMode(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, false, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { })); + + // Act + prepareChest( + helper, + pos.east(), + STONE.getDefaultInstance().copyWithCount(64) + ); + + externalStorage.setAccessMode(AccessMode.INSERT); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 64) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 64) + )) + .thenExecute(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 10))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 74) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 74) + )) + .thenExecute(networkIsAvailable(helper, pos, network -> extract(helper, network, STONE, 10, false))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 74) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 74) + )) + .thenSucceed(); + }); + } + + @GameTest(template = "empty_15x15") + public static void shouldRespectExtractAccessMode(final GameTestHelper helper) { + preparePlot(helper, Direction.EAST, false, (externalStorage, pos, sequence) -> { + // Arrange + sequence.thenWaitUntil(networkIsAvailable(helper, pos, network -> { })); + + // Act + prepareChest( + helper, + pos.east(), + STONE.getDefaultInstance().copyWithCount(64) + ); + + externalStorage.setAccessMode(AccessMode.EXTRACT); + + // Assert + sequence + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 64) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 64) + )) + .thenExecute(networkIsAvailable(helper, pos, network -> insert(helper, network, STONE, 10, false))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 64) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 64) + )) + .thenExecute(networkIsAvailable(helper, pos, network -> extract(helper, network, STONE, 10))) + .thenWaitUntil(containerContainsExactly( + helper, + pos.east(), + new ResourceAmount(asResource(STONE), 54) + )) + .thenWaitUntil(storageContainsExactly( + helper, + pos, + new ResourceAmount(asResource(STONE), 54) + )) + .thenSucceed(); + }); + } +} diff --git a/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageTestPlots.java b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageTestPlots.java new file mode 100644 index 000000000..de71d1bf0 --- /dev/null +++ b/refinedstorage-neoforge/src/test/java/com/refinedmods/refinedstorage/common/storage/externalstorage/ExternalStorageTestPlots.java @@ -0,0 +1,54 @@ +package com.refinedmods.refinedstorage.common.storage.externalstorage; + +import com.refinedmods.refinedstorage.common.storage.FluidStorageVariant; +import com.refinedmods.refinedstorage.common.storage.ItemStorageVariant; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.gametest.framework.GameTestSequence; +import org.apache.commons.lang3.function.TriConsumer; + +import static com.refinedmods.refinedstorage.common.GameTestUtil.RSBLOCKS; +import static com.refinedmods.refinedstorage.common.GameTestUtil.requireBlockEntity; +import static net.minecraft.core.BlockPos.ZERO; + +final class ExternalStorageTestPlots { + private ExternalStorageTestPlots() { + } + + static void preparePlot(final GameTestHelper helper, + final Direction direction, + final TriConsumer< + AbstractExternalStorageBlockEntity, + BlockPos, + GameTestSequence> consumer) { + preparePlot(helper, direction, true, consumer); + } + + static void preparePlot(final GameTestHelper helper, + final Direction direction, + final boolean itemStorage, + final TriConsumer< + AbstractExternalStorageBlockEntity, + BlockPos, + GameTestSequence> consumer) { + helper.setBlock(ZERO.above(), RSBLOCKS.getCreativeController().getDefault()); + if (itemStorage) { + helper.setBlock(ZERO.above().above(), RSBLOCKS.getItemStorageBlock(ItemStorageVariant.ONE_K)); + } else { + helper.setBlock(ZERO.above().above(), RSBLOCKS.getCable().getDefault()); + } + helper.setBlock( + ZERO.above().above().north(), + RSBLOCKS.getFluidStorageBlock(FluidStorageVariant.SIXTY_FOUR_B) + ); + final BlockPos externalStoragePos = ZERO.above().above().above(); + helper.setBlock(externalStoragePos, RSBLOCKS.getExternalStorage().getDefault().rotated(direction)); + consumer.accept( + requireBlockEntity(helper, externalStoragePos, AbstractExternalStorageBlockEntity.class), + externalStoragePos, + helper.startSequence() + ); + } +}