diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d20a8dc2a..71df53dcf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,12 +55,9 @@ jobs: GITHUB_USER: ${{ github.actor }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: 'Test' - env: - COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} - if: ${{ env.COVERALLS_REPO_TOKEN }} - run: ./gradlew test jacocoTestReport coveralls - - name: 'Game Test' - run: ./gradlew runGameTestServer + run: ./gradlew test runGameTestServer jacocoTestReport + - name: 'Submit coverage results' + uses: coverallsapp/github-action@v2 - name: 'Deploy as GitHub CI artifacts' uses: actions/upload-artifact@v4 with: diff --git a/README.md b/README.md index eba932a1c..ade955d82 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ## Integrated Tunnels [![Build Status](https://github.com/CyclopsMC/IntegratedTunnels/workflows/CI/badge.svg)](https://github.com/CyclopsMC/IntegratedTunnels/actions?query=workflow%3ACI) +[![Coverage Status](https://coveralls.io/repos/github/CyclopsMC/IntegratedTunnels/badge.svg)](https://coveralls.io/github/CyclopsMC/IntegratedTunnels) [![Download](https://img.shields.io/static/v1?label=Maven&message=GitHub%20Packages&color=blue)](https://github.com/CyclopsMC/packages/packages/770038) [![Crowdin](https://badges.crowdin.net/cyclopsmc-integratedtunnels/localized.svg)](https://crowdin.com/project/cyclopsmc-integratedtunnels) [![CurseForge](http://cf.way2muchnoise.eu/full_251389_downloads.svg)](http://minecraft.curseforge.com/projects/251389) diff --git a/build.gradle b/build.gradle index 8a8c393de..0fa01b813 100644 --- a/build.gradle +++ b/build.gradle @@ -401,12 +401,25 @@ idea { } jacocoTestReport { + // Include unit and game test coverage + executionData fileTree(project.buildDir).include("jacoco/*.exec") reports { xml.required = true html.required = true } } +// Also measure coverage for game tests +tasks.whenTaskAdded { task -> + if (task.name.equals('runGameTestServer')) { + jacocoTestReport.dependsOn test, task + jacoco { + toolVersion = "0.8.12" + applyTo task + } + } +} + spotless { java { target 'src/*/java/org/cyclops/**/*.java' diff --git a/gradle.properties b/gradle.properties index ec44b21b4..748d55dab 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,7 +26,7 @@ neoforge_loader_version_range=[4,) neoforge_update_json_url=https://raw.githubusercontent.com/CyclopsMC/Versions/master/neoforge_update/integrated-tunnels.json # Dependencies -cyclopscore_version=1.25.1-627 -integrateddynamics_version=1.23.2-832 +cyclopscore_version=1.25.5-643 +integrateddynamics_version=1.24.1-993 integratedtunnelscompat_version=1.0.0-45 commoncapabilities_version=2.9.3-147 diff --git a/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsEnergy.java b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsEnergy.java new file mode 100644 index 000000000..21e6b4fe5 --- /dev/null +++ b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsEnergy.java @@ -0,0 +1,193 @@ +package org.cyclops.integratedtunnels.gametest; + +import net.minecraft.core.BlockPos; +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.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; +import org.cyclops.integrateddynamics.RegistryEntries; +import org.cyclops.integrateddynamics.api.part.PartPos; +import org.cyclops.integrateddynamics.api.part.write.IPartStateWriter; +import org.cyclops.integrateddynamics.blockentity.BlockEntityEnergyBattery; +import org.cyclops.integrateddynamics.core.block.IgnoredBlockStatus; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypeLong; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes; +import org.cyclops.integrateddynamics.core.helper.PartHelpers; +import org.cyclops.integratedtunnels.Reference; +import org.cyclops.integratedtunnels.part.PartTypes; +import org.cyclops.integratedtunnels.part.aspect.TunnelAspects; + +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.createVariableForValue; +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.placeVariableInWriter; + +@GameTestHolder(Reference.MOD_ID) +@PrefixGameTestTemplate(false) +public class GameTestsEnergy { + + public static final String TEMPLATE_EMPTY = "empty10"; + public static final int TIMEOUT = 2000; + public static final BlockPos POS = BlockPos.ZERO.offset(2, 0, 2); + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testEnergyImporterToInterfaceBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place energy importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_ENERGY, new ItemStack(PartTypes.IMPORTER_ENERGY.getItem())); + + // Place energy interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ENERGY, new ItemStack(PartTypes.INTERFACE_ENERGY.getItem())); + + // Place batteries + helper.setBlock(POS.west(), RegistryEntries.BLOCK_ENERGY_BATTERY.get()); + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_ENERGY_BATTERY.get()); + + // Insert energy in interface battery + BlockEntityEnergyBattery batteryIn = helper.getBlockEntity(POS.west()); + batteryIn.setEnergyStored(10_000); + + // Place empty variable in importer + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Energy.BOOLEAN_IMPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if energy is moved + BlockEntityEnergyBattery batteryOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(batteryOut.getEnergyStored(), 10_000, "Battery out does not contain energy"); + helper.assertValueEqual(batteryIn.getEnergyStored(), 0, "Battery in was not drained"); + + // Check importer state + IPartStateWriter partStateWriter = (IPartStateWriter) PartHelpers.getPart(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)).getState(); + helper.assertFalse(partStateWriter.isDeactivated(), "Importer is deactivated"); + helper.assertValueEqual( + PartTypes.IMPORTER_ENERGY.getBlockState(PartHelpers.getPartContainerChecked(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)), Direction.WEST).getValue(IgnoredBlockStatus.STATUS), + IgnoredBlockStatus.Status.ACTIVE, + "Block status is incorrect" + ); + helper.assertValueEqual(partStateWriter.getActiveAspect(), TunnelAspects.Write.Energy.BOOLEAN_IMPORT, "Active aspect is incorrect"); + helper.assertTrue(partStateWriter.getErrors(TunnelAspects.Write.Energy.BOOLEAN_IMPORT).isEmpty(), "Active aspect has errors"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testEnergyInterfaceToExporterBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place energy interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.INTERFACE_ENERGY, new ItemStack(PartTypes.INTERFACE_ENERGY.getItem())); + + // Place energy exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.EXPORTER_ENERGY, new ItemStack(PartTypes.EXPORTER_ENERGY.getItem())); + + // Place batteries + helper.setBlock(POS.west(), RegistryEntries.BLOCK_ENERGY_BATTERY.get()); + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_ENERGY_BATTERY.get()); + + // Insert energy in interface battery + BlockEntityEnergyBattery batteryIn = helper.getBlockEntity(POS.west()); + batteryIn.setEnergyStored(10_000); + + // Place empty variable in exporter + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST), TunnelAspects.Write.Energy.BOOLEAN_EXPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if energy is moved + BlockEntityEnergyBattery batteryOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(batteryOut.getEnergyStored(), 10_000, "Battery out does not contain energy"); + helper.assertValueEqual(batteryIn.getEnergyStored(), 0, "Battery in was not drained"); + + // Check importer state + IPartStateWriter partStateWriter = (IPartStateWriter) PartHelpers.getPart(PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST)).getState(); + helper.assertFalse(partStateWriter.isDeactivated(), "Exporter is deactivated"); + helper.assertValueEqual( + PartTypes.EXPORTER_ENERGY.getBlockState(PartHelpers.getPartContainerChecked(PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST)), Direction.EAST).getValue(IgnoredBlockStatus.STATUS), + IgnoredBlockStatus.Status.ACTIVE, + "Block status is incorrect" + ); + helper.assertValueEqual(partStateWriter.getActiveAspect(), TunnelAspects.Write.Energy.BOOLEAN_EXPORT, "Active aspect is incorrect"); + helper.assertTrue(partStateWriter.getErrors(TunnelAspects.Write.Energy.BOOLEAN_EXPORT).isEmpty(), "Active aspect has errors"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testEnergyImporterToInterfaceToExporterBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_ENERGY, new ItemStack(PartTypes.IMPORTER_ENERGY.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ENERGY, new ItemStack(PartTypes.INTERFACE_ENERGY.getItem())); + + // Place item exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_ENERGY, new ItemStack(PartTypes.EXPORTER_ENERGY.getItem())); + + // Place batteries + helper.setBlock(POS.west(), RegistryEntries.BLOCK_ENERGY_BATTERY.get()); + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_ENERGY_BATTERY.get()); + helper.setBlock(POS.east().north(), RegistryEntries.BLOCK_ENERGY_BATTERY.get()); + + // Insert energy in interface battery + BlockEntityEnergyBattery batteryIn = helper.getBlockEntity(POS.west()); + batteryIn.setEnergyStored(10_000); + + // Place empty variable in importer + ItemStack variableAspectImporter = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Energy.BOOLEAN_IMPORT, variableAspectImporter); + + // Place empty variable in exporter + ItemStack variableAspectExporter = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.Energy.BOOLEAN_EXPORT, variableAspectExporter); + + helper.succeedWhen(() -> { + // Check if energy is moved + BlockEntityEnergyBattery batteryInterface = helper.getBlockEntity(POS.east().east()); + BlockEntityEnergyBattery batteryOut = helper.getBlockEntity(POS.east().north()); + helper.assertValueEqual(batteryInterface.getEnergyStored(), 0, "Battery interface was not drained"); + helper.assertValueEqual(batteryOut.getEnergyStored(), 10_000, "Battery out does not contain energy"); + helper.assertValueEqual(batteryIn.getEnergyStored(), 0, "Battery in was not drained"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testEnergyImporterToInterfaceLong(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_ENERGY, new ItemStack(PartTypes.IMPORTER_ENERGY.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ENERGY, new ItemStack(PartTypes.INTERFACE_ENERGY.getItem())); + + // Place batteries + helper.setBlock(POS.west(), RegistryEntries.BLOCK_ENERGY_BATTERY.get()); + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_ENERGY_BATTERY.get()); + + // Insert energy in importer battery + BlockEntityEnergyBattery batteryIn = helper.getBlockEntity(POS.west()); + batteryIn.setEnergyStored(10_000); + + // Place empty variable in importer + ItemStack variableAspect = createVariableForValue(helper.getLevel(), ValueTypes.LONG, ValueTypeLong.ValueLong.of(10)); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Energy.LONG_IMPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if energy is moved + BlockEntityEnergyBattery batteryOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(batteryOut.getEnergyStored(), 10_000, "Battery out does not contain energy"); + helper.assertValueEqual(batteryIn.getEnergyStored(), 0, "Battery in was not drained"); + }); + } + +} diff --git a/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsFluids.java b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsFluids.java new file mode 100644 index 000000000..5bbe0dc9c --- /dev/null +++ b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsFluids.java @@ -0,0 +1,227 @@ +package org.cyclops.integratedtunnels.gametest; + +import net.minecraft.core.BlockPos; +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.material.Fluids; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; +import org.cyclops.integrateddynamics.RegistryEntries; +import org.cyclops.integrateddynamics.api.part.PartPos; +import org.cyclops.integrateddynamics.api.part.write.IPartStateWriter; +import org.cyclops.integrateddynamics.blockentity.BlockEntityDryingBasin; +import org.cyclops.integrateddynamics.core.block.IgnoredBlockStatus; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueObjectTypeFluidStack; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes; +import org.cyclops.integrateddynamics.core.helper.PartHelpers; +import org.cyclops.integratedtunnels.Reference; +import org.cyclops.integratedtunnels.part.PartTypes; +import org.cyclops.integratedtunnels.part.aspect.TunnelAspects; + +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.createVariableForValue; +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.placeVariableInWriter; + +@GameTestHolder(Reference.MOD_ID) +@PrefixGameTestTemplate(false) +public class GameTestsFluids { + + public static final String TEMPLATE_EMPTY = "empty10"; + public static final int TIMEOUT = 2000; + public static final BlockPos POS = BlockPos.ZERO.offset(2, 0, 2); + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testFluidImporterToInterfaceBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place fluid importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_FLUID, new ItemStack(PartTypes.IMPORTER_FLUID.getItem())); + + // Place fluid interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_FLUID, new ItemStack(PartTypes.INTERFACE_FLUID.getItem())); + + // Place drying basins + helper.setBlock(POS.west(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + + // Insert fluid in importer basin + BlockEntityDryingBasin basinIn = helper.getBlockEntity(POS.west()); + basinIn.getTank().setFluid(new FluidStack(Fluids.WATER, 1_000)); + + // Place empty variable in importer + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Fluid.BOOLEAN_IMPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if fluid is moved + BlockEntityDryingBasin basinOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(basinOut.getTank().getFluidAmount(), 1_000, "Basin out does not contain energy"); + helper.assertValueEqual(basinIn.getTank().getFluidAmount(), 0, "Basin in was not drained"); + + // Check importer state + IPartStateWriter partStateWriter = (IPartStateWriter) PartHelpers.getPart(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)).getState(); + helper.assertFalse(partStateWriter.isDeactivated(), "Importer is deactivated"); + helper.assertValueEqual( + PartTypes.IMPORTER_FLUID.getBlockState(PartHelpers.getPartContainerChecked(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)), Direction.WEST).getValue(IgnoredBlockStatus.STATUS), + IgnoredBlockStatus.Status.ACTIVE, + "Block status is incorrect" + ); + helper.assertValueEqual(partStateWriter.getActiveAspect(), TunnelAspects.Write.Fluid.BOOLEAN_IMPORT, "Active aspect is incorrect"); + helper.assertTrue(partStateWriter.getErrors(TunnelAspects.Write.Fluid.BOOLEAN_IMPORT).isEmpty(), "Active aspect has errors"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testFluidInterfaceToExporterBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place fluid interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.INTERFACE_FLUID, new ItemStack(PartTypes.INTERFACE_FLUID.getItem())); + + // Place fluid exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.EXPORTER_FLUID, new ItemStack(PartTypes.EXPORTER_FLUID.getItem())); + + // Place drying basins + helper.setBlock(POS.west(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + + // Insert items in interface chest + BlockEntityDryingBasin basinIn = helper.getBlockEntity(POS.west()); + basinIn.getTank().setFluid(new FluidStack(Fluids.WATER, 1_000)); + + // Place empty variable in exporter + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST), TunnelAspects.Write.Fluid.BOOLEAN_EXPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if fluid is moved + BlockEntityDryingBasin basinOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(basinOut.getTank().getFluidAmount(), 1_000, "Basin out does not contain energy"); + helper.assertValueEqual(basinIn.getTank().getFluidAmount(), 0, "Basin in was not drained"); + + // Check importer state + IPartStateWriter partStateWriter = (IPartStateWriter) PartHelpers.getPart(PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST)).getState(); + helper.assertFalse(partStateWriter.isDeactivated(), "Exporter is deactivated"); + helper.assertValueEqual( + PartTypes.EXPORTER_FLUID.getBlockState(PartHelpers.getPartContainerChecked(PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST)), Direction.EAST).getValue(IgnoredBlockStatus.STATUS), + IgnoredBlockStatus.Status.ACTIVE, + "Block status is incorrect" + ); + helper.assertValueEqual(partStateWriter.getActiveAspect(), TunnelAspects.Write.Fluid.BOOLEAN_EXPORT, "Active aspect is incorrect"); + helper.assertTrue(partStateWriter.getErrors(TunnelAspects.Write.Fluid.BOOLEAN_EXPORT).isEmpty(), "Active aspect has errors"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testFluidImporterToInterfaceToExporterBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place fluid importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_FLUID, new ItemStack(PartTypes.IMPORTER_FLUID.getItem())); + + // Place fluid interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_FLUID, new ItemStack(PartTypes.INTERFACE_FLUID.getItem())); + + // Place fluid exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_FLUID, new ItemStack(PartTypes.EXPORTER_FLUID.getItem())); + + // Place drying basins + helper.setBlock(POS.west(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + helper.setBlock(POS.east().north(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + + // Insert fluids in interface basin + BlockEntityDryingBasin basinIn = helper.getBlockEntity(POS.west()); + basinIn.getTank().setFluid(new FluidStack(Fluids.WATER, 1_000)); + + // Place empty variable in importer + ItemStack variableAspectImporter = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Fluid.BOOLEAN_IMPORT, variableAspectImporter); + + // Place empty variable in exporter + ItemStack variableAspectExporter = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.Fluid.BOOLEAN_EXPORT, variableAspectExporter); + + helper.succeedWhen(() -> { + // Check if fluid is moved + BlockEntityDryingBasin basinInterface = helper.getBlockEntity(POS.east().east()); + BlockEntityDryingBasin basinOut = helper.getBlockEntity(POS.east().north()); + helper.assertValueEqual(basinInterface.getTank().getFluidAmount(), 0, "Basin interface was not drained"); + helper.assertValueEqual(basinOut.getTank().getFluidAmount(), 1_000, "Basin out does not contain energy"); + helper.assertValueEqual(basinIn.getTank().getFluidAmount(), 0, "Basin in was not drained"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testFluidsImporterToInterfaceFluidCorrect(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place fluid importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_FLUID, new ItemStack(PartTypes.IMPORTER_FLUID.getItem())); + + // Place fluid interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_FLUID, new ItemStack(PartTypes.INTERFACE_FLUID.getItem())); + + // Place drying basins + helper.setBlock(POS.west(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + + // Insert fluids in importer basin + BlockEntityDryingBasin basinIn = helper.getBlockEntity(POS.west()); + basinIn.getTank().setFluid(new FluidStack(Fluids.WATER, 1_000)); + + // Place empty variable in importer + ItemStack variableAspect = createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_FLUIDSTACK, ValueObjectTypeFluidStack.ValueFluidStack.of(new FluidStack(Fluids.WATER, 100))); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Fluid.FLUIDSTACK_IMPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if fluid is moved + BlockEntityDryingBasin basinOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(basinOut.getTank().getFluidAmount(), 1_000, "Basin out does not contain energy"); + helper.assertValueEqual(basinIn.getTank().getFluidAmount(), 0, "Basin in was not drained"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testFluidsImporterToInterfaceFluidIncorrect(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place fluid importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_FLUID, new ItemStack(PartTypes.IMPORTER_FLUID.getItem())); + + // Place fluid interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_FLUID, new ItemStack(PartTypes.INTERFACE_FLUID.getItem())); + + // Place drying basins + helper.setBlock(POS.west(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + + // Insert fluids in importer basin + BlockEntityDryingBasin basinIn = helper.getBlockEntity(POS.west()); + basinIn.getTank().setFluid(new FluidStack(Fluids.WATER, 1_000)); + + // Place empty variable in importer + ItemStack variableAspect = createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_FLUIDSTACK, ValueObjectTypeFluidStack.ValueFluidStack.of(new FluidStack(Fluids.LAVA, 100))); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Fluid.FLUIDSTACK_IMPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if fluid is not moved + BlockEntityDryingBasin basinOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(basinOut.getTank().getFluidAmount(), 0, "Basin out was filled"); + helper.assertValueEqual(basinIn.getTank().getFluidAmount(), 1_000, "Basin in was drained"); + }); + } + +} diff --git a/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsItems.java b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsItems.java new file mode 100644 index 000000000..dae5789ed --- /dev/null +++ b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsItems.java @@ -0,0 +1,302 @@ +package org.cyclops.integratedtunnels.gametest; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.ChestBlockEntity; +import net.minecraft.world.level.block.entity.HopperBlockEntity; +import net.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; +import org.cyclops.integrateddynamics.RegistryEntries; +import org.cyclops.integrateddynamics.api.part.PartPos; +import org.cyclops.integrateddynamics.api.part.PartTarget; +import org.cyclops.integrateddynamics.api.part.aspect.property.IAspectProperties; +import org.cyclops.integrateddynamics.api.part.write.IPartStateWriter; +import org.cyclops.integrateddynamics.core.block.IgnoredBlockStatus; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueObjectTypeItemStack; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypeInteger; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes; +import org.cyclops.integrateddynamics.core.helper.PartHelpers; +import org.cyclops.integratedtunnels.Reference; +import org.cyclops.integratedtunnels.part.PartTypes; +import org.cyclops.integratedtunnels.part.aspect.TunnelAspectWriteBuilders; +import org.cyclops.integratedtunnels.part.aspect.TunnelAspects; + +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.createVariableForValue; +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.placeVariableInWriter; + +@GameTestHolder(Reference.MOD_ID) +@PrefixGameTestTemplate(false) +public class GameTestsItems { + + public static final String TEMPLATE_EMPTY = "empty10"; + public static final int TIMEOUT = 2000; + public static final BlockPos POS = BlockPos.ZERO.offset(2, 0, 2); + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testItemsImporterToInterfaceBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_ITEM, new ItemStack(PartTypes.IMPORTER_ITEM.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place chests + helper.setBlock(POS.west(), Blocks.CHEST); + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Insert items in importer chest + ChestBlockEntity chestIn = helper.getBlockEntity(POS.west()); + chestIn.setItem(0, new ItemStack(Items.WHITE_WOOL)); + chestIn.setItem(1, new ItemStack(Items.ACACIA_LEAVES)); + chestIn.setItem(2, new ItemStack(Items.DIAMOND_PICKAXE)); + + // Place empty variable in importer + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Item.BOOLEAN_IMPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if items are moved + helper.assertContainerContains(POS.east().east(), Items.WHITE_WOOL); + helper.assertContainerContains(POS.east().east(), Items.ACACIA_LEAVES); + helper.assertContainerContains(POS.east().east(), Items.DIAMOND_PICKAXE); + helper.assertContainerEmpty(POS.west()); + + // Check importer state + IPartStateWriter partStateWriter = (IPartStateWriter) PartHelpers.getPart(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)).getState(); + helper.assertFalse(partStateWriter.isDeactivated(), "Importer is deactivated"); + helper.assertValueEqual( + PartTypes.IMPORTER_ITEM.getBlockState(PartHelpers.getPartContainerChecked(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)), Direction.WEST).getValue(IgnoredBlockStatus.STATUS), + IgnoredBlockStatus.Status.ACTIVE, + "Block status is incorrect" + ); + helper.assertValueEqual(partStateWriter.getActiveAspect(), TunnelAspects.Write.Item.BOOLEAN_IMPORT, "Active aspect is incorrect"); + helper.assertTrue(partStateWriter.getErrors(TunnelAspects.Write.Item.BOOLEAN_IMPORT).isEmpty(), "Active aspect has errors"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testItemsInterfaceToExporterBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place item exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.EXPORTER_ITEM, new ItemStack(PartTypes.EXPORTER_ITEM.getItem())); + + // Place chests + helper.setBlock(POS.west(), Blocks.CHEST); + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Insert items in interface chest + ChestBlockEntity chestIn = helper.getBlockEntity(POS.west()); + chestIn.setItem(0, new ItemStack(Items.WHITE_WOOL)); + chestIn.setItem(1, new ItemStack(Items.ACACIA_LEAVES)); + chestIn.setItem(2, new ItemStack(Items.DIAMOND_PICKAXE)); + + // Place empty variable in exporter + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST), TunnelAspects.Write.Item.BOOLEAN_EXPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if items are moved + helper.assertContainerContains(POS.east().east(), Items.WHITE_WOOL); + helper.assertContainerContains(POS.east().east(), Items.ACACIA_LEAVES); + helper.assertContainerContains(POS.east().east(), Items.DIAMOND_PICKAXE); + helper.assertContainerEmpty(POS.west()); + + // Check importer state + IPartStateWriter partStateWriter = (IPartStateWriter) PartHelpers.getPart(PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST)).getState(); + helper.assertFalse(partStateWriter.isDeactivated(), "Exporter is deactivated"); + helper.assertValueEqual( + PartTypes.EXPORTER_ITEM.getBlockState(PartHelpers.getPartContainerChecked(PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST)), Direction.EAST).getValue(IgnoredBlockStatus.STATUS), + IgnoredBlockStatus.Status.ACTIVE, + "Block status is incorrect" + ); + helper.assertValueEqual(partStateWriter.getActiveAspect(), TunnelAspects.Write.Item.BOOLEAN_EXPORT, "Active aspect is incorrect"); + helper.assertTrue(partStateWriter.getErrors(TunnelAspects.Write.Item.BOOLEAN_EXPORT).isEmpty(), "Active aspect has errors"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testItemsImporterToInterfaceToExporterBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_ITEM, new ItemStack(PartTypes.IMPORTER_ITEM.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place item exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_ITEM, new ItemStack(PartTypes.EXPORTER_ITEM.getItem())); + + // Place chests + helper.setBlock(POS.west(), Blocks.CHEST); + helper.setBlock(POS.east().east(), Blocks.CHEST); + helper.setBlock(POS.east().north(), Blocks.CHEST); + + // Insert items in importer chest + ChestBlockEntity chestIn = helper.getBlockEntity(POS.west()); + chestIn.setItem(0, new ItemStack(Items.WHITE_WOOL)); + chestIn.setItem(1, new ItemStack(Items.ACACIA_LEAVES)); + chestIn.setItem(2, new ItemStack(Items.DIAMOND_PICKAXE)); + + // Place empty variable in importer + ItemStack variableAspectImporter = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Item.BOOLEAN_IMPORT, variableAspectImporter); + + // Place empty variable in exporter + ItemStack variableAspectExporter = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.Item.BOOLEAN_EXPORT, variableAspectExporter); + + helper.succeedWhen(() -> { + // Check if items are moved + helper.assertContainerContains(POS.east().north(), Items.WHITE_WOOL); + helper.assertContainerContains(POS.east().north(), Items.ACACIA_LEAVES); + helper.assertContainerContains(POS.east().north(), Items.DIAMOND_PICKAXE); + helper.assertContainerEmpty(POS.west()); + helper.assertContainerEmpty(POS.east().east()); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testItemsImporterToInterfaceItem(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_ITEM, new ItemStack(PartTypes.IMPORTER_ITEM.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place chests + helper.setBlock(POS.west(), Blocks.CHEST); + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Insert items in importer chest + ChestBlockEntity chestIn = helper.getBlockEntity(POS.west()); + chestIn.setItem(0, new ItemStack(Items.WHITE_WOOL)); + chestIn.setItem(1, new ItemStack(Items.ACACIA_LEAVES)); + chestIn.setItem(2, new ItemStack(Items.DIAMOND_PICKAXE)); + + // Place empty variable in importer + ItemStack variableAspect = createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_ITEMSTACK, ValueObjectTypeItemStack.ValueItemStack.of(new ItemStack(Items.ACACIA_LEAVES))); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Item.ITEMSTACK_IMPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if items are moved + ChestBlockEntity chestOut = helper.getBlockEntity(POS.east().east()); + helper.assertFalse(chestIn.getItem(0).isEmpty(), "Incorrect input item was moved"); + helper.assertTrue(chestIn.getItem(1).isEmpty(), "Incorrect input item was moved"); + helper.assertFalse(chestIn.getItem(2).isEmpty(), "Incorrect input item was moved"); + helper.assertFalse(chestOut.getItem(0).isEmpty(), "Incorrect output item was moved"); + helper.assertTrue(chestOut.getItem(1).isEmpty(), "Incorrect output item was moved"); + helper.assertContainerContains(POS.west(), Items.WHITE_WOOL); + helper.assertContainerContains(POS.east().east(), Items.ACACIA_LEAVES); + helper.assertContainerContains(POS.west(), Items.DIAMOND_PICKAXE); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testItemsImporterToInterfaceBooleanReducedRate(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_ITEM, new ItemStack(PartTypes.IMPORTER_ITEM.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place chests + helper.setBlock(POS.west(), Blocks.CHEST); + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Insert items in importer chest + ChestBlockEntity chestIn = helper.getBlockEntity(POS.west()); + chestIn.setItem(0, new ItemStack(Items.WHITE_WOOL)); + chestIn.setItem(1, new ItemStack(Items.ACACIA_LEAVES)); + chestIn.setItem(2, new ItemStack(Items.DIAMOND_PICKAXE)); + + // Place empty variable in importer + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + PartPos posImporter = PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST); + placeVariableInWriter(helper.getLevel(), posImporter, TunnelAspects.Write.Item.BOOLEAN_IMPORT, variableAspect); + + // Reduce item transfer rate of importer + PartHelpers.PartStateHolder partStateHolder = PartHelpers.getPart(posImporter); + IAspectProperties properties = TunnelAspects.Write.Item.BOOLEAN_IMPORT.getProperties(partStateHolder.getPart(), PartTarget.fromCenter(posImporter), partStateHolder.getState()); + properties.setValue(TunnelAspectWriteBuilders.Item.PROP_RATE, ValueTypeInteger.ValueInteger.of(1)); + partStateHolder.getState().setAspectProperties(TunnelAspects.Write.Item.BOOLEAN_IMPORT, properties); + + helper.succeedWhen(() -> { + // Check if items are moved + helper.assertContainerContains(POS.east().east(), Items.WHITE_WOOL); + helper.assertContainerContains(POS.east().east(), Items.ACACIA_LEAVES); + helper.assertContainerContains(POS.east().east(), Items.DIAMOND_PICKAXE); + helper.assertContainerEmpty(POS.west()); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testItemsNoMoveDisconnectedFakeCable(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + // No cable for interface! + + // Place item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_ITEM, new ItemStack(PartTypes.IMPORTER_ITEM.getItem())); + + // Place item interface as player + Player player = helper.makeMockPlayer(GameType.SURVIVAL); + ItemStack itemStack = new ItemStack(PartTypes.INTERFACE_ITEM.getItem()); + player.setItemInHand(InteractionHand.MAIN_HAND, itemStack); + helper.placeAt(player, itemStack, POS.east().east().east(), Direction.WEST); + + // Place chests + helper.setBlock(POS.west(), Blocks.CHEST); + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place hopper above input chest + helper.setBlock(POS.west().above(), Blocks.HOPPER); + + // Insert items in input hopper + HopperBlockEntity hopperIn = helper.getBlockEntity(POS.west().above()); + hopperIn.setItem(0, new ItemStack(Items.WHITE_WOOL)); + hopperIn.setItem(1, new ItemStack(Items.ACACIA_LEAVES)); + hopperIn.setItem(2, new ItemStack(Items.DIAMOND_PICKAXE)); + + // Place empty variable in importer + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Item.BOOLEAN_IMPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if items are not moved + helper.assertContainerContains(POS.west(), Items.WHITE_WOOL); + helper.assertContainerContains(POS.west(), Items.ACACIA_LEAVES); + helper.assertContainerContains(POS.west(), Items.DIAMOND_PICKAXE); + helper.assertContainerEmpty(POS.east().east()); + }); + } + +} diff --git a/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsPlayerSimulator.java b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsPlayerSimulator.java new file mode 100644 index 000000000..9a3350e49 --- /dev/null +++ b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsPlayerSimulator.java @@ -0,0 +1,202 @@ +package org.cyclops.integratedtunnels.gametest; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LeverBlock; +import net.minecraft.world.level.block.entity.ChestBlockEntity; +import net.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; +import org.cyclops.integrateddynamics.RegistryEntries; +import org.cyclops.integrateddynamics.api.part.PartPos; +import org.cyclops.integrateddynamics.api.part.PartTarget; +import org.cyclops.integrateddynamics.api.part.aspect.property.IAspectProperties; +import org.cyclops.integrateddynamics.api.part.write.IPartStateWriter; +import org.cyclops.integrateddynamics.core.block.IgnoredBlockStatus; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueObjectTypeItemStack; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypeBoolean; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes; +import org.cyclops.integrateddynamics.core.helper.PartHelpers; +import org.cyclops.integratedtunnels.Reference; +import org.cyclops.integratedtunnels.part.PartTypes; +import org.cyclops.integratedtunnels.part.aspect.TunnelAspectWriteBuilders; +import org.cyclops.integratedtunnels.part.aspect.TunnelAspects; + +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.createVariableForValue; +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.placeVariableInWriter; + +@GameTestHolder(Reference.MOD_ID) +@PrefixGameTestTemplate(false) +public class GameTestsPlayerSimulator { + + public static final String TEMPLATE_EMPTY = "empty10"; + public static final int TIMEOUT = 2000; + public static final BlockPos POS = BlockPos.ZERO.offset(2, 0, 2); + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testPlayerSimulatorMilkCow(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place player simulator + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.PLAYER_SIMULATOR, new ItemStack(PartTypes.PLAYER_SIMULATOR.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place cow before player simulator + helper.spawn(EntityType.COW, POS.west()); + + // Insert some items into interface + ChestBlockEntity chestIn = helper.getBlockEntity(POS.east().east()); + chestIn.setItem(0, new ItemStack(Items.WHITE_WOOL)); + chestIn.setItem(1, new ItemStack(Items.BUCKET)); + chestIn.setItem(2, new ItemStack(Items.DIAMOND_PICKAXE)); + + // Place bucket variable in click item + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Player.CLICK_ITEM_ITEMSTACK, createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_ITEMSTACK, ValueObjectTypeItemStack.ValueItemStack.of(new ItemStack(Items.BUCKET)))); + + helper.succeedWhen(() -> { + // Check bucket is filled + helper.assertContainerContains(POS.east().east(), Items.WHITE_WOOL); + helper.assertContainerContains(POS.east().east(), Items.MILK_BUCKET); + helper.assertContainerContains(POS.east().east(), Items.DIAMOND_PICKAXE); + helper.assertTrue(chestIn.getItem(3).isEmpty(), "Chest contains too many items"); + + // Check cow still exists + helper.assertEntityPresent(EntityType.COW); + + // Check importer state + IPartStateWriter partStateWriter = (IPartStateWriter) PartHelpers.getPart(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)).getState(); + helper.assertFalse(partStateWriter.isDeactivated(), "Importer is deactivated"); + helper.assertValueEqual( + PartTypes.PLAYER_SIMULATOR.getBlockState(PartHelpers.getPartContainerChecked(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)), Direction.WEST).getValue(IgnoredBlockStatus.STATUS), + IgnoredBlockStatus.Status.ACTIVE, + "Block status is incorrect" + ); + helper.assertValueEqual(partStateWriter.getActiveAspect(), TunnelAspects.Write.Player.CLICK_ITEM_ITEMSTACK, "Active aspect is incorrect"); + helper.assertTrue(partStateWriter.getErrors(TunnelAspects.Write.Player.CLICK_ITEM_ITEMSTACK).isEmpty(), "Active aspect has errors"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testPlayerSimulatorKillCow(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place player simulator + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.PLAYER_SIMULATOR, new ItemStack(PartTypes.PLAYER_SIMULATOR.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place cow before player simulator + helper.spawnWithNoFreeWill(EntityType.COW, POS.west()); + + // Build prison around cow + helper.setBlock(POS.west().north(), Blocks.ACACIA_FENCE); + helper.setBlock(POS.west().south(), Blocks.ACACIA_FENCE); + helper.setBlock(POS.west().west().north(), Blocks.ACACIA_FENCE); + helper.setBlock(POS.west().west(), Blocks.ACACIA_FENCE); + helper.setBlock(POS.west().west().south(), Blocks.ACACIA_FENCE); + + // Insert some items into interface + ChestBlockEntity chestIn = helper.getBlockEntity(POS.east().east()); + chestIn.setItem(0, new ItemStack(Items.DIAMOND_PICKAXE)); + + // Enable click any item aspect + PartPos posPlayerSimulator = PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST); + placeVariableInWriter(helper.getLevel(), posPlayerSimulator, TunnelAspects.Write.Player.CLICK_ITEM_BOOLEAN, createVariableForValue(helper.getLevel(), ValueTypes.BOOLEAN, ValueTypeBoolean.ValueBoolean.of(true))); + + // Set aspect to left-click + PartHelpers.PartStateHolder partStateHolder = PartHelpers.getPart(posPlayerSimulator); + IAspectProperties properties = TunnelAspects.Write.Player.CLICK_ITEM_BOOLEAN.getProperties(partStateHolder.getPart(), PartTarget.fromCenter(posPlayerSimulator), partStateHolder.getState()); + properties.setValue(TunnelAspectWriteBuilders.Player.PROP_RIGHT_CLICK, ValueTypeBoolean.ValueBoolean.of(false)); + partStateHolder.getState().setAspectProperties(TunnelAspects.Write.Player.CLICK_ITEM_BOOLEAN, properties); + + helper.succeedWhen(() -> { + // Check sword still exists + helper.assertContainerContains(POS.east().east(), Items.DIAMOND_PICKAXE); + + // Check cow is dead + helper.assertEntityNotPresent(EntityType.COW); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testPlayerSimulatorFlipLever(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place player simulator + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.PLAYER_SIMULATOR, new ItemStack(PartTypes.PLAYER_SIMULATOR.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place lever before player simulator + helper.setBlock(POS.west(), Blocks.LEVER); + + // Enable empty click aspect + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Player.CLICK_EMPTY_BOOLEAN, new ItemStack(RegistryEntries.ITEM_VARIABLE)); + + helper.succeedWhen(() -> { + // Check lever is flipped + helper.assertBlockProperty(POS.west(), LeverBlock.POWERED, true); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testPlayerSimulatorPlaceWaterBucket(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place player simulator + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.PLAYER_SIMULATOR, new ItemStack(PartTypes.PLAYER_SIMULATOR.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place block a bit before player simulator to right-click bucket against + helper.setBlock(POS.west().west(), Blocks.STONE); + helper.setBlock(POS.west().north(), Blocks.STONE); + helper.setBlock(POS.west().south(), Blocks.STONE); + + // Insert some items into interface + ChestBlockEntity chestIn = helper.getBlockEntity(POS.east().east()); + chestIn.setItem(0, new ItemStack(Items.WATER_BUCKET)); + + // Enable item click aspect + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.Player.CLICK_ITEM_BOOLEAN, new ItemStack(RegistryEntries.ITEM_VARIABLE)); + + helper.succeedWhen(() -> { + // Check bucket is drained + helper.assertContainerContains(POS.east().east(), Items.BUCKET); + + // Check water is placed + helper.assertBlockPresent(Blocks.WATER, POS.west()); + }); + } + +} diff --git a/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsWorldBlock.java b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsWorldBlock.java new file mode 100644 index 000000000..557bdedc5 --- /dev/null +++ b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsWorldBlock.java @@ -0,0 +1,155 @@ +package org.cyclops.integratedtunnels.gametest; + +import net.minecraft.core.BlockPos; +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 org.cyclops.integrateddynamics.RegistryEntries; +import org.cyclops.integrateddynamics.api.part.PartPos; +import org.cyclops.integrateddynamics.api.part.write.IPartStateWriter; +import org.cyclops.integrateddynamics.core.block.IgnoredBlockStatus; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueObjectTypeItemStack; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes; +import org.cyclops.integrateddynamics.core.helper.PartHelpers; +import org.cyclops.integratedtunnels.Reference; +import org.cyclops.integratedtunnels.part.PartTypes; +import org.cyclops.integratedtunnels.part.aspect.TunnelAspects; + +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.createVariableForValue; +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.placeVariableInWriter; + +@GameTestHolder(Reference.MOD_ID) +@PrefixGameTestTemplate(false) +public class GameTestsWorldBlock { + + public static final String TEMPLATE_EMPTY = "empty10"; + public static final int TIMEOUT = 2000; + public static final BlockPos POS = BlockPos.ZERO.offset(2, 0, 2); + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testWorldBlockImporterToInterfaceToExporterBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place world block importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_WORLD_BLOCK, new ItemStack(PartTypes.IMPORTER_WORLD_BLOCK.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place world block exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_WORLD_BLOCK, new ItemStack(PartTypes.EXPORTER_WORLD_BLOCK.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place block before importer + helper.setBlock(POS.west(), Blocks.STONE); + + // Place empty variable in importer and exporter + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.World.BLOCK_BOOLEAN_IMPORT, variableAspect); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.World.BLOCK_BOOLEAN_EXPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if items are moved + helper.assertBlockNotPresent(Blocks.STONE, POS.west()); + helper.assertContainerEmpty(POS.west()); + helper.assertBlockPresent(Blocks.COBBLESTONE, POS.east().north()); + + // Check importer state + IPartStateWriter partStateWriter = (IPartStateWriter) PartHelpers.getPart(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)).getState(); + helper.assertFalse(partStateWriter.isDeactivated(), "Importer is deactivated"); + helper.assertValueEqual( + PartTypes.IMPORTER_WORLD_BLOCK.getBlockState(PartHelpers.getPartContainerChecked(PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST)), Direction.WEST).getValue(IgnoredBlockStatus.STATUS), + IgnoredBlockStatus.Status.ACTIVE, + "Block status is incorrect" + ); + helper.assertValueEqual(partStateWriter.getActiveAspect(), TunnelAspects.Write.World.BLOCK_BOOLEAN_IMPORT, "Active aspect is incorrect"); + helper.assertTrue(partStateWriter.getErrors(TunnelAspects.Write.World.BLOCK_BOOLEAN_IMPORT).isEmpty(), "Active aspect has errors"); + + // Check exporter state + IPartStateWriter partStateWriter2 = (IPartStateWriter) PartHelpers.getPart(PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH)).getState(); + helper.assertFalse(partStateWriter2.isDeactivated(), "Importer is deactivated"); + helper.assertValueEqual( + PartTypes.EXPORTER_WORLD_BLOCK.getBlockState(PartHelpers.getPartContainerChecked(PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH)), Direction.NORTH).getValue(IgnoredBlockStatus.STATUS), + IgnoredBlockStatus.Status.ACTIVE, + "Block status is incorrect" + ); + helper.assertValueEqual(partStateWriter2.getActiveAspect(), TunnelAspects.Write.World.BLOCK_BOOLEAN_EXPORT, "Active aspect is incorrect"); + helper.assertTrue(partStateWriter2.getErrors(TunnelAspects.Write.World.BLOCK_BOOLEAN_EXPORT).isEmpty(), "Active aspect has errors"); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testWorldBlockImporterToInterfaceToExporterBlockCorrect(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place world block importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_WORLD_BLOCK, new ItemStack(PartTypes.IMPORTER_WORLD_BLOCK.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place world block exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_WORLD_BLOCK, new ItemStack(PartTypes.EXPORTER_WORLD_BLOCK.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place block before importer + helper.setBlock(POS.west(), Blocks.STONE); + + // Place empty variable in importer and exporter + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.World.BLOCK_ITEMSTACK_IMPORT, createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_ITEMSTACK, ValueObjectTypeItemStack.ValueItemStack.of(new ItemStack(Blocks.COBBLESTONE)))); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.World.BLOCK_BOOLEAN_EXPORT, new ItemStack(RegistryEntries.ITEM_VARIABLE)); + + helper.succeedWhen(() -> { + // Check if items are moved + helper.assertBlockNotPresent(Blocks.STONE, POS.west()); + helper.assertContainerEmpty(POS.west()); + helper.assertBlockPresent(Blocks.COBBLESTONE, POS.east().north()); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testWorldBlockImporterToInterfaceToExporterBlockIncorrect(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place world block importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_WORLD_BLOCK, new ItemStack(PartTypes.IMPORTER_WORLD_BLOCK.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place world block exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_WORLD_BLOCK, new ItemStack(PartTypes.EXPORTER_WORLD_BLOCK.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place block before importer + helper.setBlock(POS.west(), Blocks.STONE); + + // Place empty variable in importer and exporter + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.World.BLOCK_ITEMSTACK_IMPORT, createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_ITEMSTACK, ValueObjectTypeItemStack.ValueItemStack.of(new ItemStack(Blocks.STONE)))); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.World.BLOCK_BOOLEAN_EXPORT, new ItemStack(RegistryEntries.ITEM_VARIABLE)); + + helper.succeedWhen(() -> { + // Check if items are not moved + helper.assertBlockPresent(Blocks.STONE, POS.west()); + helper.assertContainerEmpty(POS.west()); + helper.assertBlockNotPresent(Blocks.COBBLESTONE, POS.east().north()); + }); + } + +} diff --git a/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsWorldFluid.java b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsWorldFluid.java new file mode 100644 index 000000000..38305b914 --- /dev/null +++ b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsWorldFluid.java @@ -0,0 +1,137 @@ +package org.cyclops.integratedtunnels.gametest; + +import net.minecraft.core.BlockPos; +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.material.Fluids; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; +import org.cyclops.integrateddynamics.RegistryEntries; +import org.cyclops.integrateddynamics.api.part.PartPos; +import org.cyclops.integrateddynamics.blockentity.BlockEntityDryingBasin; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueObjectTypeFluidStack; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes; +import org.cyclops.integrateddynamics.core.helper.PartHelpers; +import org.cyclops.integratedtunnels.Reference; +import org.cyclops.integratedtunnels.part.PartTypes; +import org.cyclops.integratedtunnels.part.aspect.TunnelAspects; + +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.createVariableForValue; +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.placeVariableInWriter; + +@GameTestHolder(Reference.MOD_ID) +@PrefixGameTestTemplate(false) +public class GameTestsWorldFluid { + + public static final String TEMPLATE_EMPTY = "empty10"; + public static final int TIMEOUT = 2000; + public static final BlockPos POS = BlockPos.ZERO.offset(2, 0, 2); + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testWorldFluidImporterToInterfaceToExporterBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place world fluid importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_WORLD_FLUID, new ItemStack(PartTypes.IMPORTER_WORLD_FLUID.getItem())); + + // Place fluid interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_FLUID, new ItemStack(PartTypes.INTERFACE_FLUID.getItem())); + + // Place world fluid exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_WORLD_FLUID, new ItemStack(PartTypes.EXPORTER_WORLD_FLUID.getItem())); + + // Place drying basin for interface + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + + // Place fluid before importer + helper.setBlock(POS.west(), Blocks.WATER); + + // Place empty variable in importer and exporter + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.World.FLUID_BOOLEAN_IMPORT, variableAspect); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.World.FLUID_BOOLEAN_EXPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if fluids are moved + helper.assertBlockNotPresent(Blocks.WATER, POS.west()); + BlockEntityDryingBasin basinOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(basinOut.getTank().getFluidAmount(), 0, "Basin contains fluid"); + helper.assertBlockPresent(Blocks.WATER, POS.east().north()); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testWorldFluidImporterToInterfaceToExporterBlockCorrect(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place world fluid importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_WORLD_FLUID, new ItemStack(PartTypes.IMPORTER_WORLD_FLUID.getItem())); + + // Place fluid interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_FLUID, new ItemStack(PartTypes.INTERFACE_FLUID.getItem())); + + // Place world fluid exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_WORLD_FLUID, new ItemStack(PartTypes.EXPORTER_WORLD_FLUID.getItem())); + + // Place drying basin for interface + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + + // Place fluid before importer + helper.setBlock(POS.west(), Blocks.WATER); + + // Place empty variable in importer and exporter + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.World.FLUID_FLUIDSTACK_IMPORT, createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_FLUIDSTACK, ValueObjectTypeFluidStack.ValueFluidStack.of(new FluidStack(Fluids.WATER, 10)))); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.World.FLUID_FLUIDSTACK_EXPORT, createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_FLUIDSTACK, ValueObjectTypeFluidStack.ValueFluidStack.of(new FluidStack(Fluids.WATER, 10)))); + + helper.succeedWhen(() -> { + // Check if fluids are moved + helper.assertBlockNotPresent(Blocks.WATER, POS.west()); + BlockEntityDryingBasin basinOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(basinOut.getTank().getFluidAmount(), 0, "Basin contains fluid"); + helper.assertBlockPresent(Blocks.WATER, POS.east().north()); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testWorldFluidImporterToInterfaceToExporterBlockIncorrect(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place world fluid importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_WORLD_FLUID, new ItemStack(PartTypes.IMPORTER_WORLD_FLUID.getItem())); + + // Place fluid interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_FLUID, new ItemStack(PartTypes.INTERFACE_FLUID.getItem())); + + // Place world fluid exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_WORLD_FLUID, new ItemStack(PartTypes.EXPORTER_WORLD_FLUID.getItem())); + + // Place drying basin for interface + helper.setBlock(POS.east().east(), RegistryEntries.BLOCK_DRYING_BASIN.get()); + + // Place fluid before importer + helper.setBlock(POS.west(), Blocks.WATER); + + // Place empty variable in importer and exporter + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.World.FLUID_FLUIDSTACK_IMPORT, createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_FLUIDSTACK, ValueObjectTypeFluidStack.ValueFluidStack.of(new FluidStack(Fluids.LAVA, 10)))); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.World.FLUID_FLUIDSTACK_EXPORT, createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_FLUIDSTACK, ValueObjectTypeFluidStack.ValueFluidStack.of(new FluidStack(Fluids.LAVA, 10)))); + + helper.succeedWhen(() -> { + // Check if fluids are not moved + helper.assertBlockPresent(Blocks.WATER, POS.west()); + BlockEntityDryingBasin basinOut = helper.getBlockEntity(POS.east().east()); + helper.assertValueEqual(basinOut.getTank().getFluidAmount(), 0, "Basin contains fluid"); + helper.assertBlockNotPresent(Blocks.WATER, POS.east().north()); + }); + } + +} diff --git a/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsWorldItem.java b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsWorldItem.java new file mode 100644 index 000000000..85ba9c794 --- /dev/null +++ b/src/main/java/org/cyclops/integratedtunnels/gametest/GameTestsWorldItem.java @@ -0,0 +1,131 @@ +package org.cyclops.integratedtunnels.gametest; + +import net.minecraft.core.BlockPos; +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 org.cyclops.integrateddynamics.RegistryEntries; +import org.cyclops.integrateddynamics.api.part.PartPos; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueObjectTypeItemStack; +import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes; +import org.cyclops.integrateddynamics.core.helper.PartHelpers; +import org.cyclops.integratedtunnels.Reference; +import org.cyclops.integratedtunnels.part.PartTypes; +import org.cyclops.integratedtunnels.part.aspect.TunnelAspects; + +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.createVariableForValue; +import static org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics.placeVariableInWriter; + +@GameTestHolder(Reference.MOD_ID) +@PrefixGameTestTemplate(false) +public class GameTestsWorldItem { + + public static final String TEMPLATE_EMPTY = "empty10"; + public static final int TIMEOUT = 2000; + public static final BlockPos POS = BlockPos.ZERO.offset(2, 0, 2); + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testWorldItemImporterToInterfaceToExporterBoolean(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place world item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_WORLD_ITEM, new ItemStack(PartTypes.IMPORTER_WORLD_ITEM.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place world item exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_WORLD_ITEM, new ItemStack(PartTypes.EXPORTER_WORLD_ITEM.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place block item before importer + helper.spawnItem(Blocks.STONE.asItem(), POS.west()); + + // Place empty variable in importer and exporter + ItemStack variableAspect = new ItemStack(RegistryEntries.ITEM_VARIABLE); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.World.ENTITYITEM_BOOLEAN_IMPORT, variableAspect); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.World.ENTITYITEM_BOOLEAN_EXPORT, variableAspect); + + helper.succeedWhen(() -> { + // Check if items are moved + helper.assertItemEntityNotPresent(Blocks.STONE.asItem(), POS.west(), 0.25); + helper.assertContainerEmpty(POS.west()); + helper.assertItemEntityPresent(Blocks.STONE.asItem(), POS.east().north(), 0.25); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testWorldItemImporterToInterfaceToExporterBlockCorrect(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place world item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_WORLD_ITEM, new ItemStack(PartTypes.IMPORTER_WORLD_ITEM.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place world item exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_WORLD_ITEM, new ItemStack(PartTypes.EXPORTER_WORLD_ITEM.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place block item before importer + helper.spawnItem(Blocks.STONE.asItem(), POS.west()); + + // Place empty variable in importer and exporter + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.World.ENTITYITEM_ITEMSTACK_IMPORT, createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_ITEMSTACK, ValueObjectTypeItemStack.ValueItemStack.of(new ItemStack(Blocks.STONE)))); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.World.ENTITYITEM_BOOLEAN_EXPORT, new ItemStack(RegistryEntries.ITEM_VARIABLE)); + + helper.succeedWhen(() -> { + // Check if items are moved + helper.assertItemEntityNotPresent(Blocks.STONE.asItem(), POS.west(), 0.25); + helper.assertContainerEmpty(POS.west()); + helper.assertItemEntityPresent(Blocks.STONE.asItem(), POS.east().north(), 0.25); + }); + } + + @GameTest(template = TEMPLATE_EMPTY, timeoutTicks = TIMEOUT) + public void testWorldItemImporterToInterfaceToExporterBlockIncorrect(GameTestHelper helper) { + // Place cable + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + helper.setBlock(POS.east(), RegistryEntries.BLOCK_CABLE.value()); + + // Place world item importer + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.WEST, PartTypes.IMPORTER_WORLD_ITEM, new ItemStack(PartTypes.IMPORTER_WORLD_ITEM.getItem())); + + // Place item interface + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.EAST, PartTypes.INTERFACE_ITEM, new ItemStack(PartTypes.INTERFACE_ITEM.getItem())); + + // Place world item exporter + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH, PartTypes.EXPORTER_WORLD_ITEM, new ItemStack(PartTypes.EXPORTER_WORLD_ITEM.getItem())); + + // Place chest for interface + helper.setBlock(POS.east().east(), Blocks.CHEST); + + // Place block item before importer + helper.spawnItem(Blocks.STONE.asItem(), POS.west()); + + // Place empty variable in importer and exporter + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.WEST), TunnelAspects.Write.World.ENTITYITEM_ITEMSTACK_IMPORT, createVariableForValue(helper.getLevel(), ValueTypes.OBJECT_ITEMSTACK, ValueObjectTypeItemStack.ValueItemStack.of(new ItemStack(Blocks.COBBLESTONE)))); + placeVariableInWriter(helper.getLevel(), PartPos.of(helper.getLevel(), helper.absolutePos(POS.east()), Direction.NORTH), TunnelAspects.Write.World.ENTITYITEM_BOOLEAN_EXPORT, new ItemStack(RegistryEntries.ITEM_VARIABLE)); + + helper.succeedWhen(() -> { + // Check if items are not moved + helper.assertItemEntityPresent(Blocks.STONE.asItem(), POS.west(), 0.25); + helper.assertContainerEmpty(POS.west()); + helper.assertItemEntityNotPresent(Blocks.STONE.asItem(), POS.east().north(), 0.25); + }); + } + +} diff --git a/src/main/resources/data/integratedtunnels/structure/empty10.nbt b/src/main/resources/data/integratedtunnels/structure/empty10.nbt new file mode 100644 index 000000000..11ea2c5de Binary files /dev/null and b/src/main/resources/data/integratedtunnels/structure/empty10.nbt differ