diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
index 87191bb2b..0f886cd2a 100644
--- a/config/checkstyle/checkstyle.xml
+++ b/config/checkstyle/checkstyle.xml
@@ -21,7 +21,7 @@
-
+
diff --git a/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/NetworkTest.java b/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/NetworkTest.java
index 15b6880bb..d7cc58db4 100644
--- a/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/NetworkTest.java
+++ b/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/NetworkTest.java
@@ -8,10 +8,10 @@
import com.refinedmods.refinedstorage2.api.network.impl.node.grid.GridNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.iface.InterfaceNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.importer.ImporterNetworkNode;
-import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.relay.RelayInputNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.relay.RelayOutputNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.storage.StorageNetworkNode;
+import com.refinedmods.refinedstorage2.api.network.impl.node.storagetransfer.StorageTransferNetworkNode;
import com.refinedmods.refinedstorage2.network.test.nodefactory.ControllerNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.DetectorNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.ExporterNetworkNodeFactory;
@@ -19,11 +19,11 @@
import com.refinedmods.refinedstorage2.network.test.nodefactory.GridNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.ImporterNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.InterfaceNetworkNodeFactory;
-import com.refinedmods.refinedstorage2.network.test.nodefactory.MultiStorageNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.RelayInputNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.RelayOutputNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.SimpleNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.StorageNetworkNodeFactory;
+import com.refinedmods.refinedstorage2.network.test.nodefactory.StorageTransferNetworkNodeFactory;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -36,16 +36,16 @@
@Target(ElementType.TYPE)
@ExtendWith(NetworkTestExtension.class)
@RegisterNetworkNode(value = ControllerNetworkNodeFactory.class, clazz = ControllerNetworkNode.class)
-@RegisterNetworkNode(value = MultiStorageNetworkNodeFactory.class, clazz = MultiStorageNetworkNode.class)
+@RegisterNetworkNode(value = StorageNetworkNodeFactory.class, clazz = StorageNetworkNode.class)
@RegisterNetworkNode(value = ExporterNetworkNodeFactory.class, clazz = ExporterNetworkNode.class)
@RegisterNetworkNode(value = GridNetworkNodeFactory.class, clazz = GridNetworkNode.class)
@RegisterNetworkNode(value = ImporterNetworkNodeFactory.class, clazz = ImporterNetworkNode.class)
@RegisterNetworkNode(value = SimpleNetworkNodeFactory.class, clazz = SimpleNetworkNode.class)
-@RegisterNetworkNode(value = StorageNetworkNodeFactory.class, clazz = StorageNetworkNode.class)
@RegisterNetworkNode(value = InterfaceNetworkNodeFactory.class, clazz = InterfaceNetworkNode.class)
@RegisterNetworkNode(value = ExternalStorageNetworkNodeFactory.class, clazz = ExternalStorageNetworkNode.class)
@RegisterNetworkNode(value = DetectorNetworkNodeFactory.class, clazz = DetectorNetworkNode.class)
@RegisterNetworkNode(value = RelayInputNetworkNodeFactory.class, clazz = RelayInputNetworkNode.class)
@RegisterNetworkNode(value = RelayOutputNetworkNodeFactory.class, clazz = RelayOutputNetworkNode.class)
+@RegisterNetworkNode(value = StorageTransferNetworkNodeFactory.class, clazz = StorageTransferNetworkNode.class)
public @interface NetworkTest {
}
diff --git a/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/NetworkTestFixtures.java b/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/NetworkTestFixtures.java
index 4cbfc678c..aa4a5a1c5 100644
--- a/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/NetworkTestFixtures.java
+++ b/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/NetworkTestFixtures.java
@@ -15,6 +15,8 @@
import com.refinedmods.refinedstorage2.api.resource.list.ResourceListImpl;
import com.refinedmods.refinedstorage2.network.test.fake.FakePermissions;
+import java.util.LinkedHashMap;
+
public final class NetworkTestFixtures {
public static final ComponentMapFactory NETWORK_COMPONENT_MAP_FACTORY =
new ComponentMapFactory<>();
@@ -30,7 +32,7 @@ public final class NetworkTestFixtures {
);
NETWORK_COMPONENT_MAP_FACTORY.addFactory(
StorageNetworkComponent.class,
- network -> new StorageNetworkComponentImpl(new ResourceListImpl())
+ network -> new StorageNetworkComponentImpl(new ResourceListImpl(new LinkedHashMap<>()))
);
NETWORK_COMPONENT_MAP_FACTORY.addFactory(
SecurityNetworkComponent.class,
diff --git a/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/StorageNetworkNodeFactory.java b/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/StorageNetworkNodeFactory.java
index 9600b77f0..df47e8da8 100644
--- a/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/StorageNetworkNodeFactory.java
+++ b/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/StorageNetworkNodeFactory.java
@@ -7,8 +7,17 @@
import java.util.Map;
public class StorageNetworkNodeFactory extends AbstractNetworkNodeFactory {
+ public static final String PROPERTY_ENERGY_USAGE_PER_STORAGE = "energy_usage_per_storage";
+ public static final String PROPERTY_SIZE = "size";
+
@Override
protected AbstractNetworkNode innerCreate(final AddNetworkNode ctx, final Map properties) {
- return new StorageNetworkNode(getEnergyUsage(properties));
+ final long energyUsagePerStorage = (long) properties.getOrDefault(PROPERTY_ENERGY_USAGE_PER_STORAGE, 0L);
+ final int size = (int) properties.getOrDefault(PROPERTY_SIZE, 9);
+ return new StorageNetworkNode(
+ getEnergyUsage(properties),
+ energyUsagePerStorage,
+ size
+ );
}
}
diff --git a/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/MultiStorageNetworkNodeFactory.java b/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/StorageTransferNetworkNodeFactory.java
similarity index 76%
rename from refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/MultiStorageNetworkNodeFactory.java
rename to refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/StorageTransferNetworkNodeFactory.java
index 0e56caffe..3dc766bd3 100644
--- a/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/MultiStorageNetworkNodeFactory.java
+++ b/refinedstorage2-network-test/src/main/java/com/refinedmods/refinedstorage2/network/test/nodefactory/StorageTransferNetworkNodeFactory.java
@@ -1,20 +1,20 @@
package com.refinedmods.refinedstorage2.network.test.nodefactory;
import com.refinedmods.refinedstorage2.api.network.impl.node.AbstractNetworkNode;
-import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageNetworkNode;
+import com.refinedmods.refinedstorage2.api.network.impl.node.storagetransfer.StorageTransferNetworkNode;
import com.refinedmods.refinedstorage2.network.test.AddNetworkNode;
import java.util.Map;
-public class MultiStorageNetworkNodeFactory extends AbstractNetworkNodeFactory {
+public class StorageTransferNetworkNodeFactory extends AbstractNetworkNodeFactory {
public static final String PROPERTY_ENERGY_USAGE_PER_STORAGE = "energy_usage_per_storage";
public static final String PROPERTY_SIZE = "size";
@Override
protected AbstractNetworkNode innerCreate(final AddNetworkNode ctx, final Map properties) {
final long energyUsagePerStorage = (long) properties.getOrDefault(PROPERTY_ENERGY_USAGE_PER_STORAGE, 0L);
- final int size = (int) properties.getOrDefault(PROPERTY_SIZE, 9);
- return new MultiStorageNetworkNode(
+ final int size = (int) properties.getOrDefault(PROPERTY_SIZE, 6);
+ return new StorageTransferNetworkNode(
getEnergyUsage(properties),
energyUsagePerStorage,
size
diff --git a/refinedstorage2-network-test/src/test/java/com/refinedmods/refinedstorage2/network/test/NetworkNodeFactoryTest.java b/refinedstorage2-network-test/src/test/java/com/refinedmods/refinedstorage2/network/test/NetworkNodeFactoryTest.java
index baf5f2079..cff8bdbf9 100644
--- a/refinedstorage2-network-test/src/test/java/com/refinedmods/refinedstorage2/network/test/NetworkNodeFactoryTest.java
+++ b/refinedstorage2-network-test/src/test/java/com/refinedmods/refinedstorage2/network/test/NetworkNodeFactoryTest.java
@@ -8,8 +8,10 @@
import com.refinedmods.refinedstorage2.api.network.impl.node.grid.GridNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.iface.InterfaceNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.importer.ImporterNetworkNode;
-import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageNetworkNode;
+import com.refinedmods.refinedstorage2.api.network.impl.node.relay.RelayInputNetworkNode;
+import com.refinedmods.refinedstorage2.api.network.impl.node.relay.RelayOutputNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.storage.StorageNetworkNode;
+import com.refinedmods.refinedstorage2.api.network.impl.node.storagetransfer.StorageTransferNetworkNode;
import org.junit.jupiter.api.Test;
@@ -21,8 +23,6 @@ class NetworkNodeFactoryTest {
@AddNetworkNode
ControllerNetworkNode controller;
@AddNetworkNode
- MultiStorageNetworkNode multiStorage;
- @AddNetworkNode
ExporterNetworkNode exporter;
@AddNetworkNode
GridNetworkNode grid;
@@ -38,6 +38,12 @@ class NetworkNodeFactoryTest {
ExternalStorageNetworkNode externalStorage;
@AddNetworkNode
DetectorNetworkNode detector;
+ @AddNetworkNode
+ RelayInputNetworkNode relayInput;
+ @AddNetworkNode
+ RelayOutputNetworkNode relayOutput;
+ @AddNetworkNode
+ StorageTransferNetworkNode storageTransfer;
@Test
void testInitialization() {
diff --git a/refinedstorage2-network-test/src/test/java/com/refinedmods/refinedstorage2/network/test/NetworkTestExtensionTest.java b/refinedstorage2-network-test/src/test/java/com/refinedmods/refinedstorage2/network/test/NetworkTestExtensionTest.java
index f842ed7c8..7f75d9e2d 100644
--- a/refinedstorage2-network-test/src/test/java/com/refinedmods/refinedstorage2/network/test/NetworkTestExtensionTest.java
+++ b/refinedstorage2-network-test/src/test/java/com/refinedmods/refinedstorage2/network/test/NetworkTestExtensionTest.java
@@ -3,14 +3,12 @@
import com.refinedmods.refinedstorage2.api.network.Network;
import com.refinedmods.refinedstorage2.api.network.energy.EnergyNetworkComponent;
import com.refinedmods.refinedstorage2.api.network.impl.node.SimpleNetworkNode;
-import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.storage.StorageNetworkNode;
import com.refinedmods.refinedstorage2.api.network.node.GraphNetworkComponent;
import com.refinedmods.refinedstorage2.api.network.node.container.NetworkNodeContainer;
import com.refinedmods.refinedstorage2.api.network.security.SecurityNetworkComponent;
import com.refinedmods.refinedstorage2.api.network.storage.StorageNetworkComponent;
import com.refinedmods.refinedstorage2.network.test.nodefactory.AbstractNetworkNodeFactory;
-import com.refinedmods.refinedstorage2.network.test.nodefactory.MultiStorageNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.SimpleNetworkNodeFactory;
import com.refinedmods.refinedstorage2.network.test.nodefactory.StorageNetworkNodeFactory;
@@ -23,7 +21,7 @@
@ExtendWith({NetworkTestExtension.class})
@SetupNetwork(id = "a", energyCapacity = 100, energyStored = 50)
@SetupNetwork(id = "b")
-@RegisterNetworkNode(value = MultiStorageNetworkNodeFactory.class, clazz = MultiStorageNetworkNode.class)
+@RegisterNetworkNode(value = StorageNetworkNodeFactory.class, clazz = StorageNetworkNode.class)
@RegisterNetworkNode(value = StorageNetworkNodeFactory.class, clazz = StorageNetworkNode.class)
@RegisterNetworkNode(value = SimpleNetworkNodeFactory.class, clazz = SimpleNetworkNode.class)
class NetworkTestExtensionTest {
@@ -41,7 +39,7 @@ class NetworkTestExtensionTest {
@AddNetworkNode(networkId = "b", properties = {
@AddNetworkNode.Property(key = AbstractNetworkNodeFactory.PROPERTY_ACTIVE, boolValue = false)
})
- MultiStorageNetworkNode storageInB;
+ StorageNetworkNode storageInB;
@AddNetworkNode(networkId = "nonexistent")
SimpleNetworkNode nonexistentNetworkNode;
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/AbstractStorageContainerNetworkNode.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/AbstractStorageContainerNetworkNode.java
new file mode 100644
index 000000000..5258c2dfc
--- /dev/null
+++ b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/AbstractStorageContainerNetworkNode.java
@@ -0,0 +1,119 @@
+package com.refinedmods.refinedstorage2.api.network.impl.node;
+
+import com.refinedmods.refinedstorage2.api.network.impl.storage.AbstractStorageNetworkNode;
+import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage;
+import com.refinedmods.refinedstorage2.api.storage.Storage;
+import com.refinedmods.refinedstorage2.api.storage.StorageState;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractStorageContainerNetworkNode extends AbstractStorageNetworkNode {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractStorageContainerNetworkNode.class);
+
+ protected final StateTrackedStorage[] storages;
+
+ private final long energyUsage;
+ private final long energyUsagePerStorage;
+
+ @Nullable
+ private Provider provider;
+ @Nullable
+ private StateTrackedStorage.Listener listener;
+ private int activeStorages;
+
+ protected AbstractStorageContainerNetworkNode(final long energyUsage,
+ final long energyUsagePerStorage,
+ final int size) {
+ this.energyUsage = energyUsage;
+ this.energyUsagePerStorage = energyUsagePerStorage;
+ this.storages = new StateTrackedStorage[size];
+ }
+
+ public void setListener(final StateTrackedStorage.Listener listener) {
+ this.listener = listener;
+ }
+
+ public void setProvider(final Provider provider) {
+ this.provider = provider;
+ final List changes = new ArrayList<>();
+ for (int i = 0; i < storages.length; ++i) {
+ changes.addAll(initializeStorage(i));
+ }
+ // If we are already initialized, update all the storages to keep the exposed storages in sync.
+ // If we are not initialized, update nothing as we have to wait for an activeness update.
+ if (activeStorages > 0) {
+ changes.forEach(this::onStorageChange);
+ }
+ updateActiveStorageCount();
+ }
+
+ public void onStorageChanged(final int index) {
+ if (index < 0 || index >= storages.length) {
+ LOGGER.warn("Invalid index {}", index);
+ return;
+ }
+ initializeStorage(index).forEach(this::onStorageChange);
+ updateActiveStorageCount();
+ }
+
+ protected void onStorageChange(final StorageChange change) {
+ // no op
+ }
+
+ private Set initializeStorage(final int index) {
+ final Set results = new HashSet<>();
+ if (storages[index] != null) {
+ results.add(new StorageChange(true, storages[index]));
+ }
+ if (provider != null) {
+ provider.resolve(index).ifPresentOrElse(resolved -> {
+ final StateTrackedStorage newStorage = new StateTrackedStorage(resolved, listener);
+ storages[index] = newStorage;
+ results.add(new StorageChange(false, newStorage));
+ }, () -> storages[index] = null);
+ }
+ return results;
+ }
+
+ private void updateActiveStorageCount() {
+ this.activeStorages = (int) Arrays.stream(storages).filter(Objects::nonNull).count();
+ }
+
+ @Override
+ public long getEnergyUsage() {
+ return energyUsage + (energyUsagePerStorage * activeStorages);
+ }
+
+ public int getSize() {
+ return storages.length;
+ }
+
+ public StorageState getState(final int index) {
+ final var storage = storages[index];
+ if (storage == null) {
+ return StorageState.NONE;
+ }
+ if (!isActive()) {
+ return StorageState.INACTIVE;
+ }
+ return storage.getState();
+ }
+
+ protected record StorageChange(boolean removed, StateTrackedStorage storage) {
+ }
+
+ @FunctionalInterface
+ public interface Provider {
+ Optional resolve(int index);
+ }
+}
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ExposedMultiStorage.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ExposedMultiStorage.java
deleted file mode 100644
index 7823b4dc5..000000000
--- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ExposedMultiStorage.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage;
-
-import com.refinedmods.refinedstorage2.api.network.impl.storage.AbstractImmutableConfiguredProxyStorage;
-import com.refinedmods.refinedstorage2.api.network.impl.storage.StorageConfiguration;
-import com.refinedmods.refinedstorage2.api.resource.ResourceKey;
-import com.refinedmods.refinedstorage2.api.resource.list.ResourceListImpl;
-import com.refinedmods.refinedstorage2.api.storage.Actor;
-import com.refinedmods.refinedstorage2.api.storage.Storage;
-import com.refinedmods.refinedstorage2.api.storage.composite.CompositeStorage;
-import com.refinedmods.refinedstorage2.api.storage.composite.CompositeStorageImpl;
-import com.refinedmods.refinedstorage2.api.storage.composite.ParentComposite;
-import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedResource;
-
-import java.util.List;
-import java.util.Optional;
-
-class ExposedMultiStorage extends AbstractImmutableConfiguredProxyStorage
- implements CompositeStorage {
- protected ExposedMultiStorage(final StorageConfiguration config) {
- super(config, new CompositeStorageImpl(new ResourceListImpl()));
- }
-
- @Override
- public void sortSources() {
- // no-op: cannot sort individual storages.
- }
-
- @Override
- public void addSource(final Storage source) {
- getDelegate().addSource(source);
- }
-
- @Override
- public void removeSource(final Storage source) {
- getDelegate().removeSource(source);
- }
-
- @Override
- public List getSources() {
- return getDelegate().getSources();
- }
-
- @Override
- public void clearSources() {
- getDelegate().clearSources();
- }
-
- @Override
- public Optional findTrackedResourceByActorType(final ResourceKey resource,
- final Class extends Actor> actorType) {
- return getDelegate().findTrackedResourceByActorType(resource, actorType);
- }
-
- @Override
- public void onAddedIntoComposite(final ParentComposite parentComposite) {
- getDelegate().onAddedIntoComposite(parentComposite);
- }
-
- @Override
- public void onRemovedFromComposite(final ParentComposite parentComposite) {
- getDelegate().onRemovedFromComposite(parentComposite);
- }
-}
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageNetworkNode.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageNetworkNode.java
deleted file mode 100644
index 463778f84..000000000
--- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageNetworkNode.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage;
-
-import com.refinedmods.refinedstorage2.api.network.impl.storage.AbstractStorageNetworkNode;
-import com.refinedmods.refinedstorage2.api.network.storage.StorageProvider;
-import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage;
-import com.refinedmods.refinedstorage2.api.storage.Storage;
-import com.refinedmods.refinedstorage2.api.storage.StorageState;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import javax.annotation.Nullable;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class MultiStorageNetworkNode extends AbstractStorageNetworkNode implements StorageProvider {
- private static final Logger LOGGER = LoggerFactory.getLogger(MultiStorageNetworkNode.class);
-
- @Nullable
- private MultiStorageProvider provider;
- @Nullable
- private StateTrackedStorage.Listener listener;
-
- private final long energyUsage;
- private final long energyUsagePerStorage;
-
- private final StateTrackedStorage[] cache;
- private final ExposedMultiStorage storage;
- private int activeStorages;
-
- public MultiStorageNetworkNode(final long energyUsage,
- final long energyUsagePerStorage,
- final int size) {
- this.energyUsage = energyUsage;
- this.energyUsagePerStorage = energyUsagePerStorage;
- this.storage = new ExposedMultiStorage(this);
- this.cache = new StateTrackedStorage[size];
- }
-
- public void setProvider(final MultiStorageProvider provider) {
- this.provider = provider;
- final List changes = new ArrayList<>();
- for (int i = 0; i < cache.length; ++i) {
- changes.addAll(initializeStorage(i));
- }
- // If we are already initialized, update all the storages to keep the exposed storages in sync.
- // If we are not initialized, update nothing as we have to wait for an activeness update.
- if (activeStorages > 0) {
- changes.forEach(this::processStorageChange);
- }
- updateActiveStorageCount();
- }
-
- public void onStorageChanged(final int index) {
- if (index < 0 || index >= cache.length) {
- LOGGER.warn("Invalid index {}", index);
- return;
- }
- initializeStorage(index).forEach(this::processStorageChange);
- updateActiveStorageCount();
- }
-
- private Set initializeStorage(final int index) {
- final Set results = new HashSet<>();
-
- if (cache[index] != null) {
- results.add(new StorageChange(true, cache[index]));
- }
-
- if (provider != null) {
- provider.resolve(index).ifPresentOrElse(resolved -> {
- final StateTrackedStorage newStorage = new StateTrackedStorage(resolved, listener);
- cache[index] = newStorage;
- results.add(new StorageChange(false, newStorage));
- }, () -> cache[index] = null);
- }
-
- return results;
- }
-
- private void processStorageChange(final StorageChange change) {
- if (!isActive()) {
- return;
- }
- if (change.removed) {
- storage.removeSource(change.storage);
- } else {
- storage.addSource(change.storage);
- }
- }
-
- private void updateActiveStorageCount() {
- this.activeStorages = (int) Arrays.stream(cache).filter(Objects::nonNull).count();
- }
-
- @Override
- protected void onActiveChanged(final boolean newActive) {
- super.onActiveChanged(newActive);
- if (network == null) {
- return;
- }
- LOGGER.debug("Activeness got changed to {}, updating underlying internal storages", newActive);
- if (newActive) {
- enableAllStorages();
- } else {
- disableAllStorages();
- }
- }
-
- private void enableAllStorages() {
- for (final StateTrackedStorage internalStorage : cache) {
- if (internalStorage != null) {
- storage.addSource(internalStorage);
- }
- }
- }
-
- private void disableAllStorages() {
- storage.clearSources();
- }
-
- public void setListener(final StateTrackedStorage.Listener listener) {
- this.listener = listener;
- }
-
- @Override
- public long getEnergyUsage() {
- return energyUsage + (energyUsagePerStorage * activeStorages);
- }
-
- public int getSize() {
- return cache.length;
- }
-
- public StorageState getState(final int index) {
- final var cached = cache[index];
- if (cached == null) {
- return StorageState.NONE;
- }
- if (!isActive()) {
- return StorageState.INACTIVE;
- }
- return cached.getState();
- }
-
- @Override
- public Storage getStorage() {
- return storage;
- }
-
- private record StorageChange(boolean removed, StateTrackedStorage storage) {
- }
-}
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageProvider.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageProvider.java
deleted file mode 100644
index 8dd420fa1..000000000
--- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageProvider.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage;
-
-import com.refinedmods.refinedstorage2.api.storage.Storage;
-
-import java.util.Optional;
-
-@FunctionalInterface
-public interface MultiStorageProvider {
- Optional resolve(int index);
-}
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/ExposedStorage.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/ExposedStorage.java
index c4e7b035b..48a2104f7 100644
--- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/ExposedStorage.java
+++ b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/ExposedStorage.java
@@ -1,60 +1,76 @@
package com.refinedmods.refinedstorage2.api.network.impl.node.storage;
-import com.refinedmods.refinedstorage2.api.network.impl.storage.AbstractConfiguredProxyStorage;
+import com.refinedmods.refinedstorage2.api.network.impl.storage.AbstractImmutableConfiguredProxyStorage;
import com.refinedmods.refinedstorage2.api.network.impl.storage.StorageConfiguration;
import com.refinedmods.refinedstorage2.api.resource.ResourceKey;
+import com.refinedmods.refinedstorage2.api.resource.list.ResourceListImpl;
import com.refinedmods.refinedstorage2.api.storage.Actor;
import com.refinedmods.refinedstorage2.api.storage.Storage;
+import com.refinedmods.refinedstorage2.api.storage.composite.CompositeStorage;
+import com.refinedmods.refinedstorage2.api.storage.composite.CompositeStorageImpl;
import com.refinedmods.refinedstorage2.api.storage.composite.ParentComposite;
import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorage;
import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedResource;
-import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedStorage;
-import java.util.HashSet;
+import java.util.List;
import java.util.Optional;
-import java.util.Set;
-class ExposedStorage extends AbstractConfiguredProxyStorage implements TrackedStorage {
- private final Set parents = new HashSet<>();
+class ExposedStorage extends AbstractImmutableConfiguredProxyStorage implements CompositeStorage {
+ protected ExposedStorage(final StorageConfiguration config) {
+ super(config, new CompositeStorageImpl(new ResourceListImpl()));
+ }
- ExposedStorage(final StorageConfiguration config) {
- super(config);
+ long getCapacity() {
+ final CompositeStorageImpl delegate = getUnsafeDelegate();
+ if (delegate == null) {
+ return 0;
+ }
+ return delegate.getSources()
+ .stream()
+ .filter(LimitedStorage.class::isInstance)
+ .map(LimitedStorage.class::cast)
+ .mapToLong(LimitedStorage::getCapacity)
+ .sum();
}
@Override
- public Optional findTrackedResourceByActorType(final ResourceKey resource,
- final Class extends Actor> actorType) {
- return getUnsafeDelegate() instanceof TrackedStorage trackedStorage
- ? trackedStorage.findTrackedResourceByActorType(resource, actorType)
- : Optional.empty();
+ public void sortSources() {
+ // no-op: cannot sort individual storages.
}
@Override
- public void onAddedIntoComposite(final ParentComposite parentComposite) {
- parents.add(parentComposite);
+ public void addSource(final Storage source) {
+ getDelegate().addSource(source);
}
@Override
- public void onRemovedFromComposite(final ParentComposite parentComposite) {
- parents.remove(parentComposite);
+ public void removeSource(final Storage source) {
+ getDelegate().removeSource(source);
+ }
+
+ @Override
+ public List getSources() {
+ return getDelegate().getSources();
}
- public long getCapacity() {
- return getUnsafeDelegate() instanceof LimitedStorage limitedStorage
- ? limitedStorage.getCapacity()
- : 0L;
+ @Override
+ public void clearSources() {
+ getDelegate().clearSources();
+ }
+
+ @Override
+ public Optional findTrackedResourceByActorType(final ResourceKey resource,
+ final Class extends Actor> actorType) {
+ return getDelegate().findTrackedResourceByActorType(resource, actorType);
}
@Override
- public void setDelegate(final Storage newDelegate) {
- super.setDelegate(newDelegate);
- parents.forEach(parent -> parent.onSourceAddedToChild(newDelegate));
+ public void onAddedIntoComposite(final ParentComposite parentComposite) {
+ getDelegate().onAddedIntoComposite(parentComposite);
}
@Override
- public void clearDelegate() {
- final Storage delegate = getDelegate();
- parents.forEach(parent -> parent.onSourceRemovedFromChild(delegate));
- super.clearDelegate();
+ public void onRemovedFromComposite(final ParentComposite parentComposite) {
+ getDelegate().onRemovedFromComposite(parentComposite);
}
}
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/StorageNetworkNode.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/StorageNetworkNode.java
index ca7e2773f..b58b3cbb8 100644
--- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/StorageNetworkNode.java
+++ b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/StorageNetworkNode.java
@@ -1,48 +1,59 @@
package com.refinedmods.refinedstorage2.api.network.impl.node.storage;
-import com.refinedmods.refinedstorage2.api.network.impl.storage.AbstractStorageNetworkNode;
+import com.refinedmods.refinedstorage2.api.network.impl.node.AbstractStorageContainerNetworkNode;
import com.refinedmods.refinedstorage2.api.network.storage.StorageProvider;
+import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage;
import com.refinedmods.refinedstorage2.api.storage.Storage;
-import javax.annotation.Nullable;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class StorageNetworkNode extends AbstractStorageNetworkNode implements StorageProvider {
+public class StorageNetworkNode extends AbstractStorageContainerNetworkNode implements StorageProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(StorageNetworkNode.class);
- private final long energyUsage;
- private final ExposedStorage storage = new ExposedStorage(this);
- @Nullable
- private Storage internalStorage;
+ private final ExposedStorage storage;
- public StorageNetworkNode(final long energyUsage) {
- this.energyUsage = energyUsage;
+ public StorageNetworkNode(final long energyUsage, final long energyUsagePerStorage, final int size) {
+ super(energyUsage, energyUsagePerStorage, size);
+ this.storage = new ExposedStorage(this);
}
- public void setStorage(final Storage storage) {
- LOGGER.debug("Loading storage {}", storage);
- this.internalStorage = storage;
+ @Override
+ protected void onStorageChange(final AbstractStorageContainerNetworkNode.StorageChange change) {
+ if (!isActive()) {
+ return;
+ }
+ if (change.removed()) {
+ storage.removeSource(change.storage());
+ } else {
+ storage.addSource(change.storage());
+ }
}
@Override
protected void onActiveChanged(final boolean newActive) {
super.onActiveChanged(newActive);
- if (network == null || internalStorage == null) {
+ if (network == null) {
return;
}
- LOGGER.debug("Storage activeness got changed to '{}', updating underlying storage", newActive);
+ LOGGER.debug("Activeness got changed to {}, updating underlying internal storages", newActive);
if (newActive) {
- storage.setDelegate(internalStorage);
+ enableAllStorages();
} else {
- storage.clearDelegate();
+ disableAllStorages();
}
}
- @Override
- public long getEnergyUsage() {
- return energyUsage;
+ private void enableAllStorages() {
+ for (final StateTrackedStorage internalStorage : storages) {
+ if (internalStorage != null) {
+ storage.addSource(internalStorage);
+ }
+ }
+ }
+
+ private void disableAllStorages() {
+ storage.clearSources();
}
public long getStored() {
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferListener.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferListener.java
new file mode 100644
index 000000000..b4e34ced4
--- /dev/null
+++ b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferListener.java
@@ -0,0 +1,6 @@
+package com.refinedmods.refinedstorage2.api.network.impl.node.storagetransfer;
+
+@FunctionalInterface
+public interface StorageTransferListener {
+ void onTransferSuccess(int index);
+}
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferMode.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferMode.java
new file mode 100644
index 000000000..58e8eed37
--- /dev/null
+++ b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferMode.java
@@ -0,0 +1,6 @@
+package com.refinedmods.refinedstorage2.api.network.impl.node.storagetransfer;
+
+public enum StorageTransferMode {
+ INSERT,
+ EXTRACT
+}
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferNetworkNode.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferNetworkNode.java
new file mode 100644
index 000000000..5348a0935
--- /dev/null
+++ b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferNetworkNode.java
@@ -0,0 +1,141 @@
+package com.refinedmods.refinedstorage2.api.network.impl.node.storagetransfer;
+
+import com.refinedmods.refinedstorage2.api.network.impl.node.AbstractStorageContainerNetworkNode;
+import com.refinedmods.refinedstorage2.api.network.node.NetworkNodeActor;
+import com.refinedmods.refinedstorage2.api.network.storage.StorageNetworkComponent;
+import com.refinedmods.refinedstorage2.api.resource.ResourceAmount;
+import com.refinedmods.refinedstorage2.api.resource.ResourceKey;
+import com.refinedmods.refinedstorage2.api.storage.Actor;
+import com.refinedmods.refinedstorage2.api.storage.Storage;
+import com.refinedmods.refinedstorage2.api.storage.TransferHelper;
+import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorage;
+
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.function.Predicate;
+import java.util.function.ToLongFunction;
+import javax.annotation.Nullable;
+
+public class StorageTransferNetworkNode extends AbstractStorageContainerNetworkNode {
+ private final Actor actor = new NetworkNodeActor(this);
+
+ private StorageTransferMode mode = StorageTransferMode.INSERT;
+ @Nullable
+ private ToLongFunction transferQuotaProvider;
+ @Nullable
+ private StorageTransferListener listener;
+
+ public StorageTransferNetworkNode(final long energyUsage, final long energyUsagePerStorage, final int size) {
+ super(energyUsage, energyUsagePerStorage, size);
+ }
+
+ public void setMode(final StorageTransferMode mode) {
+ this.mode = mode;
+ }
+
+ public void setTransferQuotaProvider(final ToLongFunction transferQuotaProvider) {
+ this.transferQuotaProvider = transferQuotaProvider;
+ }
+
+ public void setListener(@Nullable final StorageTransferListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void doWork() {
+ super.doWork();
+ if (!isActive() || network == null) {
+ return;
+ }
+ final StorageNetworkComponent networkStorage = network.getComponent(StorageNetworkComponent.class);
+ for (int i = 0; i < storages.length / 2; ++i) {
+ final Storage storage = storages[i];
+ if (storage == null) {
+ continue;
+ }
+ final Result result = transfer(storage, networkStorage);
+ if (processResult(result, i)) {
+ return;
+ }
+ }
+ }
+
+ private Result transfer(final Storage storage, final StorageNetworkComponent networkStorage) {
+ if (transferQuotaProvider == null) {
+ return Result.FAILURE;
+ }
+ final long transferQuota = transferQuotaProvider.applyAsLong(storage);
+ if (mode == StorageTransferMode.INSERT) {
+ return transfer(storage, networkStorage, transferQuota, this::hasNoExtractableResources);
+ }
+ return transfer(
+ networkStorage,
+ storage,
+ transferQuota,
+ source -> hasNoExtractableResources(source) || storageIsFull(storage)
+ );
+ }
+
+ private Result transfer(final Storage source,
+ final Storage destination,
+ final long transferQuota,
+ final Predicate readyPredicate) {
+ if (readyPredicate.test(source)) {
+ return Result.SUCCESS;
+ }
+ if (transfer(source, destination, transferQuota)) {
+ return readyPredicate.test(source)
+ ? Result.SUCCESS
+ : Result.PARTIAL;
+ }
+ return Result.FAILURE;
+ }
+
+ private boolean transfer(final Storage source, final Storage destination, final long transferQuota) {
+ long remainder = transferQuota;
+ final Collection all = new LinkedHashSet<>(source.getAll());
+ for (final ResourceAmount resourceAmount : all) {
+ final ResourceKey resource = resourceAmount.getResource();
+ if (!isAllowed(resource)) {
+ continue;
+ }
+ final long amount = Math.min(remainder, resourceAmount.getAmount());
+ final long transferred = TransferHelper.transfer(resource, amount, actor, source, destination, source);
+ remainder -= transferred;
+ if (remainder == 0) {
+ break;
+ }
+ }
+ return remainder != transferQuota;
+ }
+
+ private boolean hasNoExtractableResources(final Storage source) {
+ return source.getAll().stream().noneMatch(resourceAmount -> isAllowed(resourceAmount.getResource()));
+ }
+
+ private boolean storageIsFull(final Storage storage) {
+ return storage instanceof LimitedStorage limitedStorage
+ && limitedStorage.getCapacity() > 0
+ && limitedStorage.getCapacity() == limitedStorage.getStored();
+ }
+
+ private boolean processResult(final Result result, final int index) {
+ if (result.isSuccess()) {
+ if (result == Result.SUCCESS && listener != null) {
+ listener.onTransferSuccess(index);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private enum Result {
+ SUCCESS,
+ PARTIAL,
+ FAILURE;
+
+ private boolean isSuccess() {
+ return this == PARTIAL || this == SUCCESS;
+ }
+ }
+}
diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/package-info.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/package-info.java
similarity index 72%
rename from refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/package-info.java
rename to refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/package-info.java
index 3e84146e5..6f817bc33 100644
--- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/package-info.java
+++ b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/package-info.java
@@ -1,6 +1,6 @@
@ParametersAreNonnullByDefault
@FieldsAndMethodsAreNonnullByDefault
-package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage;
+package com.refinedmods.refinedstorage2.api.network.impl.node.storagetransfer;
import com.refinedmods.refinedstorage2.api.core.FieldsAndMethodsAreNonnullByDefault;
diff --git a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/PriorityNetworkBuilderImplTest.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/PriorityNetworkBuilderImplTest.java
index b5b5bea44..625e32e7c 100644
--- a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/PriorityNetworkBuilderImplTest.java
+++ b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/PriorityNetworkBuilderImplTest.java
@@ -13,6 +13,7 @@
import com.refinedmods.refinedstorage2.api.storage.InMemoryStorageImpl;
import com.refinedmods.refinedstorage2.network.test.fake.FakeActor;
+import java.util.Optional;
import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
@@ -115,10 +116,10 @@ void shouldRespectPriorityWhenMerging() {
private NetworkSide createNetworkSide(final MasterSlave side,
final Supplier networkFactory) {
- final StorageNetworkNode nodeA = new StorageNetworkNode(0);
+ final StorageNetworkNode nodeA = new StorageNetworkNode(0, 0, 1);
final InMemoryStorageImpl storage = new InMemoryStorageImpl();
storage.insert(side, 10, Action.EXECUTE, FakeActor.INSTANCE);
- nodeA.setStorage(storage);
+ nodeA.setProvider(index -> Optional.of(storage));
final NetworkNodeContainer a = createContainerWithNetwork(
nodeA,
container -> networkFactory.get(),
diff --git a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageProviderImpl.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/ProviderImpl.java
similarity index 78%
rename from refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageProviderImpl.java
rename to refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/ProviderImpl.java
index 09df89765..a55d74eda 100644
--- a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageProviderImpl.java
+++ b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/ProviderImpl.java
@@ -1,4 +1,4 @@
-package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage;
+package com.refinedmods.refinedstorage2.api.network.impl.node;
import com.refinedmods.refinedstorage2.api.storage.Storage;
@@ -6,7 +6,7 @@
import java.util.Map;
import java.util.Optional;
-class MultiStorageProviderImpl implements MultiStorageProvider {
+public class ProviderImpl implements AbstractStorageContainerNetworkNode.Provider {
private final Map storages = new HashMap<>();
@Override
diff --git a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageNetworkNodeTest.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageNetworkNodeTest.java
deleted file mode 100644
index 3c696ab91..000000000
--- a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageNetworkNodeTest.java
+++ /dev/null
@@ -1,698 +0,0 @@
-package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage;
-
-import com.refinedmods.refinedstorage2.api.core.Action;
-import com.refinedmods.refinedstorage2.api.network.Network;
-import com.refinedmods.refinedstorage2.api.network.storage.StorageNetworkComponent;
-import com.refinedmods.refinedstorage2.api.resource.ResourceAmount;
-import com.refinedmods.refinedstorage2.api.resource.filter.FilterMode;
-import com.refinedmods.refinedstorage2.api.storage.AccessMode;
-import com.refinedmods.refinedstorage2.api.storage.EmptyActor;
-import com.refinedmods.refinedstorage2.api.storage.InMemoryStorageImpl;
-import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage;
-import com.refinedmods.refinedstorage2.api.storage.Storage;
-import com.refinedmods.refinedstorage2.api.storage.StorageState;
-import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorageImpl;
-import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedStorageImpl;
-import com.refinedmods.refinedstorage2.network.test.AddNetworkNode;
-import com.refinedmods.refinedstorage2.network.test.InjectNetwork;
-import com.refinedmods.refinedstorage2.network.test.InjectNetworkStorageComponent;
-import com.refinedmods.refinedstorage2.network.test.NetworkTest;
-import com.refinedmods.refinedstorage2.network.test.SetupNetwork;
-import com.refinedmods.refinedstorage2.network.test.fake.FakeActor;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
-import org.junit.jupiter.params.provider.ValueSource;
-
-import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.A;
-import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.A_ALTERNATIVE;
-import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.A_ALTERNATIVE2;
-import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.B;
-import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.B_ALTERNATIVE;
-import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.C;
-import static com.refinedmods.refinedstorage2.network.test.nodefactory.AbstractNetworkNodeFactory.PROPERTY_ENERGY_USAGE;
-import static com.refinedmods.refinedstorage2.network.test.nodefactory.MultiStorageNetworkNodeFactory.PROPERTY_ENERGY_USAGE_PER_STORAGE;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-@NetworkTest
-@SetupNetwork
-class MultiStorageNetworkNodeTest {
- private static final long BASE_USAGE = 10;
- private static final long USAGE_PER_STORAGE = 3;
-
- @AddNetworkNode(properties = {
- @AddNetworkNode.Property(key = PROPERTY_ENERGY_USAGE, longValue = BASE_USAGE),
- @AddNetworkNode.Property(key = PROPERTY_ENERGY_USAGE_PER_STORAGE, longValue = USAGE_PER_STORAGE)
- })
- MultiStorageNetworkNode sut;
-
- MultiStorageProviderImpl provider;
-
- @BeforeEach
- void setUp() {
- provider = new MultiStorageProviderImpl();
- }
-
- @Test
- void shouldInitializeButNotShowResourcesYet(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final Storage storage = new LimitedStorageImpl(10);
- storage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(1, storage);
-
- // Act
- sut.setProvider(provider);
-
- // Assert
- assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + USAGE_PER_STORAGE);
- assertThat(networkStorage.getAll()).isEmpty();
- assertThat(networkStorage.getStored()).isZero();
- }
-
- @Test
- void shouldInitializeAndShowResourcesAfterEnabling(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final Storage storage = new LimitedStorageImpl(100);
- storage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(1, storage);
-
- // Act
- sut.setProvider(provider);
- sut.setActive(true);
-
- // Assert
- assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
- new ResourceAmount(A, 50),
- new ResourceAmount(B, 50)
- );
- }
-
- @Test
- void shouldInitializeMultipleTimes(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final Storage storage1 = new LimitedStorageImpl(10);
- storage1.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(8, storage1);
- sut.setProvider(provider);
- sut.setActive(true);
-
- final Storage storage2 = new LimitedStorageImpl(10);
- storage2.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(8, storage2);
-
- // Act
- sut.setProvider(provider);
-
- // Assert
- assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + USAGE_PER_STORAGE);
- assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(B, 5)
- );
- }
-
- @Test
- void testInitialState(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
- // Assert
- assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE);
- assertThat(sut.getFilterMode()).isEqualTo(FilterMode.BLOCK);
- assertThat(networkStorage.getAll()).isEmpty();
- assertThat(networkStorage.getStored()).isZero();
- assertThat(sut.getSize()).isEqualTo(9);
- for (int i = 0; i < 9; ++i) {
- assertThat(sut.getState(i)).isEqualTo(StorageState.NONE);
- }
- }
-
- @ParameterizedTest
- @ValueSource(booleans = {true, false})
- void testState(final boolean active) {
- // Arrange
- final Storage normalStorage = new LimitedStorageImpl(100);
- normalStorage.insert(A, 74, Action.EXECUTE, EmptyActor.INSTANCE);
-
- final Storage nearCapacityStorage = new LimitedStorageImpl(100);
- nearCapacityStorage.insert(A, 75, Action.EXECUTE, EmptyActor.INSTANCE);
-
- final Storage fullStorage = new LimitedStorageImpl(100);
- fullStorage.insert(A, 100, Action.EXECUTE, EmptyActor.INSTANCE);
-
- final Storage unlimitedStorage = new InMemoryStorageImpl();
-
- provider.set(2, unlimitedStorage);
- provider.set(3, normalStorage);
- provider.set(5, nearCapacityStorage);
- provider.set(7, fullStorage);
-
- // Act
- sut.setProvider(provider);
- sut.setActive(active);
-
- // Assert
- assertThat(sut.getState(0)).isEqualTo(StorageState.NONE);
- assertThat(sut.getState(1)).isEqualTo(StorageState.NONE);
- assertThat(sut.getState(2)).isEqualTo(active ? StorageState.NORMAL : StorageState.INACTIVE);
- assertThat(sut.getState(3)).isEqualTo(active ? StorageState.NORMAL : StorageState.INACTIVE);
- assertThat(sut.getState(4)).isEqualTo(StorageState.NONE);
- assertThat(sut.getState(5)).isEqualTo(active ? StorageState.NEAR_CAPACITY : StorageState.INACTIVE);
- assertThat(sut.getState(6)).isEqualTo(StorageState.NONE);
- assertThat(sut.getState(7)).isEqualTo(active ? StorageState.FULL : StorageState.INACTIVE);
- assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + (USAGE_PER_STORAGE * 4));
- }
-
- @Test
- void shouldDetectNewStorage(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
- // Arrange
- initializeAndActivate();
-
- final Storage storage = new LimitedStorageImpl(10);
- storage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(8, storage);
-
- // Act
- sut.onStorageChanged(8);
-
- // Assert
- assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + USAGE_PER_STORAGE);
- assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(A, 5)
- );
- }
-
- @Test
- void shouldDetectChangedStorage(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
- // Arrange
- final Storage originalStorage = new LimitedStorageImpl(10);
- originalStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(0, originalStorage);
- initializeAndActivate();
-
- final Storage replacedStorage = new LimitedStorageImpl(10);
- replacedStorage.insert(B, 2, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(0, replacedStorage);
-
- // Act
- final Collection preChanging = new HashSet<>(networkStorage.getAll());
- sut.onStorageChanged(0);
- final Collection postChanging = networkStorage.getAll();
-
- // Assert
- assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + USAGE_PER_STORAGE);
- assertThat(preChanging).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(A, 5)
- );
- assertThat(postChanging).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(B, 2)
- );
- assertThat(networkStorage.getStored()).isEqualTo(2L);
- }
-
- @Test
- void shouldDetectRemovedStorage(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
- // Arrange
- final Storage storage = new LimitedStorageImpl(10);
- storage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(7, storage);
- initializeAndActivate();
-
- provider.remove(7);
-
- // Act
- final Collection preRemoval = new HashSet<>(networkStorage.getAll());
- sut.onStorageChanged(7);
- final Collection postRemoval = networkStorage.getAll();
-
- // Assert
- assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE);
- assertThat(preRemoval).isNotEmpty();
- assertThat(postRemoval).isEmpty();
- assertThat(networkStorage.getStored()).isZero();
- }
-
- @Test
- void shouldNotDetectStorageChangeInInvalidIndex() {
- // Act
- sut.onStorageChanged(-1);
- sut.onStorageChanged(9);
-
- // Assert
- assertThat(sut.getSize()).isEqualTo(9);
- for (int i = 0; i < 9; ++i) {
- assertThat(sut.getState(i)).isEqualTo(StorageState.NONE);
- }
- }
-
- @Test
- void shouldNotUpdateNetworkStorageWhenChangingStorageWhenInactive(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final Storage storage = new LimitedStorageImpl(100);
- storage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- final Collection preInactiveness = new HashSet<>(networkStorage.getAll());
- sut.setActive(false);
- sut.onStorageChanged(1);
- final Collection postInactiveness = networkStorage.getAll();
-
- // Assert
- assertThat(preInactiveness).isNotEmpty();
- assertThat(postInactiveness).isEmpty();
- assertThat(networkStorage.getStored()).isZero();
- }
-
- @Test
- void shouldHaveResourcesFromStoragePresentInNetwork(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final Storage storage = new LimitedStorageImpl(100);
- storage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(1, storage);
-
- initializeAndActivate();
-
- // Act
- final Collection resources = networkStorage.getAll();
- final long stored = networkStorage.getStored();
-
- // Assert
- assertThat(resources).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
- new ResourceAmount(A, 50),
- new ResourceAmount(B, 50)
- );
- assertThat(stored).isEqualTo(100);
- }
-
- @Test
- void shouldInsert(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
- // Arrange
- final Storage storage1 = new LimitedStorageImpl(100);
- provider.set(1, storage1);
-
- final Storage storage2 = new LimitedStorageImpl(100);
- provider.set(2, storage2);
-
- final Storage storage3 = new LimitedStorageImpl(100);
- provider.set(3, storage3);
-
- initializeAndActivate();
-
- // Act
- final long inserted1 = networkStorage.insert(A, 150, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted2 = networkStorage.insert(A, 10, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted3 = networkStorage.insert(B, 300, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(inserted1).isEqualTo(150);
- assertThat(inserted2).isEqualTo(10);
- assertThat(inserted3).isEqualTo(140);
-
- assertThat(storage1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(A, 100)
- );
- assertThat(storage2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
- new ResourceAmount(A, 60),
- new ResourceAmount(B, 40)
- );
- assertThat(storage3.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(B, 100)
- );
-
- assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
- new ResourceAmount(B, 140),
- new ResourceAmount(A, 160)
- );
- assertThat(networkStorage.getStored()).isEqualTo(inserted1 + inserted2 + inserted3);
- }
-
- @Test
- void shouldExtract(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
- // Arrange
- final Storage storage1 = new LimitedStorageImpl(100);
- storage1.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- storage1.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(1, storage1);
-
- final Storage storage2 = new LimitedStorageImpl(100);
- storage2.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- storage2.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(2, storage2);
-
- final Storage storage3 = new LimitedStorageImpl(100);
- storage3.insert(C, 10, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(3, storage3);
-
- initializeAndActivate();
-
- // Act
- final long extracted = networkStorage.extract(A, 85, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(extracted).isEqualTo(85);
-
- assertThat(storage1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(B, 50)
- );
- assertThat(storage2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
- new ResourceAmount(B, 50),
- new ResourceAmount(A, 15)
- );
- assertThat(storage3.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(C, 10)
- );
-
- assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
- new ResourceAmount(B, 100),
- new ResourceAmount(A, 15),
- new ResourceAmount(C, 10)
- );
- assertThat(networkStorage.getStored()).isEqualTo(125);
- }
-
- @Test
- void shouldRespectAllowlistWhenInserting(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- sut.setFilterMode(FilterMode.ALLOW);
- sut.setFilters(Set.of(A, B));
-
- final Storage storage = new LimitedStorageImpl(100);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- final long inserted1 = networkStorage.insert(A, 12, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted2 = networkStorage.insert(B, 12, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted3 = networkStorage.insert(C, 10, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(inserted1).isEqualTo(12);
- assertThat(inserted2).isEqualTo(12);
- assertThat(inserted3).isZero();
- }
-
- @Test
- void shouldRespectAllowlistWithNormalizerWhenInserting(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- sut.setFilterMode(FilterMode.ALLOW);
- sut.setFilters(Set.of(A));
- sut.setNormalizer(resource -> {
- if (resource == A_ALTERNATIVE || resource == A_ALTERNATIVE2) {
- return A;
- }
- if (resource == B_ALTERNATIVE) {
- return B;
- }
- return resource;
- });
-
- final Storage storage = new LimitedStorageImpl(100);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- final long inserted1 = networkStorage.insert(A, 1, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted2 = networkStorage.insert(A_ALTERNATIVE, 1, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted3 = networkStorage.insert(A_ALTERNATIVE2, 1, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted4 = networkStorage.insert(B, 1, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted5 = networkStorage.insert(B_ALTERNATIVE, 1, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(inserted1).isEqualTo(1);
- assertThat(inserted2).isEqualTo(1);
- assertThat(inserted3).isEqualTo(1);
- assertThat(inserted4).isZero();
- assertThat(inserted5).isZero();
- }
-
- @Test
- void shouldRespectEmptyAllowlistWhenInserting(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- sut.setFilterMode(FilterMode.ALLOW);
- sut.setFilters(Set.of());
-
- final Storage storage = new LimitedStorageImpl(100);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- final long inserted1 = networkStorage.insert(A, 12, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted2 = networkStorage.insert(B, 12, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted3 = networkStorage.insert(C, 10, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(inserted1).isZero();
- assertThat(inserted2).isZero();
- assertThat(inserted3).isZero();
- }
-
- @Test
- void shouldRespectBlocklistWhenInserting(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- sut.setFilterMode(FilterMode.BLOCK);
- sut.setFilters(Set.of(A, B));
-
- final Storage storage = new LimitedStorageImpl(100);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- final long inserted1 = networkStorage.insert(A, 12, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted2 = networkStorage.insert(B, 12, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted3 = networkStorage.insert(C, 10, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(inserted1).isZero();
- assertThat(inserted2).isZero();
- assertThat(inserted3).isEqualTo(10);
- }
-
- @Test
- void shouldRespectEmptyBlocklistWhenInserting(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- sut.setFilterMode(FilterMode.BLOCK);
- sut.setFilters(Set.of());
-
- final Storage storage = new LimitedStorageImpl(100);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- final long inserted1 = networkStorage.insert(A, 12, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted2 = networkStorage.insert(B, 12, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted3 = networkStorage.insert(C, 10, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(inserted1).isEqualTo(12);
- assertThat(inserted2).isEqualTo(12);
- assertThat(inserted3).isEqualTo(10);
- }
-
- @ParameterizedTest
- @EnumSource(AccessMode.class)
- void shouldRespectAccessModeWhenInserting(
- final AccessMode accessMode,
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- sut.setAccessMode(accessMode);
-
- final Storage storage = new LimitedStorageImpl(100);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- final long inserted = networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- switch (accessMode) {
- case INSERT_EXTRACT, INSERT -> assertThat(inserted).isEqualTo(5);
- case EXTRACT -> assertThat(inserted).isZero();
- }
- }
-
- @ParameterizedTest
- @EnumSource(AccessMode.class)
- void shouldRespectAccessModeWhenExtracting(
- final AccessMode accessMode,
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- sut.setAccessMode(accessMode);
-
- final Storage storage = new LimitedStorageImpl(100);
- provider.set(1, storage);
- initializeAndActivate();
-
- storage.insert(A, 20, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Act
- final long extracted = networkStorage.extract(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- switch (accessMode) {
- case INSERT_EXTRACT, EXTRACT -> assertThat(extracted).isEqualTo(5);
- case INSERT -> assertThat(extracted).isZero();
- }
- }
-
- @Test
- void shouldNotAllowInsertsWhenInactive(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final Storage storage = new LimitedStorageImpl(100);
- provider.set(1, storage);
- initializeAndActivate();
-
- sut.setActive(false);
-
- // Act
- final long inserted = networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(inserted).isZero();
- }
-
- @Test
- void shouldNotAllowExtractsWhenInactive(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final Storage storage = new LimitedStorageImpl(100);
- storage.insert(A, 20, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(1, storage);
- initializeAndActivate();
-
- sut.setActive(false);
-
- // Act
- final long extracted = networkStorage.extract(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(extracted).isZero();
- }
-
- @Test
- void shouldHideFromNetworkWhenInactive(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final Storage storage = new LimitedStorageImpl(100);
- storage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- final Collection preInactiveness = new HashSet<>(networkStorage.getAll());
- sut.setActive(false);
- final Collection postInactiveness = networkStorage.getAll();
-
- // Assert
- assertThat(preInactiveness).isNotEmpty();
- assertThat(postInactiveness).isEmpty();
- }
-
- @Test
- void shouldNoLongerShowOnNetworkWhenRemoved(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage,
- @InjectNetwork final Network network
- ) {
- // Arrange
- final Storage storage1 = new LimitedStorageImpl(100);
- storage1.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(1, storage1);
- initializeAndActivate();
-
- // Act & assert
- final Storage storage2 = new LimitedStorageImpl(100);
- storage2.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(2, storage2);
- sut.onStorageChanged(2);
-
- assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
- new ResourceAmount(A, 50),
- new ResourceAmount(B, 50)
- );
-
- network.removeContainer(() -> sut);
- assertThat(networkStorage.getAll()).isEmpty();
-
- final Storage storage3 = new LimitedStorageImpl(100);
- storage3.insert(C, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- provider.set(3, storage3);
- sut.onStorageChanged(3);
-
- assertThat(networkStorage.getAll()).isEmpty();
- }
-
- @Test
- void shouldTrackChanges(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
- // Arrange
- final Storage storage = new TrackedStorageImpl(new LimitedStorageImpl(100), () -> 0L);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- final long inserted = networkStorage.insert(A, 10, Action.EXECUTE, FakeActor.INSTANCE);
-
- // Assert
- assertThat(inserted).isEqualTo(10);
- assertThat(networkStorage.findTrackedResourceByActorType(A, FakeActor.class)).isNotEmpty();
- }
-
- @Test
- void shouldNotifyListenerWhenStateChanges(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final StateTrackedStorage.Listener listener = mock(StateTrackedStorage.Listener.class);
- sut.setListener(listener);
-
- final Storage storage = new LimitedStorageImpl(100);
- provider.set(1, storage);
- initializeAndActivate();
-
- // Act
- networkStorage.insert(A, 75, Action.EXECUTE, FakeActor.INSTANCE);
-
- // Assert
- verify(listener, times(1)).onStorageStateChanged();
- }
-
- private void initializeAndActivate() {
- sut.setProvider(provider);
- sut.setActive(true);
- }
-}
diff --git a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/PriorityMultiStorageNetworkNodeTest.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/PriorityStorageNetworkNodeTest.java
similarity index 78%
rename from refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/PriorityMultiStorageNetworkNodeTest.java
rename to refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/PriorityStorageNetworkNodeTest.java
index baf6d15f1..f1761eac5 100644
--- a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/PriorityMultiStorageNetworkNodeTest.java
+++ b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/PriorityStorageNetworkNodeTest.java
@@ -1,6 +1,7 @@
-package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage;
+package com.refinedmods.refinedstorage2.api.network.impl.node.storage;
import com.refinedmods.refinedstorage2.api.core.Action;
+import com.refinedmods.refinedstorage2.api.network.impl.node.ProviderImpl;
import com.refinedmods.refinedstorage2.api.network.storage.StorageNetworkComponent;
import com.refinedmods.refinedstorage2.api.storage.EmptyActor;
import com.refinedmods.refinedstorage2.api.storage.Storage;
@@ -19,40 +20,40 @@
@NetworkTest
@SetupNetwork
-class PriorityMultiStorageNetworkNodeTest {
+class PriorityStorageNetworkNodeTest {
@AddNetworkNode
- MultiStorageNetworkNode a;
+ StorageNetworkNode a;
@AddNetworkNode
- MultiStorageNetworkNode b;
+ StorageNetworkNode b;
- MultiStorageProviderImpl provider;
+ ProviderImpl provider;
@BeforeEach
void setUp() {
- provider = new MultiStorageProviderImpl();
+ provider = new ProviderImpl();
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void shouldRespectPriority(
- final boolean multiStorageAHasPriority,
+ final boolean storageAHasPriority,
@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
) {
// Arrange
final Storage storage1 = new LimitedStorageImpl(100);
- final MultiStorageProviderImpl provider1 = new MultiStorageProviderImpl();
+ final ProviderImpl provider1 = new ProviderImpl();
provider1.set(1, storage1);
a.setProvider(provider1);
a.setActive(true);
final Storage storage2 = new LimitedStorageImpl(100);
- final MultiStorageProviderImpl provider2 = new MultiStorageProviderImpl();
+ final ProviderImpl provider2 = new ProviderImpl();
provider2.set(1, storage2);
b.setProvider(provider2);
b.setActive(true);
- if (multiStorageAHasPriority) {
+ if (storageAHasPriority) {
a.setPriority(5);
b.setPriority(2);
} else {
@@ -64,7 +65,7 @@ void shouldRespectPriority(
networkStorage.insert(A, 1, Action.EXECUTE, EmptyActor.INSTANCE);
// Assert
- if (multiStorageAHasPriority) {
+ if (storageAHasPriority) {
assertThat(storage1.getAll()).isNotEmpty();
assertThat(storage2.getAll()).isEmpty();
} else {
diff --git a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/StorageNetworkNodeTest.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/StorageNetworkNodeTest.java
index bb04a9e36..441da0459 100644
--- a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/StorageNetworkNodeTest.java
+++ b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storage/StorageNetworkNodeTest.java
@@ -1,133 +1,407 @@
package com.refinedmods.refinedstorage2.api.network.impl.node.storage;
import com.refinedmods.refinedstorage2.api.core.Action;
+import com.refinedmods.refinedstorage2.api.network.Network;
+import com.refinedmods.refinedstorage2.api.network.impl.node.ProviderImpl;
import com.refinedmods.refinedstorage2.api.network.storage.StorageNetworkComponent;
import com.refinedmods.refinedstorage2.api.resource.ResourceAmount;
import com.refinedmods.refinedstorage2.api.resource.filter.FilterMode;
import com.refinedmods.refinedstorage2.api.storage.AccessMode;
import com.refinedmods.refinedstorage2.api.storage.EmptyActor;
+import com.refinedmods.refinedstorage2.api.storage.InMemoryStorageImpl;
+import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage;
import com.refinedmods.refinedstorage2.api.storage.Storage;
-import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorage;
+import com.refinedmods.refinedstorage2.api.storage.StorageState;
import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorageImpl;
import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedStorageImpl;
import com.refinedmods.refinedstorage2.network.test.AddNetworkNode;
+import com.refinedmods.refinedstorage2.network.test.InjectNetwork;
import com.refinedmods.refinedstorage2.network.test.InjectNetworkStorageComponent;
import com.refinedmods.refinedstorage2.network.test.NetworkTest;
import com.refinedmods.refinedstorage2.network.test.SetupNetwork;
import com.refinedmods.refinedstorage2.network.test.fake.FakeActor;
import java.util.Collection;
+import java.util.HashSet;
import java.util.Set;
-import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.ValueSource;
import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.A;
+import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.A_ALTERNATIVE;
+import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.A_ALTERNATIVE2;
import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.B;
+import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.B_ALTERNATIVE;
import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.C;
import static com.refinedmods.refinedstorage2.network.test.nodefactory.AbstractNetworkNodeFactory.PROPERTY_ENERGY_USAGE;
+import static com.refinedmods.refinedstorage2.network.test.nodefactory.StorageNetworkNodeFactory.PROPERTY_ENERGY_USAGE_PER_STORAGE;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
@NetworkTest
@SetupNetwork
class StorageNetworkNodeTest {
- private static final int ENERGY_USAGE = 5;
+ private static final long BASE_USAGE = 10;
+ private static final long USAGE_PER_STORAGE = 3;
@AddNetworkNode(properties = {
- @AddNetworkNode.Property(key = PROPERTY_ENERGY_USAGE, longValue = ENERGY_USAGE)
+ @AddNetworkNode.Property(key = PROPERTY_ENERGY_USAGE, longValue = BASE_USAGE),
+ @AddNetworkNode.Property(key = PROPERTY_ENERGY_USAGE_PER_STORAGE, longValue = USAGE_PER_STORAGE)
})
StorageNetworkNode sut;
+ ProviderImpl provider;
+
+ @BeforeEach
+ void setUp() {
+ provider = new ProviderImpl();
+ }
+
@Test
- void testInitialState(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ void shouldInitializeButNotShowResourcesYet(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ final Storage storage = new LimitedStorageImpl(10);
+ storage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, storage);
+
// Act
- final long inserted = networkStorage.insert(A, 10, Action.EXECUTE, EmptyActor.INSTANCE);
- final long extracted = networkStorage.extract(A, 10, Action.EXECUTE, EmptyActor.INSTANCE);
+ sut.setProvider(provider);
// Assert
- assertThat(inserted).isZero();
- assertThat(extracted).isZero();
- assertThat(sut.getEnergyUsage()).isEqualTo(ENERGY_USAGE);
- assertThat(sut.getAccessMode()).isEqualTo(AccessMode.INSERT_EXTRACT);
+ assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + USAGE_PER_STORAGE);
+ assertThat(networkStorage.getAll()).isEmpty();
+ assertThat(networkStorage.getStored()).isZero();
+ }
+
+ @Test
+ void shouldInitializeAndShowResourcesAfterEnabling(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ final Storage storage = new LimitedStorageImpl(100);
+ storage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, storage);
+
+ // Act
+ sut.setProvider(provider);
+ sut.setActive(true);
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 50),
+ new ResourceAmount(B, 50)
+ );
+ }
+
+ @Test
+ void shouldInitializeMultipleTimes(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ final Storage storage1 = new LimitedStorageImpl(10);
+ storage1.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(8, storage1);
+ sut.setProvider(provider);
+ sut.setActive(true);
+
+ final Storage storage2 = new LimitedStorageImpl(10);
+ storage2.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(8, storage2);
+
+ // Act
+ sut.setProvider(provider);
+
+ // Assert
+ assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + USAGE_PER_STORAGE);
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(B, 5)
+ );
+ }
+
+ @Test
+ void testInitialState(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Assert
+ assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE);
assertThat(sut.getFilterMode()).isEqualTo(FilterMode.BLOCK);
- assertThat(sut.getStored()).isZero();
- assertThat(sut.getCapacity()).isZero();
- assertThat(sut.getPriority()).isZero();
assertThat(networkStorage.getAll()).isEmpty();
assertThat(networkStorage.getStored()).isZero();
+ assertThat(sut.getSize()).isEqualTo(9);
+ for (int i = 0; i < 9; ++i) {
+ assertThat(sut.getState(i)).isEqualTo(StorageState.NONE);
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(booleans = {true, false})
+ void testState(final boolean active) {
+ // Arrange
+ final Storage normalStorage = new LimitedStorageImpl(100);
+ normalStorage.insert(A, 74, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage nearCapacityStorage = new LimitedStorageImpl(100);
+ nearCapacityStorage.insert(A, 75, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage fullStorage = new LimitedStorageImpl(100);
+ fullStorage.insert(A, 100, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage unlimitedStorage = new InMemoryStorageImpl();
+
+ provider.set(2, unlimitedStorage);
+ provider.set(3, normalStorage);
+ provider.set(5, nearCapacityStorage);
+ provider.set(7, fullStorage);
+
+ // Act
+ sut.setProvider(provider);
+ sut.setActive(active);
+
+ // Assert
+ assertThat(sut.getState(0)).isEqualTo(StorageState.NONE);
+ assertThat(sut.getState(1)).isEqualTo(StorageState.NONE);
+ assertThat(sut.getState(2)).isEqualTo(active ? StorageState.NORMAL : StorageState.INACTIVE);
+ assertThat(sut.getState(3)).isEqualTo(active ? StorageState.NORMAL : StorageState.INACTIVE);
+ assertThat(sut.getState(4)).isEqualTo(StorageState.NONE);
+ assertThat(sut.getState(5)).isEqualTo(active ? StorageState.NEAR_CAPACITY : StorageState.INACTIVE);
+ assertThat(sut.getState(6)).isEqualTo(StorageState.NONE);
+ assertThat(sut.getState(7)).isEqualTo(active ? StorageState.FULL : StorageState.INACTIVE);
+ assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + (USAGE_PER_STORAGE * 4));
}
@Test
- void shouldInitialize(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ void shouldDetectNewStorage(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
// Arrange
- final LimitedStorage limitedStorage = new LimitedStorageImpl(100);
- limitedStorage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ initializeAndActivate();
+
+ final Storage storage = new LimitedStorageImpl(10);
+ storage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(8, storage);
// Act
- activateStorage(limitedStorage);
+ sut.onStorageChanged(8);
// Assert
- assertThat(sut.getStored()).isEqualTo(50L);
- assertThat(sut.getCapacity()).isEqualTo(100L);
+ assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + USAGE_PER_STORAGE);
assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(A, 50L)
+ new ResourceAmount(A, 5)
);
}
@Test
- void shouldInsert(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ void shouldDetectChangedStorage(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ final Storage originalStorage = new LimitedStorageImpl(10);
+ originalStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, originalStorage);
+ initializeAndActivate();
+
+ final Storage replacedStorage = new LimitedStorageImpl(10);
+ replacedStorage.insert(B, 2, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, replacedStorage);
+
+ // Act
+ final Collection preChanging = new HashSet<>(networkStorage.getAll());
+ sut.onStorageChanged(0);
+ final Collection postChanging = networkStorage.getAll();
+
+ // Assert
+ assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE + USAGE_PER_STORAGE);
+ assertThat(preChanging).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(A, 5)
+ );
+ assertThat(postChanging).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(B, 2)
+ );
+ assertThat(networkStorage.getStored()).isEqualTo(2L);
+ }
+
+ @Test
+ void shouldDetectRemovedStorage(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ final Storage storage = new LimitedStorageImpl(10);
+ storage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(7, storage);
+ initializeAndActivate();
+
+ provider.remove(7);
+
+ // Act
+ final Collection preRemoval = new HashSet<>(networkStorage.getAll());
+ sut.onStorageChanged(7);
+ final Collection postRemoval = networkStorage.getAll();
+
+ // Assert
+ assertThat(sut.getEnergyUsage()).isEqualTo(BASE_USAGE);
+ assertThat(preRemoval).isNotEmpty();
+ assertThat(postRemoval).isEmpty();
+ assertThat(networkStorage.getStored()).isZero();
+ }
+
+ @Test
+ void shouldNotDetectStorageChangeInInvalidIndex() {
+ // Act
+ sut.onStorageChanged(-1);
+ sut.onStorageChanged(9);
+
+ // Assert
+ assertThat(sut.getSize()).isEqualTo(9);
+ for (int i = 0; i < 9; ++i) {
+ assertThat(sut.getState(i)).isEqualTo(StorageState.NONE);
+ }
+ }
+
+ @Test
+ void shouldNotUpdateNetworkStorageWhenChangingStorageWhenInactive(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
// Arrange
final Storage storage = new LimitedStorageImpl(100);
- activateStorage(storage);
+ storage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, storage);
+ initializeAndActivate();
// Act
- final long inserted = networkStorage.insert(A, 100, Action.EXECUTE, EmptyActor.INSTANCE);
+ final Collection preInactiveness = new HashSet<>(networkStorage.getAll());
+ sut.setActive(false);
+ sut.onStorageChanged(1);
+ final Collection postInactiveness = networkStorage.getAll();
// Assert
- assertThat(inserted).isEqualTo(100);
- assertThat(storage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(A, 100)
+ assertThat(preInactiveness).isNotEmpty();
+ assertThat(postInactiveness).isEmpty();
+ assertThat(networkStorage.getStored()).isZero();
+ }
+
+ @Test
+ void shouldHaveResourcesFromStoragePresentInNetwork(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ final Storage storage = new LimitedStorageImpl(100);
+ storage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, storage);
+
+ initializeAndActivate();
+
+ // Act
+ final Collection resources = networkStorage.getAll();
+ final long stored = networkStorage.getStored();
+
+ // Assert
+ assertThat(resources).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 50),
+ new ResourceAmount(B, 50)
);
- assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ assertThat(stored).isEqualTo(100);
+ }
+
+ @Test
+ void shouldInsert(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ final Storage storage1 = new LimitedStorageImpl(100);
+ provider.set(1, storage1);
+
+ final Storage storage2 = new LimitedStorageImpl(100);
+ provider.set(2, storage2);
+
+ final Storage storage3 = new LimitedStorageImpl(100);
+ provider.set(3, storage3);
+
+ initializeAndActivate();
+
+ // Act
+ final long inserted1 = networkStorage.insert(A, 150, Action.EXECUTE, EmptyActor.INSTANCE);
+ final long inserted2 = networkStorage.insert(A, 10, Action.EXECUTE, EmptyActor.INSTANCE);
+ final long inserted3 = networkStorage.insert(B, 300, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ // Assert
+ assertThat(inserted1).isEqualTo(150);
+ assertThat(inserted2).isEqualTo(10);
+ assertThat(inserted3).isEqualTo(140);
+
+ assertThat(storage1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
new ResourceAmount(A, 100)
);
+ assertThat(storage2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 60),
+ new ResourceAmount(B, 40)
+ );
+ assertThat(storage3.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(B, 100)
+ );
+
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(B, 140),
+ new ResourceAmount(A, 160)
+ );
+ assertThat(networkStorage.getStored()).isEqualTo(inserted1 + inserted2 + inserted3);
}
@Test
void shouldExtract(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
// Arrange
- final Storage storage = new LimitedStorageImpl(200);
- storage.insert(A, 100, Action.EXECUTE, EmptyActor.INSTANCE);
- storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- activateStorage(storage);
+ final Storage storage1 = new LimitedStorageImpl(100);
+ storage1.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ storage1.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, storage1);
+
+ final Storage storage2 = new LimitedStorageImpl(100);
+ storage2.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ storage2.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(2, storage2);
+
+ final Storage storage3 = new LimitedStorageImpl(100);
+ storage3.insert(C, 10, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(3, storage3);
+
+ initializeAndActivate();
// Act
- final long extracted = networkStorage.extract(A, 30, Action.EXECUTE, EmptyActor.INSTANCE);
+ final long extracted = networkStorage.extract(A, 85, Action.EXECUTE, EmptyActor.INSTANCE);
// Assert
- assertThat(extracted).isEqualTo(30);
- assertThat(storage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
- new ResourceAmount(A, 70),
+ assertThat(extracted).isEqualTo(85);
+
+ assertThat(storage1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
new ResourceAmount(B, 50)
);
+ assertThat(storage2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(B, 50),
+ new ResourceAmount(A, 15)
+ );
+ assertThat(storage3.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(C, 10)
+ );
+
assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
- new ResourceAmount(A, 70),
- new ResourceAmount(B, 50)
+ new ResourceAmount(B, 100),
+ new ResourceAmount(A, 15),
+ new ResourceAmount(C, 10)
);
+ assertThat(networkStorage.getStored()).isEqualTo(125);
}
@Test
void shouldRespectAllowlistWhenInserting(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
// Arrange
sut.setFilterMode(FilterMode.ALLOW);
sut.setFilters(Set.of(A, B));
final Storage storage = new LimitedStorageImpl(100);
- activateStorage(storage);
+ provider.set(1, storage);
+ initializeAndActivate();
// Act
final long inserted1 = networkStorage.insert(A, 12, Action.EXECUTE, EmptyActor.INSTANCE);
@@ -140,15 +414,53 @@ void shouldRespectAllowlistWhenInserting(
assertThat(inserted3).isZero();
}
+ @Test
+ void shouldRespectAllowlistWithNormalizerWhenInserting(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ sut.setFilterMode(FilterMode.ALLOW);
+ sut.setFilters(Set.of(A));
+ sut.setNormalizer(resource -> {
+ if (resource == A_ALTERNATIVE || resource == A_ALTERNATIVE2) {
+ return A;
+ }
+ if (resource == B_ALTERNATIVE) {
+ return B;
+ }
+ return resource;
+ });
+
+ final Storage storage = new LimitedStorageImpl(100);
+ provider.set(1, storage);
+ initializeAndActivate();
+
+ // Act
+ final long inserted1 = networkStorage.insert(A, 1, Action.EXECUTE, EmptyActor.INSTANCE);
+ final long inserted2 = networkStorage.insert(A_ALTERNATIVE, 1, Action.EXECUTE, EmptyActor.INSTANCE);
+ final long inserted3 = networkStorage.insert(A_ALTERNATIVE2, 1, Action.EXECUTE, EmptyActor.INSTANCE);
+ final long inserted4 = networkStorage.insert(B, 1, Action.EXECUTE, EmptyActor.INSTANCE);
+ final long inserted5 = networkStorage.insert(B_ALTERNATIVE, 1, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ // Assert
+ assertThat(inserted1).isEqualTo(1);
+ assertThat(inserted2).isEqualTo(1);
+ assertThat(inserted3).isEqualTo(1);
+ assertThat(inserted4).isZero();
+ assertThat(inserted5).isZero();
+ }
+
@Test
void shouldRespectEmptyAllowlistWhenInserting(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
// Arrange
sut.setFilterMode(FilterMode.ALLOW);
sut.setFilters(Set.of());
final Storage storage = new LimitedStorageImpl(100);
- activateStorage(storage);
+ provider.set(1, storage);
+ initializeAndActivate();
// Act
final long inserted1 = networkStorage.insert(A, 12, Action.EXECUTE, EmptyActor.INSTANCE);
@@ -163,13 +475,15 @@ void shouldRespectEmptyAllowlistWhenInserting(
@Test
void shouldRespectBlocklistWhenInserting(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
// Arrange
sut.setFilterMode(FilterMode.BLOCK);
sut.setFilters(Set.of(A, B));
final Storage storage = new LimitedStorageImpl(100);
- activateStorage(storage);
+ provider.set(1, storage);
+ initializeAndActivate();
// Act
final long inserted1 = networkStorage.insert(A, 12, Action.EXECUTE, EmptyActor.INSTANCE);
@@ -184,13 +498,15 @@ void shouldRespectBlocklistWhenInserting(
@Test
void shouldRespectEmptyBlocklistWhenInserting(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
// Arrange
sut.setFilterMode(FilterMode.BLOCK);
sut.setFilters(Set.of());
final Storage storage = new LimitedStorageImpl(100);
- activateStorage(storage);
+ provider.set(1, storage);
+ initializeAndActivate();
// Act
final long inserted1 = networkStorage.insert(A, 12, Action.EXECUTE, EmptyActor.INSTANCE);
@@ -205,15 +521,16 @@ void shouldRespectEmptyBlocklistWhenInserting(
@ParameterizedTest
@EnumSource(AccessMode.class)
- void shouldRespectAccessModeWhenInserting(final AccessMode accessMode,
- @InjectNetworkStorageComponent
- final StorageNetworkComponent networkStorage
+ void shouldRespectAccessModeWhenInserting(
+ final AccessMode accessMode,
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
) {
// Arrange
sut.setAccessMode(accessMode);
final Storage storage = new LimitedStorageImpl(100);
- activateStorage(storage);
+ provider.set(1, storage);
+ initializeAndActivate();
// Act
final long inserted = networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
@@ -227,16 +544,18 @@ void shouldRespectAccessModeWhenInserting(final AccessMode accessMode,
@ParameterizedTest
@EnumSource(AccessMode.class)
- void shouldRespectAccessModeWhenExtracting(final AccessMode accessMode,
- @InjectNetworkStorageComponent
- final StorageNetworkComponent networkStorage
+ void shouldRespectAccessModeWhenExtracting(
+ final AccessMode accessMode,
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
) {
// Arrange
sut.setAccessMode(accessMode);
final Storage storage = new LimitedStorageImpl(100);
+ provider.set(1, storage);
+ initializeAndActivate();
+
storage.insert(A, 20, Action.EXECUTE, EmptyActor.INSTANCE);
- activateStorage(storage);
// Act
final long extracted = networkStorage.extract(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
@@ -249,10 +568,14 @@ void shouldRespectAccessModeWhenExtracting(final AccessMode accessMode,
}
@Test
- void shouldNotInsertWhenInactive(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ void shouldNotAllowInsertsWhenInactive(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
// Arrange
final Storage storage = new LimitedStorageImpl(100);
- activateStorage(storage);
+ provider.set(1, storage);
+ initializeAndActivate();
+
sut.setActive(false);
// Act
@@ -263,10 +586,14 @@ void shouldNotInsertWhenInactive(@InjectNetworkStorageComponent final StorageNet
}
@Test
- void shouldNotExtractWhenInactive(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ void shouldNotAllowExtractsWhenInactive(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
// Arrange
final Storage storage = new LimitedStorageImpl(100);
- activateStorage(storage);
+ storage.insert(A, 20, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, storage);
+ initializeAndActivate();
sut.setActive(false);
@@ -278,189 +605,95 @@ void shouldNotExtractWhenInactive(@InjectNetworkStorageComponent final StorageNe
}
@Test
- void shouldHideStorageContentsWhenInactive(
+ void shouldHideFromNetworkWhenInactive(
@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
) {
// Arrange
final Storage storage = new LimitedStorageImpl(100);
storage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- activateStorage(storage);
+ provider.set(1, storage);
+ initializeAndActivate();
// Act
+ final Collection preInactiveness = new HashSet<>(networkStorage.getAll());
sut.setActive(false);
+ final Collection postInactiveness = networkStorage.getAll();
// Assert
- assertThat(networkStorage.getAll()).isEmpty();
+ assertThat(preInactiveness).isNotEmpty();
+ assertThat(postInactiveness).isEmpty();
}
@Test
- void shouldShowStorageContentsWhenActive(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ void shouldNoLongerShowOnNetworkWhenRemoved(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage,
+ @InjectNetwork final Network network
+ ) {
// Arrange
- final Storage storage = new LimitedStorageImpl(100);
- storage.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
- storage.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ final Storage storage1 = new LimitedStorageImpl(100);
+ storage1.insert(A, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, storage1);
+ initializeAndActivate();
- // Act
- activateStorage(storage);
+ // Act & assert
+ final Storage storage2 = new LimitedStorageImpl(100);
+ storage2.insert(B, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(2, storage2);
+ sut.onStorageChanged(2);
- // Assert
assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
new ResourceAmount(A, 50),
new ResourceAmount(B, 50)
);
- }
-
- @Test
- void shouldNotInsertWhenFull(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
- // Arrange
- final Storage storage = new LimitedStorageImpl(100);
- storage.insert(A, 95, Action.EXECUTE, EmptyActor.INSTANCE);
- activateStorage(storage);
-
- // Act
- final long inserted1 = networkStorage.insert(A, 7, Action.EXECUTE, EmptyActor.INSTANCE);
- final Collection stored1 = networkStorage.getAll();
- final long inserted2 = networkStorage.insert(A, 7, Action.EXECUTE, EmptyActor.INSTANCE);
- final Collection stored2 = networkStorage.getAll();
-
- // Assert
- assertThat(inserted1).isEqualTo(5);
- assertThat(stored1).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(A, 100)
- );
-
- assertThat(inserted2).isZero();
- assertThat(stored2).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(A, 100)
- );
- }
-
- @Test
- void shouldNotInsertWhenFullWhenStorageVoidsExcessButIsNotInAllowlistMode(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final LimitedStorageImpl storage = new LimitedStorageImpl(100);
- storage.insert(A, 95, Action.EXECUTE, EmptyActor.INSTANCE);
- activateStorage(storage);
- sut.setVoidExcess(true);
+ network.removeContainer(() -> sut);
+ assertThat(networkStorage.getAll()).isEmpty();
- // Act
- final long inserted = networkStorage.insert(A, 7, Action.EXECUTE, EmptyActor.INSTANCE);
+ final Storage storage3 = new LimitedStorageImpl(100);
+ storage3.insert(C, 50, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(3, storage3);
+ sut.onStorageChanged(3);
- // Assert
- assertThat(inserted).isEqualTo(5);
- assertThat(storage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(A, 100)
- );
+ assertThat(networkStorage.getAll()).isEmpty();
}
@Test
- void shouldNotInsertWhenStorageVoidsExcessAndInAllowlistModeWithoutConfiguredFilter(
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
+ void shouldTrackChanges(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
// Arrange
- final LimitedStorageImpl storage = new LimitedStorageImpl(100);
- activateStorage(storage);
-
- sut.setVoidExcess(true);
- sut.setFilterMode(FilterMode.ALLOW);
+ final Storage storage = new TrackedStorageImpl(new LimitedStorageImpl(100), () -> 0L);
+ provider.set(1, storage);
+ initializeAndActivate();
// Act
- final long inserted = networkStorage.insert(A, 7, Action.EXECUTE, EmptyActor.INSTANCE);
+ final long inserted = networkStorage.insert(A, 10, Action.EXECUTE, FakeActor.INSTANCE);
// Assert
- assertThat(inserted).isZero();
- assertThat(storage.getAll()).isEmpty();
+ assertThat(inserted).isEqualTo(10);
+ assertThat(networkStorage.findTrackedResourceByActorType(A, FakeActor.class)).isNotEmpty();
}
@Test
- void shouldInsertWhenFullWhenStorageVoidsExcessAndIsInAllowlistMode(
+ void shouldNotifyListenerWhenStateChanges(
@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
) {
// Arrange
- final LimitedStorageImpl storage = new LimitedStorageImpl(100);
- storage.insert(A, 95, Action.EXECUTE, EmptyActor.INSTANCE);
- activateStorage(storage);
-
- sut.setVoidExcess(true);
- sut.setFilterMode(FilterMode.ALLOW);
- sut.setFilters(Set.of(A));
-
- // Act
- final long inserted1 = networkStorage.insert(A, 3, Action.EXECUTE, EmptyActor.INSTANCE);
- final long inserted2 = networkStorage.insert(A, 7, Action.EXECUTE, EmptyActor.INSTANCE);
- final long insertedOther = networkStorage.insert(B, 1, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- assertThat(inserted1).isEqualTo(3);
- assertThat(inserted2).isEqualTo(7);
- assertThat(insertedOther).isZero();
- assertThat(storage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
- new ResourceAmount(A, 100)
- );
- }
+ final StateTrackedStorage.Listener listener = mock(StateTrackedStorage.Listener.class);
+ sut.setListener(listener);
- @Test
- void shouldTrackChanges(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
- // Arrange
- activateStorage(new TrackedStorageImpl(new LimitedStorageImpl(100), () -> 0L));
+ final Storage storage = new LimitedStorageImpl(100);
+ provider.set(1, storage);
+ initializeAndActivate();
// Act
- final long inserted = networkStorage.insert(A, 10, Action.EXECUTE, FakeActor.INSTANCE);
+ networkStorage.insert(A, 75, Action.EXECUTE, FakeActor.INSTANCE);
// Assert
- assertThat(inserted).isEqualTo(10);
- assertThat(networkStorage.findTrackedResourceByActorType(A, FakeActor.class)).isNotEmpty();
+ verify(listener, times(1)).onStorageStateChanged();
}
- private void activateStorage(final Storage storage) {
- sut.setStorage(storage);
+ private void initializeAndActivate() {
+ sut.setProvider(provider);
sut.setActive(true);
}
-
- @Nested
- class PriorityTest {
- @AddNetworkNode
- StorageNetworkNode otherStorage;
-
- @ParameterizedTest
- @ValueSource(booleans = {true, false})
- void shouldRespectPriority(
- final boolean oneHasPriority,
- @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
- ) {
- // Arrange
- final LimitedStorageImpl storage1 = new LimitedStorageImpl(100);
- sut.setStorage(storage1);
- sut.setActive(true);
-
- final LimitedStorageImpl storage2 = new LimitedStorageImpl(100);
- otherStorage.setStorage(storage2);
- otherStorage.setActive(true);
-
- if (oneHasPriority) {
- sut.setPriority(5);
- otherStorage.setPriority(2);
- } else {
- sut.setPriority(2);
- otherStorage.setPriority(5);
- }
-
- // Act
- networkStorage.insert(A, 1, Action.EXECUTE, EmptyActor.INSTANCE);
-
- // Assert
- if (oneHasPriority) {
- assertThat(storage1.getAll()).isNotEmpty();
- assertThat(storage2.getAll()).isEmpty();
- } else {
- assertThat(storage1.getAll()).isEmpty();
- assertThat(storage2.getAll()).isNotEmpty();
- }
- }
- }
}
diff --git a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferNetworkNodeTest.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferNetworkNodeTest.java
new file mode 100644
index 000000000..0249b8f3e
--- /dev/null
+++ b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/storagetransfer/StorageTransferNetworkNodeTest.java
@@ -0,0 +1,718 @@
+package com.refinedmods.refinedstorage2.api.network.impl.node.storagetransfer;
+
+import com.refinedmods.refinedstorage2.api.core.Action;
+import com.refinedmods.refinedstorage2.api.network.impl.node.ProviderImpl;
+import com.refinedmods.refinedstorage2.api.network.storage.StorageNetworkComponent;
+import com.refinedmods.refinedstorage2.api.resource.ResourceAmount;
+import com.refinedmods.refinedstorage2.api.resource.ResourceKey;
+import com.refinedmods.refinedstorage2.api.resource.filter.FilterMode;
+import com.refinedmods.refinedstorage2.api.resource.list.ResourceListImpl;
+import com.refinedmods.refinedstorage2.api.storage.Actor;
+import com.refinedmods.refinedstorage2.api.storage.EmptyActor;
+import com.refinedmods.refinedstorage2.api.storage.InMemoryStorageImpl;
+import com.refinedmods.refinedstorage2.api.storage.Storage;
+import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorageImpl;
+import com.refinedmods.refinedstorage2.network.test.AddNetworkNode;
+import com.refinedmods.refinedstorage2.network.test.InjectNetworkStorageComponent;
+import com.refinedmods.refinedstorage2.network.test.NetworkTest;
+import com.refinedmods.refinedstorage2.network.test.SetupNetwork;
+
+import java.util.LinkedHashMap;
+import java.util.Set;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+
+import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.A;
+import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.A_ALTERNATIVE;
+import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.B;
+import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.C;
+import static com.refinedmods.refinedstorage2.network.test.fake.FakeResources.D;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@NetworkTest
+@SetupNetwork
+class StorageTransferNetworkNodeTest {
+ @AddNetworkNode
+ StorageTransferNetworkNode sut;
+ StorageTransferListener listener;
+ ProviderImpl provider;
+
+ @BeforeEach
+ void setUp() {
+ provider = new ProviderImpl();
+ listener = mock(StorageTransferListener.class);
+ sut.setListener(listener);
+ }
+
+ @Test
+ void shouldNotTransferWithoutNetwork(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+
+ final Storage source = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+
+ // Act
+ sut.setNetwork(null);
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).isEmpty();
+ assertThat(source.getAll()).isNotEmpty();
+ }
+
+ @Test
+ void shouldNotTransferWhenInactive(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+
+ final Storage source = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+
+ // Act
+ sut.setActive(false);
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).isEmpty();
+ assertThat(source.getAll()).isNotEmpty();
+ }
+
+ @ParameterizedTest
+ @EnumSource(StorageTransferMode.class)
+ void shouldNotTransferWithoutTransferQuotaProvider(
+ final StorageTransferMode mode,
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+ networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage source = new InMemoryStorageImpl();
+ source.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setMode(mode);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(A, 5)
+ );
+ assertThat(source.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(B, 5)
+ );
+ }
+
+ @Test
+ void shouldInsert(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+
+ final Storage source0 = new LimitedStorageImpl(1) {
+ @Override
+ public long extract(final ResourceKey resource,
+ final long amount,
+ final Action action,
+ final Actor actor) {
+ return 0;
+ }
+ };
+ source0.insert(A, 1, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source0);
+
+ final Storage source1 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source1.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(C, 35, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, source1);
+
+ final Storage source2 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source2.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(2, source2);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 10)
+ );
+ assertThat(source0.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(A, 1)
+ );
+ assertThat(source1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(C, 25),
+ new ResourceAmount(D, 5)
+ );
+ assertThat(source2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(D, 5)
+ );
+ verify(listener, never()).onTransferSuccess(anyInt());
+ }
+
+ @Test
+ void shouldInsertAllowlist(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+
+ final Storage source1 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source1.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(C, 35, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set((sut.getSize() / 2) - 2, source1);
+
+ final Storage source2 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source2.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set((sut.getSize() / 2) - 1, source2);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+ sut.setFilterMode(FilterMode.ALLOW);
+ sut.setFilters(Set.of(A, B));
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(B, 5)
+ );
+ assertThat(source1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(C, 35),
+ new ResourceAmount(D, 5)
+ );
+ assertThat(source2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(D, 5)
+ );
+ verify(listener, times(1)).onTransferSuccess((sut.getSize() / 2) - 2);
+ }
+
+ @Test
+ void shouldInsertBlocklist(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+
+ final Storage source1 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source1.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(C, 35, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source1);
+
+ final Storage source2 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source2.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, source2);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+ sut.setFilterMode(FilterMode.BLOCK);
+ sut.setFilters(Set.of(A, B));
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(C, 20)
+ );
+ assertThat(source1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 15),
+ new ResourceAmount(D, 5)
+ );
+ assertThat(source2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(D, 5)
+ );
+ verify(listener, never()).onTransferSuccess(anyInt());
+ }
+
+ @Test
+ void shouldNotifyListenerWhenReadyInsertingBecauseStorageWasAlreadyEmpty() {
+ // Arrange
+ final Storage source = new InMemoryStorageImpl();
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 15L);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldNotifyListenerWhenReadyInsertingAllResources(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+
+ final Storage source = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source.insert(C, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 15L);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(source.getAll()).isEmpty();
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldNotifyListenerWhenReadyInsertingAllResourcesAndUsingFilterButInsertedNothing() {
+ // Arrange
+ final Storage source1 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source1.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(C, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source1);
+
+ final Storage source2 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source2.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, source2);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 15L);
+ sut.setFilterMode(FilterMode.ALLOW);
+ sut.setFilters(Set.of(A));
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(source1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 5)
+ );
+ assertThat(source2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(D, 5)
+ );
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldNotifyListenerWhenReadyInsertingAllResourcesAndUsingFilterButStillInsertedSomething(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+
+ final Storage source1 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source1.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(C, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source1);
+
+ final Storage source2 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source2.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, source2);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 15L);
+ sut.setFilterMode(FilterMode.ALLOW);
+ sut.setFilters(Set.of(A));
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(source1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 5)
+ );
+ assertThat(source2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(D, 5)
+ );
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldNotNotifyListenerWhenReadyInsertingAllResourcesAndNetworkIsFull(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new LimitedStorageImpl(15));
+
+ final Storage source1 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source1.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(C, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source1.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source1);
+
+ final Storage source2 = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source2.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(1, source2);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 100L);
+
+ // Act
+ sut.doWork();
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 5)
+ );
+ assertThat(source1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(D, 5)
+ );
+ assertThat(source2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(A, 5)
+ );
+ verify(listener, never()).onTransferSuccess(anyInt());
+ }
+
+ @Test
+ void shouldExtract(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+ networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(C, 35, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage source1 = new LimitedStorageImpl(0);
+ provider.set(0, source1);
+
+ final Storage source2 = new InMemoryStorageImpl();
+ provider.set(1, source2);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+ sut.setMode(StorageTransferMode.EXTRACT);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(C, 25),
+ new ResourceAmount(D, 5)
+ );
+ assertThat(source2.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 10)
+ );
+ assertThat(source1.getAll()).isEmpty();
+ verify(listener, never()).onTransferSuccess(anyInt());
+ }
+
+ @Test
+ void shouldExtractAllowlist(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+ networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(C, 35, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage source1 = new InMemoryStorageImpl();
+ provider.set(0, source1);
+
+ final Storage source2 = new InMemoryStorageImpl();
+ provider.set(1, source2);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+ sut.setMode(StorageTransferMode.EXTRACT);
+ sut.setFilterMode(FilterMode.ALLOW);
+ sut.setFilters(Set.of(A, B));
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(C, 35),
+ new ResourceAmount(D, 5)
+ );
+ assertThat(source1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(B, 5)
+ );
+ assertThat(source2.getAll()).isEmpty();
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldExtractBlocklist(@InjectNetworkStorageComponent final StorageNetworkComponent networkStorage) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+ networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(C, 35, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage source1 = new InMemoryStorageImpl();
+ provider.set(0, source1);
+
+ final Storage source2 = new InMemoryStorageImpl();
+ provider.set(1, source2);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+ sut.setMode(StorageTransferMode.EXTRACT);
+ sut.setFilterMode(FilterMode.BLOCK);
+ sut.setFilters(Set.of(A, B));
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 15),
+ new ResourceAmount(D, 5)
+ );
+ assertThat(source1.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(C, 20)
+ );
+ assertThat(source2.getAll()).isEmpty();
+ verify(listener, never()).onTransferSuccess(anyInt());
+ }
+
+ @Test
+ void shouldNotifyListenerWhenReadyExtractingBecauseStorageWasAlreadyEmpty() {
+ // Arrange
+ final Storage source = new InMemoryStorageImpl();
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 15L);
+ sut.setMode(StorageTransferMode.EXTRACT);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldNotifyListenerWhenReadyExtractingAllResources(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+ networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(C, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage source = new InMemoryStorageImpl();
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 15L);
+ sut.setMode(StorageTransferMode.EXTRACT);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).isEmpty();
+ assertThat(source.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 5)
+ );
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldNotifyListenerWhenReadyExtractingAllResourcesAndUsingFilterButInsertedNothing(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+ networkStorage.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(C, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage source = new InMemoryStorageImpl();
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 15L);
+ sut.setFilterMode(FilterMode.ALLOW);
+ sut.setFilters(Set.of(A));
+ sut.setMode(StorageTransferMode.EXTRACT);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(source.getAll()).isEmpty();
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 5),
+ new ResourceAmount(D, 5)
+ );
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldNotifyListenerWhenReadyExtractingAllResourcesAndUsingFilterButStillExtractedSomething(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>())));
+ networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(C, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage source = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 15L);
+ sut.setFilterMode(FilterMode.ALLOW);
+ sut.setFilters(Set.of(A));
+ sut.setMode(StorageTransferMode.EXTRACT);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(source.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(A, 5)
+ );
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(B, 5),
+ new ResourceAmount(C, 5)
+ );
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldNotifyListenerWhenExtractingAllResourcesAndReachingCapacity(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+ networkStorage.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ networkStorage.insert(C, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+
+ final Storage source = new LimitedStorageImpl(10);
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 100L);
+ sut.setMode(StorageTransferMode.EXTRACT);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(source.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(B, 5)
+ );
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(C, 5)
+ );
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldRespectNormalizer(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+
+ final Storage source = new InMemoryStorageImpl(new ResourceListImpl(new LinkedHashMap<>()));
+ source.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source.insert(A_ALTERNATIVE, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source.insert(B, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ source.insert(D, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(0, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+ sut.setFilterMode(FilterMode.ALLOW);
+ sut.setFilters(Set.of(A));
+ sut.setNormalizer(resource -> resource == A || resource == A_ALTERNATIVE ? A : resource);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(A, 5),
+ new ResourceAmount(A_ALTERNATIVE, 5)
+ );
+ assertThat(source.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(
+ new ResourceAmount(B, 5),
+ new ResourceAmount(D, 5)
+ );
+ verify(listener, times(1)).onTransferSuccess(0);
+ }
+
+ @Test
+ void shouldNotTransferAtIndexHigherThanHalf(
+ @InjectNetworkStorageComponent final StorageNetworkComponent networkStorage
+ ) {
+ // Arrange
+ networkStorage.addSource(new InMemoryStorageImpl());
+
+ final Storage source = new InMemoryStorageImpl();
+ source.insert(A, 5, Action.EXECUTE, EmptyActor.INSTANCE);
+ provider.set(sut.getSize() / 2, source);
+
+ sut.setProvider(provider);
+ sut.setTransferQuotaProvider(storage -> 20L);
+
+ // Act
+ sut.doWork();
+
+ // Assert
+ assertThat(networkStorage.getAll()).isEmpty();
+ assertThat(source.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly(
+ new ResourceAmount(A, 5)
+ );
+ verify(listener, never()).onTransferSuccess(1);
+ }
+}
diff --git a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/storage/StorageNetworkComponentImplTest.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/storage/StorageNetworkComponentImplTest.java
index eb99af6f1..f1f4757ab 100644
--- a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/storage/StorageNetworkComponentImplTest.java
+++ b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/storage/StorageNetworkComponentImplTest.java
@@ -17,6 +17,7 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -38,15 +39,17 @@ class StorageNetworkComponentImplTest {
void setUp() {
sut = new StorageNetworkComponentImpl(new ResourceListImpl());
- storage1 = new StorageNetworkNode(0);
+ storage1 = new StorageNetworkNode(0, 0, 1);
storage1.setNetwork(new NetworkImpl(NetworkTestFixtures.NETWORK_COMPONENT_MAP_FACTORY));
- storage1.setStorage(new LimitedStorageImpl(100));
+ final var storage1S = new LimitedStorageImpl(100);
+ storage1.setProvider(index -> Optional.of(storage1S));
storage1.setActive(true);
storage1Container = () -> storage1;
- storage2 = new StorageNetworkNode(0);
+ storage2 = new StorageNetworkNode(0, 0, 1);
storage2.setNetwork(new NetworkImpl(NetworkTestFixtures.NETWORK_COMPONENT_MAP_FACTORY));
- storage2.setStorage(new LimitedStorageImpl(100));
+ final var storage2S = new LimitedStorageImpl(100);
+ storage2.setProvider(index -> Optional.of(storage2S));
storage2.setActive(true);
storage2Container = () -> storage2;
}
diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/AbstractStorageContainerBlockItem.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/AbstractStorageContainerBlockItem.java
index c874ae24f..f4c499eae 100644
--- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/AbstractStorageContainerBlockItem.java
+++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/AbstractStorageContainerBlockItem.java
@@ -62,7 +62,7 @@ protected boolean updateCustomBlockEntityTag(final BlockPos pos,
private void updateBlockEntityTag(final BlockPos pos,
final Level level,
final ItemStack stack) {
- if (level.getBlockEntity(pos) instanceof ItemTransferableStorageBlockEntity blockEntity) {
+ if (level.getBlockEntity(pos) instanceof StorageBlockEntity blockEntity) {
helper.transferToBlockEntity(stack, blockEntity);
} else {
LOGGER.warn("Storage could not be set, block entity does not exist yet at {}", pos);
diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/ItemTransferableStorageBlockEntity.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageBlockEntity.java
similarity index 79%
rename from refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/ItemTransferableStorageBlockEntity.java
rename to refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageBlockEntity.java
index ffa22ac93..be88e8a16 100644
--- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/ItemTransferableStorageBlockEntity.java
+++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageBlockEntity.java
@@ -10,9 +10,9 @@
* The "storage block" is an example of such an item.
*/
@API(status = API.Status.STABLE, since = "2.0.0-milestone.3.3")
-public interface ItemTransferableStorageBlockEntity {
+public interface StorageBlockEntity {
@Nullable
UUID getStorageId();
- void modifyStorageIdAfterAlreadyInitialized(UUID id);
+ void setStorageId(UUID storageId);
}
diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageContainerItemHelper.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageContainerItemHelper.java
index b2577334b..c2428eac2 100644
--- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageContainerItemHelper.java
+++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageContainerItemHelper.java
@@ -40,9 +40,9 @@ void appendToTooltip(ItemStack stack,
LongFunction amountFormatter,
boolean hasCapacity);
- void transferToBlockEntity(ItemStack stack, ItemTransferableStorageBlockEntity blockEntity);
+ void transferToBlockEntity(ItemStack stack, StorageBlockEntity blockEntity);
- void transferFromBlockEntity(ItemStack stack, ItemTransferableStorageBlockEntity blockEntity);
+ void transferFromBlockEntity(ItemStack stack, StorageBlockEntity blockEntity);
void registerDiskModel(Item item, ResourceLocation model);
diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java
index 5db389b00..d5a8871bc 100644
--- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java
+++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java
@@ -1,6 +1,6 @@
package com.refinedmods.refinedstorage2.platform.common.storage;
-import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageProvider;
+import com.refinedmods.refinedstorage2.api.network.impl.node.AbstractStorageContainerNetworkNode;
import com.refinedmods.refinedstorage2.api.storage.Storage;
import com.refinedmods.refinedstorage2.api.storage.StorageState;
import com.refinedmods.refinedstorage2.platform.api.storage.StorageContainerItem;
@@ -16,7 +16,7 @@
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.item.ItemStack;
-public class DiskInventory extends SimpleContainer implements MultiStorageProvider {
+public class DiskInventory extends SimpleContainer implements AbstractStorageContainerNetworkNode.Provider {
private static final String TAG_DISK_STATE = "s";
private static final String TAG_DISK_ITEM_ID = "i";
diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/StorageContainerItemHelperImpl.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/StorageContainerItemHelperImpl.java
index 84c88cc6b..ee061f0e6 100644
--- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/StorageContainerItemHelperImpl.java
+++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/StorageContainerItemHelperImpl.java
@@ -2,7 +2,7 @@
import com.refinedmods.refinedstorage2.api.storage.Storage;
import com.refinedmods.refinedstorage2.platform.api.PlatformApi;
-import com.refinedmods.refinedstorage2.platform.api.storage.ItemTransferableStorageBlockEntity;
+import com.refinedmods.refinedstorage2.platform.api.storage.StorageBlockEntity;
import com.refinedmods.refinedstorage2.platform.api.storage.StorageContainerItemHelper;
import com.refinedmods.refinedstorage2.platform.api.storage.StorageInfo;
import com.refinedmods.refinedstorage2.platform.api.storage.StorageRepository;
@@ -127,15 +127,15 @@ public void appendToTooltip(final ItemStack stack,
}
@Override
- public void transferToBlockEntity(final ItemStack stack, final ItemTransferableStorageBlockEntity blockEntity) {
+ public void transferToBlockEntity(final ItemStack stack, final StorageBlockEntity blockEntity) {
getId(stack).ifPresent(id -> {
- blockEntity.modifyStorageIdAfterAlreadyInitialized(id);
+ blockEntity.setStorageId(id);
LOGGER.debug("Transferred storage {} to block entity {}", id, blockEntity);
});
}
@Override
- public void transferFromBlockEntity(final ItemStack stack, final ItemTransferableStorageBlockEntity blockEntity) {
+ public void transferFromBlockEntity(final ItemStack stack, final StorageBlockEntity blockEntity) {
final UUID storageId = blockEntity.getStorageId();
if (storageId != null) {
LOGGER.debug("Transferred storage {} from block entity {} to stack", storageId, blockEntity);
diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/AbstractDiskDriveBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/AbstractDiskDriveBlockEntity.java
index ca814bdb5..b8189de59 100644
--- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/AbstractDiskDriveBlockEntity.java
+++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/AbstractDiskDriveBlockEntity.java
@@ -1,6 +1,6 @@
package com.refinedmods.refinedstorage2.platform.common.storage.diskdrive;
-import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageNetworkNode;
+import com.refinedmods.refinedstorage2.api.network.impl.node.storage.StorageNetworkNode;
import com.refinedmods.refinedstorage2.platform.api.PlatformApi;
import com.refinedmods.refinedstorage2.platform.common.Platform;
import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities;
@@ -39,7 +39,7 @@
import net.minecraft.world.level.block.state.BlockState;
public abstract class AbstractDiskDriveBlockEntity
- extends AbstractRedstoneModeNetworkNodeContainerBlockEntity
+ extends AbstractRedstoneModeNetworkNodeContainerBlockEntity
implements BlockEntityWithDrops, NetworkNodeMenuProvider {
public static final int AMOUNT_OF_DISKS = 8;
@@ -55,7 +55,7 @@ public abstract class AbstractDiskDriveBlockEntity
private final DiskStateChangeListener diskStateListener = new DiskStateChangeListener(this);
protected AbstractDiskDriveBlockEntity(final BlockPos pos, final BlockState state) {
- super(BlockEntities.INSTANCE.getDiskDrive(), pos, state, new MultiStorageNetworkNode(
+ super(BlockEntities.INSTANCE.getDiskDrive(), pos, state, new StorageNetworkNode(
Platform.INSTANCE.getConfig().getDiskDrive().getEnergyUsage(),
Platform.INSTANCE.getConfig().getDiskDrive().getEnergyUsagePerDisk(),
AMOUNT_OF_DISKS
diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/DiskDriveBlockEntityTicker.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/DiskDriveBlockEntityTicker.java
index 9b77b4538..ea731571e 100644
--- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/DiskDriveBlockEntityTicker.java
+++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/DiskDriveBlockEntityTicker.java
@@ -1,6 +1,6 @@
package com.refinedmods.refinedstorage2.platform.common.storage.diskdrive;
-import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageNetworkNode;
+import com.refinedmods.refinedstorage2.api.network.impl.node.storage.StorageNetworkNode;
import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities;
import com.refinedmods.refinedstorage2.platform.common.support.network.NetworkNodeBlockEntityTicker;
@@ -9,7 +9,7 @@
import net.minecraft.world.level.block.state.BlockState;
class DiskDriveBlockEntityTicker
- extends NetworkNodeBlockEntityTicker {
+ extends NetworkNodeBlockEntityTicker {
DiskDriveBlockEntityTicker() {
super(BlockEntities.INSTANCE::getDiskDrive);
diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/AbstractStorageBlockBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/AbstractStorageBlockBlockEntity.java
index c0d533097..c658ea8b5 100644
--- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/AbstractStorageBlockBlockEntity.java
+++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/AbstractStorageBlockBlockEntity.java
@@ -1,9 +1,10 @@
package com.refinedmods.refinedstorage2.platform.common.storage.storageblock;
+import com.refinedmods.refinedstorage2.api.network.impl.node.AbstractStorageContainerNetworkNode;
import com.refinedmods.refinedstorage2.api.network.impl.node.storage.StorageNetworkNode;
import com.refinedmods.refinedstorage2.api.storage.Storage;
import com.refinedmods.refinedstorage2.platform.api.PlatformApi;
-import com.refinedmods.refinedstorage2.platform.api.storage.ItemTransferableStorageBlockEntity;
+import com.refinedmods.refinedstorage2.platform.api.storage.StorageBlockEntity;
import com.refinedmods.refinedstorage2.platform.api.storage.StorageRepository;
import com.refinedmods.refinedstorage2.platform.api.support.resource.ResourceContainer;
import com.refinedmods.refinedstorage2.platform.api.support.resource.ResourceFactory;
@@ -13,7 +14,7 @@
import com.refinedmods.refinedstorage2.platform.common.support.network.AbstractRedstoneModeNetworkNodeContainerBlockEntity;
import com.refinedmods.refinedstorage2.platform.common.support.resource.ResourceContainerImpl;
-import java.util.Objects;
+import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -29,7 +30,7 @@
abstract class AbstractStorageBlockBlockEntity
extends AbstractRedstoneModeNetworkNodeContainerBlockEntity
- implements NetworkNodeMenuProvider, ItemTransferableStorageBlockEntity {
+ implements NetworkNodeMenuProvider, StorageBlockEntity, AbstractStorageContainerNetworkNode.Provider {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractStorageBlockBlockEntity.class);
private static final String TAG_STORAGE_ID = "sid";
@@ -69,7 +70,6 @@ public void setLevel(final Level level) {
if (level.isClientSide()) {
return;
}
- final StorageRepository storageRepository = PlatformApi.INSTANCE.getStorageRepository(level);
if (storageId == null) {
// We are a new block entity, or:
// - We are placed through NBT
@@ -78,42 +78,17 @@ public void setLevel(final Level level) {
// (#setLevel(Level) -> #modifyStorageAfterAlreadyInitialized(UUID)).
// In both cases listed above we need to clean up the storage we create here.
storageId = UUID.randomUUID();
+ final StorageRepository storageRepository = PlatformApi.INSTANCE.getStorageRepository(level);
final Storage storage = createStorage(storageRepository::markAsChanged);
storageRepository.set(storageId, storage);
- mainNode.setStorage(storage);
- } else {
- // The existing block entity got loaded in the level (#load(CompoundTag) -> #setLevel(Level)).
- storageRepository.get(storageId).ifPresentOrElse(
- mainNode::setStorage,
- () -> LOGGER.warn("Storage {} could not be resolved", storageId)
- );
}
- }
-
- @Override
- public void modifyStorageIdAfterAlreadyInitialized(final UUID actualStorageId) {
- LOGGER.debug(
- "Storage {} got placed through NBT, replacing with actual storage {}",
- storageId,
- actualStorageId
- );
- cleanupUnneededInitialStorageAndReinitialize(actualStorageId);
- this.storageId = actualStorageId;
+ mainNode.setProvider(this);
}
@Override
public void load(final CompoundTag tag) {
if (tag.contains(TAG_STORAGE_ID)) {
- final UUID actualStorageId = tag.getUUID(TAG_STORAGE_ID);
- if (isPlacedThroughNbtPlacement(actualStorageId)) {
- LOGGER.debug(
- "Storage {} got placed through nbt, replacing with actual storage {}",
- storageId,
- actualStorageId
- );
- cleanupUnneededInitialStorageAndReinitialize(actualStorageId);
- }
- storageId = actualStorageId;
+ setStorageId(tag.getUUID(TAG_STORAGE_ID));
}
super.load(tag);
}
@@ -125,27 +100,6 @@ public void readConfiguration(final CompoundTag tag) {
filter.load(tag);
}
- private void cleanupUnneededInitialStorageAndReinitialize(final UUID actualStorageId) {
- // We got placed through NBT (#setLevel(Level) -> #load(CompoundTag)), or,
- // we got placed with an existing storage ID (#setLevel(Level) -> modifyStorageAfterAlreadyInitialized(UUID)).
- // Clean up the storage created earlier in #setLevel(Level).
- final StorageRepository storageRepository = PlatformApi.INSTANCE
- .getStorageRepository(Objects.requireNonNull(level));
- storageRepository.removeIfEmpty(Objects.requireNonNull(storageId)).ifPresentOrElse(
- storage -> LOGGER.debug("Unneeded storage {} successfully removed", storageId),
- () -> LOGGER.warn("Unneeded storage {} could not be removed", storageId)
- );
- storageRepository.get(actualStorageId).ifPresentOrElse(
- mainNode::setStorage,
- () -> LOGGER.warn("Actual storage ID {} could not be resolved!", actualStorageId)
- );
- }
-
- private boolean isPlacedThroughNbtPlacement(final UUID otherStorageId) {
- // When placed through nbt, the level is already set and a default new storage was created.
- return level != null && storageId != null && !storageId.equals(otherStorageId);
- }
-
@Override
public void saveAdditional(final CompoundTag tag) {
super.saveAdditional(tag);
@@ -161,6 +115,28 @@ public void writeConfiguration(final CompoundTag tag) {
filter.save(tag);
}
+ @Override
+ public void setStorageId(final UUID storageId) {
+ tryRemoveCurrentStorage(storageId);
+ this.storageId = storageId;
+ mainNode.onStorageChanged(0);
+ }
+
+ private void tryRemoveCurrentStorage(final UUID newStorageId) {
+ if (level == null || storageId == null || storageId.equals(newStorageId)) {
+ return;
+ }
+ // We got placed through NBT (#setLevel(Level) -> #load(CompoundTag)), or,
+ // we got placed with an existing storage ID (#setLevel(Level) -> #setStorageId(UUID)).
+ // Clean up the storage created earlier in #setLevel(Level).
+ LOGGER.info("Updating storage ID from {} to {}. Removing old storage", storageId, newStorageId);
+ final StorageRepository storageRepository = PlatformApi.INSTANCE.getStorageRepository(level);
+ storageRepository.removeIfEmpty(storageId).ifPresentOrElse(
+ storage -> LOGGER.info("Storage {} successfully removed", storageId),
+ () -> LOGGER.warn("Storage {} could not be removed", storageId)
+ );
+ }
+
@Override
@Nullable
public UUID getStorageId() {
@@ -177,4 +153,13 @@ public void writeScreenOpeningData(final ServerPlayer player, final FriendlyByte
buf.writeLong(mainNode.getCapacity());
filter.getFilterContainer().writeToUpdatePacket(buf);
}
+
+ @Override
+ public Optional resolve(final int index) {
+ if (level == null || storageId == null) {
+ return Optional.empty();
+ }
+ final StorageRepository storageRepository = PlatformApi.INSTANCE.getStorageRepository(level);
+ return storageRepository.get(storageId);
+ }
}
diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/FluidStorageBlockBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/FluidStorageBlockBlockEntity.java
index 412d4d87a..6b34e6fa1 100644
--- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/FluidStorageBlockBlockEntity.java
+++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/FluidStorageBlockBlockEntity.java
@@ -28,7 +28,7 @@ public FluidStorageBlockBlockEntity(final BlockPos pos,
BlockEntities.INSTANCE.getFluidStorageBlock(variant),
pos,
state,
- new StorageNetworkNode(getEnergyUsage(variant)),
+ new StorageNetworkNode(getEnergyUsage(variant), 0, 1),
PlatformApi.INSTANCE.getFluidResourceFactory()
);
this.variant = variant;
diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/ItemStorageBlockBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/ItemStorageBlockBlockEntity.java
index 397d572ba..0efc11d89 100644
--- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/ItemStorageBlockBlockEntity.java
+++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/ItemStorageBlockBlockEntity.java
@@ -28,7 +28,7 @@ public ItemStorageBlockBlockEntity(final BlockPos pos,
BlockEntities.INSTANCE.getItemStorageBlock(variant),
pos,
state,
- new StorageNetworkNode(getEnergyUsage(variant)),
+ new StorageNetworkNode(getEnergyUsage(variant), 0, 1),
PlatformApi.INSTANCE.getItemResourceFactory()
);
this.variant = variant;
diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/StorageBlockLootItemFunction.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/StorageBlockLootItemFunction.java
index 126792210..6f064375d 100644
--- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/StorageBlockLootItemFunction.java
+++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/storageblock/StorageBlockLootItemFunction.java
@@ -1,7 +1,7 @@
package com.refinedmods.refinedstorage2.platform.common.storage.storageblock;
import com.refinedmods.refinedstorage2.platform.api.PlatformApi;
-import com.refinedmods.refinedstorage2.platform.api.storage.ItemTransferableStorageBlockEntity;
+import com.refinedmods.refinedstorage2.platform.api.storage.StorageBlockEntity;
import com.refinedmods.refinedstorage2.platform.common.content.LootFunctions;
import net.minecraft.world.item.ItemStack;
@@ -20,7 +20,7 @@ public LootItemFunctionType getType() {
@Override
public ItemStack apply(final ItemStack stack, final LootContext lootContext) {
final BlockEntity blockEntity = lootContext.getParam(LootContextParams.BLOCK_ENTITY);
- if (blockEntity instanceof ItemTransferableStorageBlockEntity transferable) {
+ if (blockEntity instanceof StorageBlockEntity transferable) {
PlatformApi.INSTANCE.getStorageContainerItemHelper().transferFromBlockEntity(stack, transferable);
}
return stack;
diff --git a/refinedstorage2-resource-api/src/main/java/com/refinedmods/refinedstorage2/api/resource/list/ResourceListImpl.java b/refinedstorage2-resource-api/src/main/java/com/refinedmods/refinedstorage2/api/resource/list/ResourceListImpl.java
index d9a2c42b1..3ba666d75 100644
--- a/refinedstorage2-resource-api/src/main/java/com/refinedmods/refinedstorage2/api/resource/list/ResourceListImpl.java
+++ b/refinedstorage2-resource-api/src/main/java/com/refinedmods/refinedstorage2/api/resource/list/ResourceListImpl.java
@@ -11,11 +11,19 @@
import org.apiguardian.api.API;
/**
- * An implementation of a {@link ResourceList} that stores the resource entries in a {@link HashMap}.
+ * An implementation of a {@link ResourceList} that stores the resource entries in memory.
*/
@API(status = API.Status.STABLE, since = "2.0.0-milestone.1.2")
public class ResourceListImpl implements ResourceList {
- private final Map entries = new HashMap<>();
+ private final Map entries;
+
+ public ResourceListImpl(final Map entries) {
+ this.entries = entries;
+ }
+
+ public ResourceListImpl() {
+ this(new HashMap<>());
+ }
@Override
public OperationResult add(final ResourceKey resource, final long amount) {
diff --git a/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/InMemoryStorageImpl.java b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/InMemoryStorageImpl.java
index d03e7aa85..dbdf0cb0b 100644
--- a/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/InMemoryStorageImpl.java
+++ b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/InMemoryStorageImpl.java
@@ -15,9 +15,17 @@
*/
@API(status = API.Status.STABLE, since = "2.0.0-milestone.1.0")
public class InMemoryStorageImpl implements Storage {
- private final ResourceList list = new ResourceListImpl();
+ private final ResourceList list;
private long stored;
+ public InMemoryStorageImpl(final ResourceList list) {
+ this.list = list;
+ }
+
+ public InMemoryStorageImpl() {
+ this(new ResourceListImpl());
+ }
+
@Override
public long extract(final ResourceKey resource, final long amount, final Action action, final Actor actor) {
ResourceAmount.validate(resource, amount);
diff --git a/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java
index 7b4fd4401..70da6d0ce 100644
--- a/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java
+++ b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java
@@ -11,12 +11,13 @@
import java.util.Optional;
import javax.annotation.Nullable;
-public class StateTrackedStorage implements TrackedStorage {
+public class StateTrackedStorage implements TrackedStorage, LimitedStorage {
private static final double NEAR_CAPACITY_THRESHOLD = .75;
private final Storage delegate;
@Nullable
private final Listener listener;
+
private StorageState state;
public StateTrackedStorage(final Storage delegate, @Nullable final Listener listener) {
@@ -96,6 +97,13 @@ public Optional findTrackedResourceByActorType(final ResourceKe
: Optional.empty();
}
+ @Override
+ public long getCapacity() {
+ return delegate instanceof LimitedStorage limitedStorage
+ ? limitedStorage.getCapacity()
+ : 0;
+ }
+
@FunctionalInterface
public interface Listener {
void onStorageStateChanged();
diff --git a/refinedstorage2-storage-api/src/test/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorageTest.java b/refinedstorage2-storage-api/src/test/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorageTest.java
index 594b42135..bfdc6df44 100644
--- a/refinedstorage2-storage-api/src/test/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorageTest.java
+++ b/refinedstorage2-storage-api/src/test/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorageTest.java
@@ -65,9 +65,9 @@ void shouldSetInitialState() {
new ResourceAmount(TestResource.A, 75)
);
assertThat(sut.getStored()).isEqualTo(75);
+ assertThat(sut.getCapacity()).isZero();
}
-
@Test
void shouldSetInitialStateForLimitedStorage() {
// Arrange
@@ -82,6 +82,8 @@ void shouldSetInitialStateForLimitedStorage() {
// Assert
verify(listener, never()).onStorageStateChanged();
assertThat(state).isEqualTo(StorageState.NEAR_CAPACITY);
+ assertThat(sut.getStored()).isEqualTo(75);
+ assertThat(sut.getCapacity()).isEqualTo(100);
}
@Test