From cdbf4d14fa624e57c613046783836925585f2a8a Mon Sep 17 00:00:00 2001 From: raoulvdberge Date: Mon, 11 Mar 2024 21:50:07 +0100 Subject: [PATCH] fix: problems moving network devices with Carry On mod Carry On was initializing block entities twice. We had to: * Protect the event queue from running the update for the first erroneous initialization request. * Allow block entity removals without network, to avoid a crash when the block entity is replaced. The event queue hasn't run yet at that point so there's no network, so allow no networks on removal. --- CHANGELOG.md | 1 + .../platform/api/PlatformApi.java | 8 +++---- .../platform/api/PlatformApiProxy.java | 8 +++---- ...stractNetworkNodeContainerBlockEntity.java | 5 ++++ .../network/PlatformNetworkNodeContainer.java | 8 +++++-- .../platform/common/PlatformApiImpl.java | 24 +++++++++++++++---- .../network/ConnectionProviderImpl.java | 2 +- 7 files changed, 41 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da3cd2de9..216ab2159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Fixed changing side buttons not working on Forge. - Fixed External Storage not displaying empty allowlist warning. - Fixed incrementing starting from 1 in amount screens not having an intended off-by-one. +- Fixed problems moving network devices with "Carry On" mod. ## [2.0.0-milestone.3.3] - 2024-02-17 diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApi.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApi.java index 6cb41434e..74ce585f4 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApi.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApi.java @@ -4,7 +4,6 @@ import com.refinedmods.refinedstorage2.api.network.Network; import com.refinedmods.refinedstorage2.api.network.component.NetworkComponent; import com.refinedmods.refinedstorage2.api.network.energy.EnergyStorage; -import com.refinedmods.refinedstorage2.api.network.node.container.NetworkNodeContainer; import com.refinedmods.refinedstorage2.api.resource.ResourceKey; import com.refinedmods.refinedstorage2.platform.api.constructordestructor.ConstructorStrategyFactory; import com.refinedmods.refinedstorage2.platform.api.constructordestructor.DestructorStrategyFactory; @@ -28,6 +27,7 @@ import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorExtractionStrategy; import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorInsertionStrategy; import com.refinedmods.refinedstorage2.platform.api.support.energy.EnergyItemHelper; +import com.refinedmods.refinedstorage2.platform.api.support.network.PlatformNetworkNodeContainer; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.NetworkBoundItemHelper; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReference; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReferenceFactory; @@ -103,11 +103,11 @@ public interface PlatformApi { BuiltinUpgradeDestinations getBuiltinUpgradeDestinations(); - void requestNetworkNodeInitialization(NetworkNodeContainer container, Level level, Runnable callback); + void requestNetworkNodeInitialization(PlatformNetworkNodeContainer container, Level level, Runnable callback); - void requestNetworkNodeRemoval(NetworkNodeContainer container, Level level); + void requestNetworkNodeRemoval(PlatformNetworkNodeContainer container, Level level); - void requestNetworkNodeUpdate(NetworkNodeContainer container, Level level); + void requestNetworkNodeUpdate(PlatformNetworkNodeContainer container, Level level); GridInsertionStrategy createGridInsertionStrategy(AbstractContainerMenu containerMenu, Player player, diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApiProxy.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApiProxy.java index 4edd95bab..840eebc04 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApiProxy.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApiProxy.java @@ -4,7 +4,6 @@ import com.refinedmods.refinedstorage2.api.network.Network; import com.refinedmods.refinedstorage2.api.network.component.NetworkComponent; import com.refinedmods.refinedstorage2.api.network.energy.EnergyStorage; -import com.refinedmods.refinedstorage2.api.network.node.container.NetworkNodeContainer; import com.refinedmods.refinedstorage2.api.resource.ResourceKey; import com.refinedmods.refinedstorage2.platform.api.constructordestructor.ConstructorStrategyFactory; import com.refinedmods.refinedstorage2.platform.api.constructordestructor.DestructorStrategyFactory; @@ -28,6 +27,7 @@ import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorExtractionStrategy; import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorInsertionStrategy; import com.refinedmods.refinedstorage2.platform.api.support.energy.EnergyItemHelper; +import com.refinedmods.refinedstorage2.platform.api.support.network.PlatformNetworkNodeContainer; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.NetworkBoundItemHelper; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReference; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReferenceFactory; @@ -177,19 +177,19 @@ public BuiltinUpgradeDestinations getBuiltinUpgradeDestinations() { } @Override - public void requestNetworkNodeInitialization(final NetworkNodeContainer container, + public void requestNetworkNodeInitialization(final PlatformNetworkNodeContainer container, final Level level, final Runnable callback) { ensureLoaded().requestNetworkNodeInitialization(container, level, callback); } @Override - public void requestNetworkNodeRemoval(final NetworkNodeContainer container, final Level level) { + public void requestNetworkNodeRemoval(final PlatformNetworkNodeContainer container, final Level level) { ensureLoaded().requestNetworkNodeRemoval(container, level); } @Override - public void requestNetworkNodeUpdate(final NetworkNodeContainer container, final Level level) { + public void requestNetworkNodeUpdate(final PlatformNetworkNodeContainer container, final Level level) { ensureLoaded().requestNetworkNodeUpdate(container, level); } diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/support/network/AbstractNetworkNodeContainerBlockEntity.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/support/network/AbstractNetworkNodeContainerBlockEntity.java index 3de6c3be6..1c6bacffd 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/support/network/AbstractNetworkNodeContainerBlockEntity.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/support/network/AbstractNetworkNodeContainerBlockEntity.java @@ -35,6 +35,11 @@ public void clearRemoved() { PlatformApi.INSTANCE.requestNetworkNodeInitialization(this, level, this::onNetworkInNodeInitialized); } + @Override + public boolean isContainerRemoved() { + return isRemoved(); + } + protected void onNetworkInNodeInitialized() { } diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/support/network/PlatformNetworkNodeContainer.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/support/network/PlatformNetworkNodeContainer.java index 5ce90b0b2..ec7d815c7 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/support/network/PlatformNetworkNodeContainer.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/support/network/PlatformNetworkNodeContainer.java @@ -14,7 +14,8 @@ public interface PlatformNetworkNodeContainer extends NetworkNodeContainer { * Called when a node is about to be added into the network graph. * Add outgoing connections here. * If the outgoing connections ever change, call {@link - * com.refinedmods.refinedstorage2.platform.api.PlatformApi#requestNetworkNodeUpdate(NetworkNodeContainer, Level)}. + * com.refinedmods.refinedstorage2.platform.api.PlatformApi#requestNetworkNodeUpdate( + *PlatformNetworkNodeContainer, Level)}. * * @param sink the sink that accepts outgoing connections */ @@ -24,7 +25,8 @@ public interface PlatformNetworkNodeContainer extends NetworkNodeContainer { * Returns whether the (not yet discovered) node can accept an incoming connection. * Changes to this return value won't cause a rebuild of the network state. * If the return value ever changes, call {@link - * com.refinedmods.refinedstorage2.platform.api.PlatformApi#requestNetworkNodeUpdate(NetworkNodeContainer, Level)}. + * com.refinedmods.refinedstorage2.platform.api.PlatformApi#requestNetworkNodeUpdate( + *PlatformNetworkNodeContainer, Level)}. * * @param incomingDirection the incoming direction * @param connectingState the state wanting to connect @@ -35,4 +37,6 @@ public interface PlatformNetworkNodeContainer extends NetworkNodeContainer { BlockState getContainerBlockState(); GlobalPos getContainerPosition(); + + boolean isContainerRemoved(); } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/PlatformApiImpl.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/PlatformApiImpl.java index 5eab2aa38..07d5805d0 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/PlatformApiImpl.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/PlatformApiImpl.java @@ -7,7 +7,6 @@ import com.refinedmods.refinedstorage2.api.network.energy.EnergyStorage; import com.refinedmods.refinedstorage2.api.network.impl.NetworkBuilderImpl; import com.refinedmods.refinedstorage2.api.network.impl.NetworkFactory; -import com.refinedmods.refinedstorage2.api.network.node.container.NetworkNodeContainer; import com.refinedmods.refinedstorage2.api.resource.ResourceKey; import com.refinedmods.refinedstorage2.platform.api.PlatformApi; import com.refinedmods.refinedstorage2.platform.api.constructordestructor.ConstructorStrategyFactory; @@ -32,6 +31,7 @@ import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorExtractionStrategy; import com.refinedmods.refinedstorage2.platform.api.storagemonitor.StorageMonitorInsertionStrategy; import com.refinedmods.refinedstorage2.platform.api.support.energy.EnergyItemHelper; +import com.refinedmods.refinedstorage2.platform.api.support.network.PlatformNetworkNodeContainer; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.NetworkBoundItemHelper; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReference; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReferenceFactory; @@ -295,24 +295,40 @@ public BuiltinUpgradeDestinations getBuiltinUpgradeDestinations() { } @Override - public void requestNetworkNodeInitialization(final NetworkNodeContainer container, + public void requestNetworkNodeInitialization(final PlatformNetworkNodeContainer container, final Level level, final Runnable callback) { final ConnectionProviderImpl connectionProvider = new ConnectionProviderImpl(level); ServerEventQueue.queue(() -> { + // The container could've been removed by the time it has been placed, and by the time the event queue has + // run. In that case, don't initialize the network node because it no longer exists. + // This is a workaround for the "Carry On" mod. The mod places the block (which creates a block entity and + // requests this network node initialization) and then overrides the placed block entity with their own + // block entity. This triggers a new initialization, but then this one can no longer run! + if (container.isContainerRemoved()) { + return; + } networkBuilder.initialize(container, connectionProvider); callback.run(); }); } @Override - public void requestNetworkNodeRemoval(final NetworkNodeContainer container, final Level level) { + public void requestNetworkNodeRemoval(final PlatformNetworkNodeContainer container, final Level level) { + // "Carry On" mod places the block (which creates a block entity and requests network node initialization) + // and then overrides the placed block entity with their own information. + // However, when the placed block entity is replaced, the server event queue hasn't run yet and there is + // no network loaded yet, even though the network node initialization was requested. + // Stop continuing here to avoid further code failing due to a missing network. + if (container.getNode().getNetwork() == null) { + return; + } final ConnectionProviderImpl connectionProvider = new ConnectionProviderImpl(level); networkBuilder.remove(container, connectionProvider); } @Override - public void requestNetworkNodeUpdate(final NetworkNodeContainer container, final Level level) { + public void requestNetworkNodeUpdate(final PlatformNetworkNodeContainer container, final Level level) { final ConnectionProviderImpl connectionProvider = new ConnectionProviderImpl(level); networkBuilder.update(container, connectionProvider); } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/ConnectionProviderImpl.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/ConnectionProviderImpl.java index cd33c72e3..7d6f81382 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/ConnectionProviderImpl.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/ConnectionProviderImpl.java @@ -141,7 +141,7 @@ private BlockEntity getBlockEntitySafely(final Level level, final BlockPos pos) } // Avoid using EntityCreationType.IMMEDIATE. // By default, the block is removed first and then the block entity (see BaseBlock#onRemove). - // But, when using mods like Carrier or Carpet that allow for moving block entities, + // But, when using mods like "Carrier", "Carpet" or "Carry On" that allow for moving block entities, // they remove the block entity first and then the block. // When removing a block with Carrier for example, // this causes a problematic situation that the block entity IS gone,