diff --git a/src/integrationtest/java/org/cyclops/integrateddynamics/gametest/GameTestsNetwork.java b/src/integrationtest/java/org/cyclops/integrateddynamics/gametest/GameTestsNetwork.java index ea94946859b..5c1e2b93ecd 100644 --- a/src/integrationtest/java/org/cyclops/integrateddynamics/gametest/GameTestsNetwork.java +++ b/src/integrationtest/java/org/cyclops/integrateddynamics/gametest/GameTestsNetwork.java @@ -3,6 +3,7 @@ import com.google.common.collect.Sets; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; import net.minecraft.gametest.framework.GameTest; import net.minecraft.gametest.framework.GameTestHelper; import net.minecraft.world.InteractionHand; @@ -17,18 +18,23 @@ import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; import org.cyclops.cyclopscore.client.particle.ParticleBlurData; import org.cyclops.cyclopscore.datastructure.DimPos; +import org.cyclops.cyclopscore.helper.BlockEntityHelpers; import org.cyclops.integrateddynamics.IntegratedDynamics; import org.cyclops.integrateddynamics.Reference; import org.cyclops.integrateddynamics.RegistryEntries; import org.cyclops.integrateddynamics.api.network.INetwork; +import org.cyclops.integrateddynamics.api.part.PartPos; import org.cyclops.integrateddynamics.api.path.ISidedPathElement; import org.cyclops.integrateddynamics.capability.path.PathElementPosition; import org.cyclops.integrateddynamics.capability.path.SidedPathElement; +import org.cyclops.integrateddynamics.core.blockentity.BlockEntityMultipartTicking; import org.cyclops.integrateddynamics.core.helper.CableHelpers; import org.cyclops.integrateddynamics.core.helper.NetworkHelpers; import org.cyclops.integrateddynamics.core.helper.PartHelpers; +import org.cyclops.integrateddynamics.core.network.PartNetworkElement; import org.cyclops.integrateddynamics.core.part.PartTypes; import org.cyclops.integrateddynamics.core.persist.world.NetworkWorldStorage; +import org.cyclops.integrateddynamics.part.PartTypeConnector; import java.util.Optional; @@ -2056,4 +2062,36 @@ public void testNetworkOmnidirectionalUnconnected(GameTestHelper helper) { }); } + @GameTest(template = TEMPLATE_EMPTY) + public void testNetworkRevalidateAllPartsAtPosition(GameTestHelper helper) { + // Place a cable with two parts + helper.setBlock(POS, RegistryEntries.BLOCK_CABLE.value()); + ItemStack omniDirectionalConnector = new ItemStack(PartTypes.CONNECTOR_OMNI.getItem()); + omniDirectionalConnector.set(RegistryEntries.DATACOMPONENT_OMNIDIRECTIONAL_GROUP, 1); + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.DOWN, PartTypes.CONNECTOR_OMNI, omniDirectionalConnector.copy()); + PartHelpers.addPart(helper.getLevel(), helper.absolutePos(POS), Direction.UP, PartTypes.CONNECTOR_OMNI, omniDirectionalConnector.copy()); + PartPos posDown = PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.DOWN); + PartPos posUp = PartPos.of(helper.getLevel(), helper.absolutePos(POS), Direction.UP); + + helper.runAfterDelay(20, () -> { + INetwork network = NetworkHelpers.getNetworkChecked(helper.getLevel(), helper.absolutePos(POS), null); + + // Simulate loading the cable from disk, which creates new part states that are not attached to the network yet + BlockEntityMultipartTicking blockEntity = BlockEntityHelpers.get(helper.getLevel(), helper.absolutePos(POS), BlockEntityMultipartTicking.class).orElseThrow(); + HolderLookup.Provider provider = helper.getLevel().registryAccess(); + blockEntity.getPartContainer().deserializeNBT(provider, blockEntity.getPartContainer().serializeNBT(provider)); + blockEntity.getNetworkCarrier().setNetwork(null); + helper.assertTrue(((PartTypeConnector.State) PartHelpers.getPart(posUp).getState()).getPosition() == null, "Part state was not recreated"); + + // The network lazily revalidates the first updatable part at this position, which links the cable to the network + new PartNetworkElement<>(PartTypes.CONNECTOR_OMNI, posDown).revalidate(network); + helper.assertTrue(blockEntity.getNetwork() == network, "Network was not revalidated"); + + // The other part at this position must also be attached to the network again + helper.assertTrue(((PartTypeConnector.State) PartHelpers.getPart(posDown).getState()).getPosition() != null, "First part was not attached to the network"); + helper.assertTrue(((PartTypeConnector.State) PartHelpers.getPart(posUp).getState()).getPosition() != null, "Second part was not attached to the network"); + helper.succeed(); + }); + } + } diff --git a/src/main/java/org/cyclops/integrateddynamics/core/network/PartNetworkElement.java b/src/main/java/org/cyclops/integrateddynamics/core/network/PartNetworkElement.java index 6efea9b3eeb..fc332085c9c 100644 --- a/src/main/java/org/cyclops/integrateddynamics/core/network/PartNetworkElement.java +++ b/src/main/java/org/cyclops/integrateddynamics/core/network/PartNetworkElement.java @@ -118,6 +118,18 @@ public void revalidate(INetwork network) { super.revalidate(network); if (revalidatePositioned(network, this.center.getPos())) { afterNetworkReAlive(network); + + // Ensure that non-ticking parts are also revalidated. + DimPos dimPos = this.center.getPos(); + NetworkHelpers.getNetworkElementProvider(dimPos.getLevel(true), dimPos.getBlockPos(), null) + .ifPresent(networkElementProvider -> { + for (INetworkElement element : networkElementProvider.createNetworkElements(dimPos.getLevel(true), dimPos.getBlockPos())) { + if (!element.equals(this)) { + element.revalidate(network); + element.afterNetworkReAlive(network); + } + } + }); } }