From ecbb220f80abfc5560fca8a1938555256e5f09f4 Mon Sep 17 00:00:00 2001 From: raoulvdberge Date: Fri, 29 Dec 2023 15:35:14 +0100 Subject: [PATCH] feat: portable grid menu Generifies disk inventory and extracts the internal multistorage as a "StateTrackedStorage". The storage channel type component of the internal multistorage has been moved into TypedStorage, as it's not necessary for the portable grid or StateTrackedStorage. --- .../api/network/impl/node/StorageState.java | 49 ------- ...xposedStorage.java => ExposedStorage.java} | 4 +- .../multistorage/MultiStorageListener.java | 6 - .../multistorage/MultiStorageNetworkNode.java | 64 ++++----- .../multistorage/MultiStorageProvider.java | 3 +- .../ListenerMultiStorageNetworkNodeTest.java | 120 ----------------- .../MultiStorageNetworkNodeTest.java | 25 +++- .../MultiStorageProviderImpl.java | 5 +- .../platform/api/PlatformApi.java | 3 + .../platform/api/PlatformApiProxy.java | 6 + .../storage/AbstractStorageContainerItem.java | 3 +- .../api/storage/StorageContainerItem.java | 3 +- .../storage/StorageContainerItemHelper.java | 2 +- .../common/AbstractClientModInitializer.java | 2 + .../common/AbstractModInitializer.java | 5 + .../platform/common/PlatformApiImpl.java | 11 ++ .../platform/common/content/ContentNames.java | 1 + .../platform/common/content/Menus.java | 50 ++++--- .../common/grid/AbstractGridBlock.java | 6 +- .../grid/AbstractGridContainerMenu.java | 30 +++-- .../common/grid/GridExtendedMenuProvider.java | 8 +- .../grid/screen/AbstractGridScreen.java | 10 +- .../grid/screen/CraftingGridScreen.java | 2 +- .../common/grid/screen/GridScreen.java | 2 +- .../platform/common/storage/Disk.java | 2 +- ...DriveInventory.java => DiskInventory.java} | 32 +++-- .../StorageContainerItemHelperImpl.java | 2 +- .../AbstractDiskDriveBlockEntity.java | 32 +++-- .../AbstractPortableGridBlockEntity.java | 123 +++++++++++++++++- .../portablegrid/PortableGridBlock.java | 14 ++ .../PortableGridContainerMenu.java | 35 +++++ .../portablegrid/PortableGridScreen.java | 67 ++++++++++ .../common/support/AbstractBaseScreen.java | 6 +- .../AbstractDiskLedBlockEntityRenderer.java | 2 +- .../textures/gui/portable_grid.png | Bin 0 -> 1330 bytes .../diskdrive/DiskDriveBakedModel.java | 2 +- .../diskdrive/DiskDriveBakedModel.java | 2 +- .../diskdrive/ForgeDiskDriveBlockEntity.java | 4 +- .../ForgePortableGridBlockEntity.java | 4 +- .../portablegrid/PortableGridBakedModel.java | 2 +- .../api/storage/StateTrackedStorage.java | 51 +++++--- .../api/storage/StorageState.java | 30 +++++ .../api/storage/TypedStorage.java | 2 +- .../api/storage/StateTrackedStorageTest.java | 118 +++++++++++++++++ 44 files changed, 628 insertions(+), 322 deletions(-) delete mode 100644 refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/StorageState.java rename refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/{MultiStorageExposedStorage.java => ExposedStorage.java} (92%) delete mode 100644 refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageListener.java delete mode 100644 refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ListenerMultiStorageNetworkNodeTest.java rename refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/{diskdrive/DiskDriveInventory.java => DiskInventory.java} (62%) create mode 100644 refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridContainerMenu.java create mode 100644 refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridScreen.java create mode 100644 refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/textures/gui/portable_grid.png rename refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageInternalStorage.java => refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java (61%) create mode 100644 refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StorageState.java create mode 100644 refinedstorage2-storage-api/src/test/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorageTest.java diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/StorageState.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/StorageState.java deleted file mode 100644 index 339cb4c8e..000000000 --- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/StorageState.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.refinedmods.refinedstorage2.api.network.impl.node; - -import com.refinedmods.refinedstorage2.api.storage.Storage; -import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorage; - -import org.apiguardian.api.API; - -@API(status = API.Status.STABLE, since = "2.0.0-milestone.3.3") -public enum StorageState { - /** - * There is no storage in the container. - */ - NONE, - /** - * There is a storage present in the container, but the container is inactive. - */ - INACTIVE, - /** - * The storage is active and has enough capacity to store more resources. - */ - NORMAL, - /** - * The storage is active and has less than 25% capacity left. - */ - NEAR_CAPACITY, - /** - * The storage is active and full. - */ - FULL; - - private static final double NEAR_CAPACITY_THRESHOLD = .75; - - public static StorageState compute(final Storage storage) { - if (storage instanceof LimitedStorage limitedStorage) { - return compute(limitedStorage.getCapacity(), storage.getStored()); - } - return StorageState.NORMAL; - } - - private static StorageState compute(final long capacity, final long stored) { - final double fullness = stored / (double) capacity; - if (fullness >= 1D) { - return FULL; - } else if (fullness >= NEAR_CAPACITY_THRESHOLD) { - return NEAR_CAPACITY; - } - return NORMAL; - } -} diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageExposedStorage.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ExposedStorage.java similarity index 92% rename from refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageExposedStorage.java rename to refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ExposedStorage.java index 09c5137e6..1cd63837d 100644 --- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageExposedStorage.java +++ b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ExposedStorage.java @@ -14,9 +14,9 @@ import java.util.List; import java.util.Optional; -class MultiStorageExposedStorage extends AbstractImmutableConfiguredProxyStorage> +class ExposedStorage extends AbstractImmutableConfiguredProxyStorage> implements CompositeStorage, CompositeAwareChild { - protected MultiStorageExposedStorage(final StorageConfiguration config) { + protected ExposedStorage(final StorageConfiguration config) { super(config, new CompositeStorageImpl<>(new ResourceListImpl<>())); } diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageListener.java b/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageListener.java deleted file mode 100644 index 659327903..000000000 --- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageListener.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage; - -@FunctionalInterface -public interface MultiStorageListener { - void onStorageChanged(); -} 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 index 6502eb383..222bc3a8e 100644 --- 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 @@ -1,9 +1,11 @@ package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage; import com.refinedmods.refinedstorage2.api.network.component.StorageProvider; -import com.refinedmods.refinedstorage2.api.network.impl.node.StorageState; import com.refinedmods.refinedstorage2.api.network.node.AbstractStorageNetworkNode; +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.TypedStorage; import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType; import java.util.ArrayList; @@ -28,13 +30,13 @@ public class MultiStorageNetworkNode extends AbstractStorageNetworkNode implemen @Nullable private MultiStorageProvider provider; @Nullable - private MultiStorageListener listener; + private StateTrackedStorage.Listener listener; private final long energyUsage; private final long energyUsagePerStorage; - private final MultiStorageInternalStorage[] cache; - private final Map, MultiStorageExposedStorage> exposedStorages; + private final TypedStorage>[] cache; + private final Map, ExposedStorage> exposedStorages; private int activeStorages; public MultiStorageNetworkNode(final long energyUsage, @@ -44,10 +46,10 @@ public MultiStorageNetworkNode(final long energyUsage, this.energyUsage = energyUsage; this.energyUsagePerStorage = energyUsagePerStorage; this.exposedStorages = createExposedStorages(storageChannelTypes); - this.cache = new MultiStorageInternalStorage[size]; + this.cache = new TypedStorage[size]; } - private Map, MultiStorageExposedStorage> createExposedStorages( + private Map, ExposedStorage> createExposedStorages( final Collection> storageChannelTypes ) { return storageChannelTypes.stream().collect(Collectors.toUnmodifiableMap( @@ -56,8 +58,8 @@ private Map, MultiStorageExposedStorage> createExposedS )); } - private MultiStorageExposedStorage createExposedStorage(final StorageChannelType type) { - return new MultiStorageExposedStorage<>(this); + private ExposedStorage createExposedStorage(final StorageChannelType type) { + return new ExposedStorage<>(this); } public void setProvider(final MultiStorageProvider provider) { @@ -86,29 +88,31 @@ public void onStorageChanged(final int index) { @SuppressWarnings({"rawtypes", "unchecked"}) private Set initializeStorage(final int index) { final Set results = new HashSet<>(); + if (cache[index] != null) { - final StorageChannelType removedType = cache[index].getStorageChannelType(); - final MultiStorageExposedStorage relevantComposite = exposedStorages.get(removedType); - results.add(new StorageChange(true, relevantComposite, cache[index])); + final StorageChannelType removedType = cache[index].storageChannelType(); + final ExposedStorage relevantComposite = exposedStorages.get(removedType); + results.add(new StorageChange(true, relevantComposite, cache[index].storage())); } if (provider != null) { provider.resolve(index).ifPresentOrElse(resolved -> { - cache[index] = new MultiStorageInternalStorage( - resolved.storage(), - resolved.storageChannelType(), - listener - ); - final MultiStorageExposedStorage relevantComposite = exposedStorages.get( - resolved.storageChannelType() - ); - results.add(new StorageChange(false, relevantComposite, cache[index])); + cache[index] = (TypedStorage) trackState(resolved); + final ExposedStorage relevantComposite = exposedStorages.get(resolved.storageChannelType()); + results.add(new StorageChange(false, relevantComposite, cache[index].storage())); }, () -> cache[index] = null); } return results; } + private TypedStorage> trackState(final TypedStorage> resolved) { + return new TypedStorage<>( + new StateTrackedStorage<>(resolved.storage(), listener), + resolved.storageChannelType() + ); + } + @SuppressWarnings({"unchecked", "rawtypes"}) private void processStorageChange(final StorageChange change) { if (!isActive()) { @@ -145,19 +149,19 @@ private void enableAllStorages() { @SuppressWarnings({"unchecked", "rawtypes"}) private void enableAllStoragesForChannel(final StorageChannelType type, - final MultiStorageExposedStorage exposedStorage) { - for (final MultiStorageInternalStorage internalStorage : cache) { - if (internalStorage != null && internalStorage.getStorageChannelType() == type) { - exposedStorage.addSource((MultiStorageInternalStorage) internalStorage); + final ExposedStorage exposedStorage) { + for (final TypedStorage> internalStorage : cache) { + if (internalStorage != null && internalStorage.storageChannelType() == type) { + exposedStorage.addSource((StateTrackedStorage) internalStorage.storage()); } } } private void disableAllStorages() { - exposedStorages.values().forEach(MultiStorageExposedStorage::clearSources); + exposedStorages.values().forEach(ExposedStorage::clearSources); } - public void setListener(final MultiStorageListener listener) { + public void setListener(final StateTrackedStorage.Listener listener) { this.listener = listener; } @@ -178,7 +182,7 @@ public StorageState getState(final int index) { if (!isActive()) { return StorageState.INACTIVE; } - return storage.getState(); + return storage.storage().getState(); } @Override @@ -189,7 +193,7 @@ protected Set> getRelevantStorageChannelTypes() @Override @SuppressWarnings("unchecked") public Optional> getStorageForChannel(final StorageChannelType channelType) { - final MultiStorageExposedStorage storage = exposedStorages.get(channelType); + final ExposedStorage storage = exposedStorages.get(channelType); if (storage != null) { return Optional.of((Storage) storage); } @@ -197,7 +201,7 @@ public Optional> getStorageForChannel(final StorageChannelType } private record StorageChange(boolean removed, - MultiStorageExposedStorage exposedStorage, - MultiStorageInternalStorage internalStorage) { + ExposedStorage exposedStorage, + StateTrackedStorage internalStorage) { } } 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 index 59802b791..5b9049d52 100644 --- 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 @@ -1,10 +1,11 @@ package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage; +import com.refinedmods.refinedstorage2.api.storage.Storage; import com.refinedmods.refinedstorage2.api.storage.TypedStorage; import java.util.Optional; @FunctionalInterface public interface MultiStorageProvider { - Optional> resolve(int index); + Optional>> resolve(int index); } diff --git a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ListenerMultiStorageNetworkNodeTest.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ListenerMultiStorageNetworkNodeTest.java deleted file mode 100644 index 6ae1aee46..000000000 --- a/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/ListenerMultiStorageNetworkNodeTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage; - -import com.refinedmods.refinedstorage2.api.core.Action; -import com.refinedmods.refinedstorage2.api.storage.EmptyActor; -import com.refinedmods.refinedstorage2.api.storage.Storage; -import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannel; -import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorageImpl; -import com.refinedmods.refinedstorage2.network.test.AddNetworkNode; -import com.refinedmods.refinedstorage2.network.test.InjectNetworkStorageChannel; -import com.refinedmods.refinedstorage2.network.test.NetworkTest; -import com.refinedmods.refinedstorage2.network.test.SetupNetwork; - -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.mockito.verification.VerificationMode; - -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 ListenerMultiStorageNetworkNodeTest { - @AddNetworkNode - MultiStorageNetworkNode sut; - - MultiStorageListener listener; - MultiStorageProviderImpl provider; - - @BeforeEach - void setUp() { - listener = mock(MultiStorageListener.class); - sut.setListener(listener); - provider = new MultiStorageProviderImpl(); - sut.setProvider(provider); - } - - @ParameterizedTest - @EnumSource(Action.class) - void shouldCallStateChangeListenerWhenExtracting( - final Action action, - @InjectNetworkStorageChannel final StorageChannel networkStorage - ) { - // Arrange - final Storage storage = new LimitedStorageImpl<>(100); - storage.insert("A", 75, Action.EXECUTE, EmptyActor.INSTANCE); - provider.set(1, storage); - initializeAndActivate(); - - // Act - networkStorage.extract("A", 1, action, EmptyActor.INSTANCE); - networkStorage.extract("A", 1, action, EmptyActor.INSTANCE); - - // Assert - final VerificationMode expectedTimes = action == Action.EXECUTE ? times(1) : never(); - verify(listener, expectedTimes).onStorageChanged(); - } - - @ParameterizedTest - @EnumSource(Action.class) - void shouldCallStateChangeListenerWhenInserting( - final Action action, - @InjectNetworkStorageChannel final StorageChannel networkStorage - ) { - // Arrange - final Storage storage = new LimitedStorageImpl<>(100); - storage.insert("A", 74, Action.EXECUTE, EmptyActor.INSTANCE); - provider.set(1, storage); - initializeAndActivate(); - - // Act - networkStorage.insert("A", 1, action, EmptyActor.INSTANCE); - networkStorage.insert("A", 1, action, EmptyActor.INSTANCE); - - // Assert - final VerificationMode expectedTimes = action == Action.EXECUTE ? times(1) : never(); - verify(listener, expectedTimes).onStorageChanged(); - } - - @Test - void shouldNotCallStateChangeListenerWhenUnnecessaryOnExtracting( - @InjectNetworkStorageChannel final StorageChannel networkStorage - ) { - // Arrange - final Storage storage = new LimitedStorageImpl<>(100); - storage.insert("A", 76, Action.EXECUTE, EmptyActor.INSTANCE); - provider.set(1, storage); - initializeAndActivate(); - - // Act - networkStorage.extract("A", 1, Action.EXECUTE, EmptyActor.INSTANCE); - - // Assert - verify(listener, never()).onStorageChanged(); - } - - @Test - void shouldNotCallStateChangeListenerWhenUnnecessaryOnInserting( - @InjectNetworkStorageChannel final StorageChannel networkStorage - ) { - // Arrange - final Storage storage = new LimitedStorageImpl<>(100); - provider.set(1, storage); - initializeAndActivate(); - - // Act - networkStorage.insert("A", 74, Action.EXECUTE, EmptyActor.INSTANCE); - - // Assert - verify(listener, never()).onStorageChanged(); - } - - 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/MultiStorageNetworkNodeTest.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageNetworkNodeTest.java index 2b63381e8..bc99e72c6 100644 --- 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 @@ -3,12 +3,13 @@ import com.refinedmods.refinedstorage2.api.core.Action; import com.refinedmods.refinedstorage2.api.core.filter.FilterMode; import com.refinedmods.refinedstorage2.api.network.Network; -import com.refinedmods.refinedstorage2.api.network.impl.node.StorageState; import com.refinedmods.refinedstorage2.api.resource.ResourceAmount; 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.channel.StorageChannel; import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorageImpl; import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedStorageImpl; @@ -32,6 +33,9 @@ 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 @@ -659,6 +663,25 @@ void shouldTrackChanges(@InjectNetworkStorageChannel final StorageChannel 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/MultiStorageProviderImpl.java b/refinedstorage2-network/src/test/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageProviderImpl.java index 2c37cb775..551ce6891 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/multistorage/MultiStorageProviderImpl.java @@ -12,8 +12,9 @@ class MultiStorageProviderImpl implements MultiStorageProvider { private final Map> storages = new HashMap<>(); @Override - public Optional> resolve(final int index) { - return Optional.ofNullable(storages.get(index)).map(storage -> new TypedStorage<>( + @SuppressWarnings({"unchecked", "rawtypes"}) + public Optional>> resolve(final int index) { + return (Optional) Optional.ofNullable(storages.get(index)).map(storage -> new TypedStorage<>( storage, NetworkTestFixtures.STORAGE_CHANNEL_TYPE )); diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApi.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApi.java index ee0c849dc..6d0a9b751 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApi.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApi.java @@ -48,6 +48,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.InteractionHand; +import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.Item; @@ -97,6 +98,8 @@ public interface PlatformApi { PlatformRegistry getGridSynchronizerRegistry(); + MenuProvider getGridMenuProvider(Grid grid, MenuProvider menuProvider); + UpgradeRegistry getUpgradeRegistry(); BuiltinUpgradeDestinations getBuiltinUpgradeDestinations(); diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApiProxy.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApiProxy.java index b934fa5f6..63d88d896 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApiProxy.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/PlatformApiProxy.java @@ -49,6 +49,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.InteractionHand; +import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.Item; @@ -161,6 +162,11 @@ public PlatformRegistry getGridSynchronizerRegistry() { return ensureLoaded().getGridSynchronizerRegistry(); } + @Override + public MenuProvider getGridMenuProvider(final Grid grid, final MenuProvider menuProvider) { + return ensureLoaded().getGridMenuProvider(grid, menuProvider); + } + @Override public UpgradeRegistry getUpgradeRegistry() { return ensureLoaded().getUpgradeRegistry(); diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/AbstractStorageContainerItem.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/AbstractStorageContainerItem.java index 91b7399e7..0f16a19aa 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/AbstractStorageContainerItem.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/AbstractStorageContainerItem.java @@ -37,7 +37,8 @@ protected AbstractStorageContainerItem(final Properties properties, @Override @SuppressWarnings({"unchecked", "rawtypes"}) - public Optional> resolve(final StorageRepository storageRepository, final ItemStack stack) { + public Optional>> resolve(final StorageRepository storageRepository, + final ItemStack stack) { return helper.resolve(storageRepository, stack).map(storage -> new TypedStorage(storage, type)); } diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageContainerItem.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageContainerItem.java index 05e58b027..a1bfd3958 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageContainerItem.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/storage/StorageContainerItem.java @@ -1,5 +1,6 @@ package com.refinedmods.refinedstorage2.platform.api.storage; +import com.refinedmods.refinedstorage2.api.storage.Storage; import com.refinedmods.refinedstorage2.api.storage.TypedStorage; import java.util.Optional; @@ -9,7 +10,7 @@ @API(status = API.Status.STABLE, since = "2.0.0-milestone.1.0") public interface StorageContainerItem { - Optional> resolve(StorageRepository storageRepository, ItemStack stack); + Optional>> resolve(StorageRepository storageRepository, ItemStack stack); Optional getInfo(StorageRepository storageRepository, ItemStack stack); } 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 40f83750d..865fc0e98 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 @@ -21,7 +21,7 @@ @API(status = API.Status.STABLE, since = "2.0.0-milestone.2.5") public interface StorageContainerItemHelper { - Optional> resolve(StorageRepository storageRepository, ItemStack stack); + Optional> resolve(StorageRepository storageRepository, ItemStack stack); void set(StorageRepository storageRepository, ItemStack stack, Storage storage); diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/AbstractClientModInitializer.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/AbstractClientModInitializer.java index e98c67f3d..3a40062d5 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/AbstractClientModInitializer.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/AbstractClientModInitializer.java @@ -23,6 +23,7 @@ import com.refinedmods.refinedstorage2.platform.common.storage.ItemStorageType; import com.refinedmods.refinedstorage2.platform.common.storage.diskdrive.DiskDriveScreen; import com.refinedmods.refinedstorage2.platform.common.storage.externalstorage.ExternalStorageScreen; +import com.refinedmods.refinedstorage2.platform.common.storage.portablegrid.PortableGridScreen; import com.refinedmods.refinedstorage2.platform.common.storage.storageblock.FluidStorageBlockScreen; import com.refinedmods.refinedstorage2.platform.common.storage.storageblock.ItemStorageBlockScreen; import com.refinedmods.refinedstorage2.platform.common.storagemonitor.StorageMonitorScreen; @@ -64,6 +65,7 @@ protected static void registerScreens(final ScreenRegistration registration) { registration.register(Menus.INSTANCE.getWirelessTransmitter(), WirelessTransmitterScreen::new); registration.register(Menus.INSTANCE.getStorageMonitor(), StorageMonitorScreen::new); registration.register(Menus.INSTANCE.getNetworkTransmitter(), NetworkTransmitterScreen::new); + registration.register(Menus.INSTANCE.getPortableGrid(), PortableGridScreen::new); } protected static void registerAlternativeGridHints() { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/AbstractModInitializer.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/AbstractModInitializer.java index 77038c01e..30a6c6061 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/AbstractModInitializer.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/AbstractModInitializer.java @@ -66,6 +66,7 @@ import com.refinedmods.refinedstorage2.platform.common.storage.externalstorage.ExternalStorageContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storage.portablegrid.AbstractPortableGridBlockEntity; import com.refinedmods.refinedstorage2.platform.common.storage.portablegrid.PortableGridBlock; +import com.refinedmods.refinedstorage2.platform.common.storage.portablegrid.PortableGridContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storage.portablegrid.PortableGridItem; import com.refinedmods.refinedstorage2.platform.common.storage.portablegrid.PortableGridLootItemFunctionSerializer; import com.refinedmods.refinedstorage2.platform.common.storage.portablegrid.PortableGridType; @@ -704,6 +705,10 @@ protected final void registerMenus(final RegistryCallback> callback, NETWORK_TRANSMITTER, () -> menuTypeFactory.create(NetworkTransmitterContainerMenu::new) )); + Menus.INSTANCE.setPortableGrid(callback.register( + PORTABLE_GRID, + () -> menuTypeFactory.create(PortableGridContainerMenu::new) + )); } protected final void registerLootFunctions(final RegistryCallback callback) { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/PlatformApiImpl.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/PlatformApiImpl.java index 442204f50..311bc426b 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/PlatformApiImpl.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/PlatformApiImpl.java @@ -44,6 +44,7 @@ import com.refinedmods.refinedstorage2.platform.api.upgrade.BuiltinUpgradeDestinations; import com.refinedmods.refinedstorage2.platform.api.upgrade.UpgradeRegistry; import com.refinedmods.refinedstorage2.platform.api.wirelesstransmitter.WirelessTransmitterRangeModifier; +import com.refinedmods.refinedstorage2.platform.common.grid.GridExtendedMenuProvider; import com.refinedmods.refinedstorage2.platform.common.grid.NoOpGridSynchronizer; import com.refinedmods.refinedstorage2.platform.common.grid.screen.hint.GridInsertionHintsImpl; import com.refinedmods.refinedstorage2.platform.common.grid.screen.hint.ItemGridInsertionHint; @@ -95,6 +96,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; +import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.Item; @@ -277,6 +279,15 @@ public PlatformRegistry getGridSynchronizerRegistry() { return gridSynchronizerRegistry; } + @Override + public MenuProvider getGridMenuProvider(final Grid grid, final MenuProvider menuProvider) { + return new GridExtendedMenuProvider( + grid, + storageChannelTypeRegistry, + menuProvider + ); + } + @Override public UpgradeRegistry getUpgradeRegistry() { return upgradeRegistry; diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/ContentNames.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/ContentNames.java index f5a5b4e1a..9a721d1a4 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/ContentNames.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/ContentNames.java @@ -24,6 +24,7 @@ public final class ContentNames { public static final MutableComponent DISK_DRIVE = createTranslation("block", "disk_drive"); public static final MutableComponent NETWORK_RECEIVER = createTranslation("block", "network_receiver"); public static final MutableComponent NETWORK_TRANSMITTER = createTranslation("block", "network_transmitter"); + public static final MutableComponent PORTABLE_GRID = createTranslation("block", "portable_grid"); private ContentNames() { } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/Menus.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/Menus.java index d737dcb21..c03d85145 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/Menus.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/Menus.java @@ -13,18 +13,20 @@ import com.refinedmods.refinedstorage2.platform.common.networking.NetworkTransmitterContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storage.diskdrive.DiskDriveContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storage.externalstorage.ExternalStorageContainerMenu; +import com.refinedmods.refinedstorage2.platform.common.storage.portablegrid.PortableGridContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storage.storageblock.FluidStorageBlockContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storage.storageblock.ItemStorageBlockContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storagemonitor.StorageMonitorContainerMenu; import com.refinedmods.refinedstorage2.platform.common.upgrade.RegulatorUpgradeContainerMenu; import com.refinedmods.refinedstorage2.platform.common.wirelesstransmitter.WirelessTransmitterContainerMenu; -import java.util.Objects; import java.util.function.Supplier; import javax.annotation.Nullable; import net.minecraft.world.inventory.MenuType; +import static java.util.Objects.requireNonNull; + public final class Menus { public static final Menus INSTANCE = new Menus(); @@ -64,20 +66,22 @@ public final class Menus { private Supplier> storageMonitor; @Nullable private Supplier> networkTransmitter; + @Nullable + private Supplier> portableGrid; private Menus() { } public MenuType getDiskDrive() { - return Objects.requireNonNull(diskDrive).get(); + return requireNonNull(diskDrive).get(); } public MenuType getGrid() { - return Objects.requireNonNull(grid).get(); + return requireNonNull(grid).get(); } public MenuType getCraftingGrid() { - return Objects.requireNonNull(craftingGrid).get(); + return requireNonNull(craftingGrid).get(); } public void setCraftingGrid(final Supplier> supplier) { @@ -85,7 +89,7 @@ public void setCraftingGrid(final Supplier> } public MenuType getWirelessGrid() { - return Objects.requireNonNull(wirelessGrid).get(); + return requireNonNull(wirelessGrid).get(); } public void setWirelessGrid(final Supplier> supplier) { @@ -93,7 +97,7 @@ public void setWirelessGrid(final Supplier> } public MenuType getController() { - return Objects.requireNonNull(controller).get(); + return requireNonNull(controller).get(); } public void setDiskDrive(final Supplier> supplier) { @@ -109,7 +113,7 @@ public void setController(final Supplier> supp } public MenuType getItemStorage() { - return Objects.requireNonNull(itemStorage).get(); + return requireNonNull(itemStorage).get(); } public void setItemStorage(final Supplier> supplier) { @@ -117,7 +121,7 @@ public void setItemStorage(final Supplier getFluidStorage() { - return Objects.requireNonNull(fluidStorage).get(); + return requireNonNull(fluidStorage).get(); } public void setFluidStorage(final Supplier> supplier) { @@ -125,7 +129,7 @@ public void setFluidStorage(final Supplier getImporter() { - return Objects.requireNonNull(importer).get(); + return requireNonNull(importer).get(); } public void setImporter(final Supplier> supplier) { @@ -133,7 +137,7 @@ public void setImporter(final Supplier> supplier } public MenuType getExporter() { - return Objects.requireNonNull(exporter).get(); + return requireNonNull(exporter).get(); } public void setExporter(final Supplier> supplier) { @@ -141,7 +145,7 @@ public void setExporter(final Supplier> supplier } public MenuType getInterface() { - return Objects.requireNonNull(iface).get(); + return requireNonNull(iface).get(); } public void setInterface(final Supplier> supplier) { @@ -149,7 +153,7 @@ public void setInterface(final Supplier> suppli } public MenuType getExternalStorage() { - return Objects.requireNonNull(externalStorage).get(); + return requireNonNull(externalStorage).get(); } public void setExternalStorage(final Supplier> supplier) { @@ -157,7 +161,7 @@ public void setExternalStorage(final Supplier getDetector() { - return Objects.requireNonNull(detector).get(); + return requireNonNull(detector).get(); } public void setDetector(final Supplier> supplier) { @@ -165,7 +169,7 @@ public void setDetector(final Supplier> supplier } public MenuType getDestructor() { - return Objects.requireNonNull(destructor).get(); + return requireNonNull(destructor).get(); } public void setDestructor(final Supplier> supplier) { @@ -173,7 +177,7 @@ public void setDestructor(final Supplier> supp } public MenuType getConstructor() { - return Objects.requireNonNull(constructor).get(); + return requireNonNull(constructor).get(); } public void setConstructor(final Supplier> supplier) { @@ -181,7 +185,7 @@ public void setConstructor(final Supplier> su } public MenuType getRegulatorUpgrade() { - return Objects.requireNonNull(regulatorUpgrade).get(); + return requireNonNull(regulatorUpgrade).get(); } public void setRegulatorUpgrade(final Supplier> supplier) { @@ -189,7 +193,7 @@ public void setRegulatorUpgrade(final Supplier getWirelessTransmitter() { - return Objects.requireNonNull(wirelessTransmitter).get(); + return requireNonNull(wirelessTransmitter).get(); } public void setWirelessTransmitter(final Supplier> supplier) { @@ -197,7 +201,7 @@ public void setWirelessTransmitter(final Supplier getStorageMonitor() { - return Objects.requireNonNull(storageMonitor).get(); + return requireNonNull(storageMonitor).get(); } public void setStorageMonitor(final Supplier> supplier) { @@ -205,10 +209,18 @@ public void setStorageMonitor(final Supplier getNetworkTransmitter() { - return Objects.requireNonNull(networkTransmitter).get(); + return requireNonNull(networkTransmitter).get(); } public void setNetworkTransmitter(final Supplier> supplier) { this.networkTransmitter = supplier; } + + public MenuType getPortableGrid() { + return requireNonNull(portableGrid).get(); + } + + public void setPortableGrid(final Supplier> portableGrid) { + this.portableGrid = portableGrid; + } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridBlock.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridBlock.java index e1747fe9c..d6850436c 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridBlock.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridBlock.java @@ -72,11 +72,7 @@ public boolean canAlwaysConnect() { public MenuProvider getMenuProvider(final BlockState state, final Level level, final BlockPos pos) { final BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof Grid grid && blockEntity instanceof MenuProvider menuProvider) { - return new GridExtendedMenuProvider( - grid, - PlatformApi.INSTANCE.getStorageChannelTypeRegistry(), - menuProvider - ); + return PlatformApi.INSTANCE.getGridMenuProvider(grid, menuProvider); } return null; } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridContainerMenu.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridContainerMenu.java index 0af0e65c3..37277a5a6 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridContainerMenu.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridContainerMenu.java @@ -35,7 +35,6 @@ import com.refinedmods.refinedstorage2.query.parser.ParserOperatorMappings; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.function.Predicate; import javax.annotation.Nullable; @@ -51,6 +50,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static java.util.Objects.requireNonNull; + public abstract class AbstractGridContainerMenu extends AbstractBaseContainerMenu implements GridWatcher, GridInsertionStrategy, GridExtractionStrategy, GridScrollingStrategy { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGridContainerMenu.class); @@ -66,24 +67,24 @@ public abstract class AbstractGridContainerMenu extends AbstractBaseContainerMen private static String lastSearchQuery = ""; - private final Inventory playerInventory; + protected final Inventory playerInventory; + private final GridView view; @Nullable private Grid grid; - + @Nullable private GridInsertionStrategy insertionStrategy; + @Nullable private GridExtractionStrategy extractionStrategy; + @Nullable private GridScrollingStrategy scrollingStrategy; - @Nullable private Runnable sizeChangedListener; - private GridSynchronizer synchronizer; @Nullable private PlatformStorageChannelType storageChannelTypeFilter; private boolean autoSelected; private boolean active; - @Nullable private GridSearchBox searchBox; @@ -294,17 +295,17 @@ private void initStrategies() { this.insertionStrategy = PlatformApi.INSTANCE.createGridInsertionStrategy( this, playerInventory.player, - Objects.requireNonNull(grid) + requireNonNull(grid) ); this.extractionStrategy = PlatformApi.INSTANCE.createGridExtractionStrategy( this, playerInventory.player, - Objects.requireNonNull(grid) + requireNonNull(grid) ); this.scrollingStrategy = PlatformApi.INSTANCE.createGridScrollingStrategy( this, playerInventory.player, - Objects.requireNonNull(grid) + requireNonNull(grid) ); } @@ -389,6 +390,9 @@ public boolean onInsert(final GridInsertMode insertMode, final boolean tryAltern if (grid != null && !grid.isGridActive()) { return false; } + if (insertionStrategy == null) { + return false; + } return insertionStrategy.onInsert(insertMode, tryAlternatives); } @@ -400,6 +404,9 @@ public boolean onExtract(final PlatformStorageChannelType storageChannelT if (grid != null && !grid.isGridActive()) { return false; } + if (extractionStrategy == null) { + return false; + } return extractionStrategy.onExtract(storageChannelType, resource, extractMode, cursor); } @@ -411,6 +418,9 @@ public boolean onScroll(final PlatformStorageChannelType storageChannelTy if (grid != null && !grid.isGridActive()) { return false; } + if (scrollingStrategy == null) { + return false; + } return scrollingStrategy.onScroll(storageChannelType, resource, scrollMode, slotIndex); } @@ -423,7 +433,7 @@ public boolean onTransfer(final int slotIndex) { public ItemStack quickMoveStack(final Player playerEntity, final int slotIndex) { if (!playerEntity.level().isClientSide() && grid != null && grid.isGridActive()) { final Slot slot = getSlot(slotIndex); - if (slot.hasItem()) { + if (slot.hasItem() && insertionStrategy != null) { insertionStrategy.onTransfer(slot.index); } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/GridExtendedMenuProvider.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/GridExtendedMenuProvider.java index c29c3e4d0..d4d1d9bc3 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/GridExtendedMenuProvider.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/GridExtendedMenuProvider.java @@ -20,14 +20,14 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -class GridExtendedMenuProvider implements ExtendedMenuProvider { +public class GridExtendedMenuProvider implements ExtendedMenuProvider { private final Grid grid; private final PlatformRegistry> storageChannelTypeRegistry; private final MenuProvider menuProvider; - GridExtendedMenuProvider(final Grid grid, - final PlatformRegistry> storageChannelTypeRegistry, - final MenuProvider menuProvider) { + public GridExtendedMenuProvider(final Grid grid, + final PlatformRegistry> storageChannelTypeRegistry, + final MenuProvider menuProvider) { this.grid = grid; this.storageChannelTypeRegistry = storageChannelTypeRegistry; this.menuProvider = menuProvider; diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/screen/AbstractGridScreen.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/screen/AbstractGridScreen.java index 1a7cdb2de..9760dbbfa 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/screen/AbstractGridScreen.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/screen/AbstractGridScreen.java @@ -122,8 +122,8 @@ protected void init() { addSideButton(new AutoSelectedSideButtonWidget(getMenu())); addSideButton(new StorageChannelTypeSideButtonWidget(getMenu())); - final PlatformRegistry registry = PlatformApi.INSTANCE.getGridSynchronizerRegistry(); - if (!registry.isEmpty()) { + final PlatformRegistry synchronizers = PlatformApi.INSTANCE.getGridSynchronizerRegistry(); + if (!synchronizers.isEmpty()) { addSideButton(new SynchronizationSideButtonWidget(getMenu())); searchField.addListener(this::trySynchronizeFromGrid); } @@ -193,7 +193,7 @@ protected void renderBg(final GuiGraphics graphics, final float delta, final int final int x = (width - imageWidth) / 2; final int y = (height - imageHeight) / 2; - graphics.blit(getTexture(), x, y, 0, 0, imageWidth - 34, TOP_HEIGHT); + graphics.blit(getTexture(), x, y, 0, 0, imageWidth, TOP_HEIGHT); for (int row = 0; row < visibleRows; ++row) { int textureY = 37; @@ -202,10 +202,10 @@ protected void renderBg(final GuiGraphics graphics, final float delta, final int } else if (row == visibleRows - 1) { textureY = 55; } - graphics.blit(getTexture(), x, y + TOP_HEIGHT + (18 * row), 0, textureY, imageWidth - 34, 18); + graphics.blit(getTexture(), x, y + TOP_HEIGHT + (18 * row), 0, textureY, imageWidth, 18); } - graphics.blit(getTexture(), x, y + TOP_HEIGHT + (18 * visibleRows), 0, 73, imageWidth - 34, bottomHeight); + graphics.blit(getTexture(), x, y + TOP_HEIGHT + (18 * visibleRows), 0, 73, imageWidth, bottomHeight); currentGridSlotIndex = -1; diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/screen/CraftingGridScreen.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/screen/CraftingGridScreen.java index 247831d43..ca4f0e6cb 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/screen/CraftingGridScreen.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/screen/CraftingGridScreen.java @@ -32,7 +32,7 @@ public class CraftingGridScreen extends AbstractGridScreen extends AbstractGri public GridScreen(final T menu, final Inventory inventory, final Component title) { super(menu, inventory, title, 99); this.inventoryLabelY = 75; - this.imageWidth = 227; + this.imageWidth = 193; this.imageHeight = 176; } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/Disk.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/Disk.java index 242b3a4c3..8cbd25f3b 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/Disk.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/Disk.java @@ -1,6 +1,6 @@ package com.refinedmods.refinedstorage2.platform.common.storage; -import com.refinedmods.refinedstorage2.api.network.impl.node.StorageState; +import com.refinedmods.refinedstorage2.api.storage.StorageState; import javax.annotation.Nullable; diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/DiskDriveInventory.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java similarity index 62% rename from refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/DiskDriveInventory.java rename to refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java index 69903ed5b..000a9c18a 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/DiskDriveInventory.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java @@ -1,6 +1,7 @@ -package com.refinedmods.refinedstorage2.platform.common.storage.diskdrive; +package com.refinedmods.refinedstorage2.platform.common.storage; import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageProvider; +import com.refinedmods.refinedstorage2.api.storage.Storage; import com.refinedmods.refinedstorage2.api.storage.TypedStorage; import com.refinedmods.refinedstorage2.platform.api.storage.StorageContainerItem; import com.refinedmods.refinedstorage2.platform.api.storage.StorageRepository; @@ -11,17 +12,17 @@ import net.minecraft.world.SimpleContainer; import net.minecraft.world.item.ItemStack; -class DiskDriveInventory extends SimpleContainer implements MultiStorageProvider { - private final AbstractDiskDriveBlockEntity diskDrive; +public class DiskInventory extends SimpleContainer implements MultiStorageProvider { + private final DiskListener listener; @Nullable private StorageRepository storageRepository; - DiskDriveInventory(final AbstractDiskDriveBlockEntity diskDrive, final int diskCount) { + public DiskInventory(final DiskListener listener, final int diskCount) { super(diskCount); - this.diskDrive = diskDrive; + this.listener = listener; } - void setStorageRepository(@Nullable final StorageRepository storageRepository) { + public void setStorageRepository(@Nullable final StorageRepository storageRepository) { this.storageRepository = storageRepository; } @@ -34,26 +35,18 @@ public boolean canPlaceItem(final int slot, final ItemStack stack) { public ItemStack removeItem(final int slot, final int amount) { // Forge InvWrapper calls this instead of setItem. final ItemStack result = super.removeItem(slot, amount); - diskDrive.onDiskChanged(slot); + listener.onDiskChanged(slot); return result; } @Override public void setItem(final int slot, final ItemStack stack) { super.setItem(slot, stack); - // level will not yet be present - final boolean isJustPlacedIntoLevelOrLoading = diskDrive.getLevel() == null - || diskDrive.getLevel().isClientSide(); - // level will be present, but network not yet - final boolean isPlacedThroughDismantlingMode = diskDrive.getNode().getNetwork() == null; - if (isJustPlacedIntoLevelOrLoading || isPlacedThroughDismantlingMode) { - return; - } - diskDrive.onDiskChanged(slot); + listener.onDiskChanged(slot); } @Override - public Optional> resolve(final int index) { + public Optional>> resolve(final int index) { if (storageRepository == null) { return Optional.empty(); } @@ -70,4 +63,9 @@ private Optional validateAndGetStack(final int slot) { } return Optional.of(stack); } + + @FunctionalInterface + public interface DiskListener { + void onDiskChanged(int slot); + } } 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 dbe9bd476..cd9cd5916 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 @@ -42,7 +42,7 @@ public class StorageContainerItemHelperImpl implements StorageContainerItemHelpe private final Set diskModels = new HashSet<>(); @Override - public Optional> resolve(final StorageRepository storageRepository, final ItemStack stack) { + public Optional> resolve(final StorageRepository storageRepository, final ItemStack stack) { return getId(stack).flatMap(storageRepository::get); } 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 ccba183c4..5355441a2 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,13 +1,14 @@ package com.refinedmods.refinedstorage2.platform.common.storage.diskdrive; -import com.refinedmods.refinedstorage2.api.network.impl.node.StorageState; -import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageListener; import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageNetworkNode; +import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage; +import com.refinedmods.refinedstorage2.api.storage.StorageState; import com.refinedmods.refinedstorage2.platform.api.PlatformApi; import com.refinedmods.refinedstorage2.platform.common.Platform; import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities; import com.refinedmods.refinedstorage2.platform.common.content.ContentNames; import com.refinedmods.refinedstorage2.platform.common.storage.Disk; +import com.refinedmods.refinedstorage2.platform.common.storage.DiskInventory; import com.refinedmods.refinedstorage2.platform.common.storage.StorageConfigurationContainerImpl; import com.refinedmods.refinedstorage2.platform.common.support.AbstractDirectionalBlock; import com.refinedmods.refinedstorage2.platform.common.support.BlockEntityWithDrops; @@ -46,7 +47,7 @@ public abstract class AbstractDiskDriveBlockEntity extends AbstractRedstoneModeNetworkNodeContainerBlockEntity - implements BlockEntityWithDrops, MultiStorageListener, ExtendedMenuProvider { + implements BlockEntityWithDrops, StateTrackedStorage.Listener, ExtendedMenuProvider { public static final int AMOUNT_OF_DISKS = 8; private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDiskDriveBlockEntity.class); @@ -59,7 +60,7 @@ public abstract class AbstractDiskDriveBlockEntity @Nullable protected Disk[] disks; - private final DiskDriveInventory diskInventory; + private final DiskInventory diskInventory; private final FilterWithFuzzyMode filter; private final StorageConfigurationContainerImpl configContainer; private final RateLimiter diskStateChangeRateLimiter = RateLimiter.create(1); @@ -73,7 +74,7 @@ protected AbstractDiskDriveBlockEntity(final BlockPos pos, final BlockState stat PlatformApi.INSTANCE.getStorageChannelTypeRegistry().getAll(), AMOUNT_OF_DISKS )); - this.diskInventory = new DiskDriveInventory(this, getNode().getSize()); + this.diskInventory = new DiskInventory(this::onDiskChanged, getNode().getSize()); this.filter = FilterWithFuzzyMode.createAndListenForUniqueTemplates( ResourceContainerImpl.createForFilter(), this::setChanged, @@ -191,14 +192,21 @@ public SimpleContainer getDiskInventory() { return diskInventory; } - void onDiskChanged(final int slot) { + private void onDiskChanged(final int slot) { + // Level will not yet be present + final boolean isJustPlacedIntoLevelOrLoading = level == null || level.isClientSide(); + // Level will be present, but network not yet + final boolean isPlacedThroughDismantlingMode = getNode().getNetwork() == null; + if (isJustPlacedIntoLevelOrLoading || isPlacedThroughDismantlingMode) { + return; + } getNode().onStorageChanged(slot); updateBlock(); setChanged(); } @Override - public void onStorageChanged() { + public void onStorageStateChanged() { this.syncRequested = true; } @@ -223,7 +231,11 @@ private void fromClientTag(final CompoundTag tag) { .map(item -> new Disk(item.value(), getState(diskTag))) .orElse(new Disk(null, StorageState.NONE)); } - onDriveStateUpdated(); + onClientDriveStateUpdated(); + } + + protected void onClientDriveStateUpdated() { + updateBlock(); } private StorageState getState(final CompoundTag tag) { @@ -235,10 +247,6 @@ private StorageState getState(final CompoundTag tag) { return values[stateOrdinal]; } - protected void onDriveStateUpdated() { - updateBlock(); - } - @Override public Packet getUpdatePacket() { return ClientboundBlockEntityDataPacket.create(this); diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/AbstractPortableGridBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/AbstractPortableGridBlockEntity.java index 53164b721..6d15a3643 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/AbstractPortableGridBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/AbstractPortableGridBlockEntity.java @@ -1,31 +1,148 @@ package com.refinedmods.refinedstorage2.platform.common.storage.portablegrid; -import com.refinedmods.refinedstorage2.api.network.impl.node.StorageState; +import com.refinedmods.refinedstorage2.api.grid.GridWatcher; +import com.refinedmods.refinedstorage2.api.grid.operations.GridExtractMode; +import com.refinedmods.refinedstorage2.api.grid.operations.GridInsertMode; +import com.refinedmods.refinedstorage2.api.grid.operations.GridOperations; +import com.refinedmods.refinedstorage2.api.storage.Actor; +import com.refinedmods.refinedstorage2.api.storage.ExtractableStorage; +import com.refinedmods.refinedstorage2.api.storage.InMemoryStorageImpl; +import com.refinedmods.refinedstorage2.api.storage.InsertableStorage; +import com.refinedmods.refinedstorage2.api.storage.Storage; +import com.refinedmods.refinedstorage2.api.storage.StorageState; +import com.refinedmods.refinedstorage2.api.storage.TrackedResourceAmount; +import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType; +import com.refinedmods.refinedstorage2.platform.api.grid.Grid; +import com.refinedmods.refinedstorage2.platform.api.storage.channel.PlatformStorageChannelType; +import com.refinedmods.refinedstorage2.platform.api.support.resource.ItemResource; import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities; +import com.refinedmods.refinedstorage2.platform.common.content.ContentNames; import com.refinedmods.refinedstorage2.platform.common.content.Items; +import com.refinedmods.refinedstorage2.platform.common.grid.AbstractGridContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storage.Disk; +import com.refinedmods.refinedstorage2.platform.common.storage.DiskInventory; import com.refinedmods.refinedstorage2.platform.common.storage.ItemStorageType; +import com.refinedmods.refinedstorage2.platform.common.util.ContainerUtil; +import java.util.Collections; +import java.util.List; import javax.annotation.Nullable; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -public abstract class AbstractPortableGridBlockEntity extends BlockEntity { +public abstract class AbstractPortableGridBlockEntity extends BlockEntity implements Grid, MenuProvider { + private static final String TAG_DISK_INVENTORY = "inv"; + @Nullable protected Disk disk = new Disk( Items.INSTANCE.getItemStorageDisk(ItemStorageType.Variant.ONE_K), StorageState.NEAR_CAPACITY ); + private final DiskInventory diskInventory; protected AbstractPortableGridBlockEntity(final PortableGridType type, final BlockPos pos, final BlockState state) { super(getBlockEntityType(type), pos, state); + this.diskInventory = new DiskInventory(this::onDiskChanged, 1); + } + + private void onDiskChanged(final int slot) { + // Level will not yet be present + final boolean isJustPlacedIntoLevelOrLoading = level == null || level.isClientSide(); + if (isJustPlacedIntoLevelOrLoading) { + return; + } + updateBlock(); + setChanged(); + } + + @Override + public void load(final CompoundTag tag) { + if (tag.contains(TAG_DISK_INVENTORY)) { + ContainerUtil.read(tag.getCompound(TAG_DISK_INVENTORY), diskInventory); + } + super.load(tag); + } + + @Override + public void saveAdditional(final CompoundTag tag) { + super.saveAdditional(tag); + tag.put(TAG_DISK_INVENTORY, ContainerUtil.write(diskInventory)); + } + + @Override + public void addWatcher(final GridWatcher watcher, final Class actorType) { + + } + + @Override + public void removeWatcher(final GridWatcher watcher) { + + } + + @Override + public Storage getItemStorage() { + return new InMemoryStorageImpl<>(); + } + + @Override + public boolean isGridActive() { + return true; + } + + @Override + public List> getResources(final StorageChannelType type, + final Class actorType) { + return Collections.emptyList(); + } + + @Override + public GridOperations createOperations(final PlatformStorageChannelType storageChannelType, + final Actor actor) { + return new GridOperations<>() { + @Override + public boolean extract(final T resource, final GridExtractMode extractMode, + final InsertableStorage destination) { + return false; + } + + @Override + public boolean insert(final T resource, final GridInsertMode insertMode, + final ExtractableStorage source) { + return false; + } + }; + } + + @Override + public Component getDisplayName() { + return ContentNames.PORTABLE_GRID; + } + + @Override + @Nullable + public AbstractGridContainerMenu createMenu(final int syncId, final Inventory inventory, final Player player) { + return new PortableGridContainerMenu(syncId, inventory, this); + } + + public SimpleContainer getDiskInventory() { + return diskInventory; + } + + protected void onClientDriveStateUpdated() { + updateBlock(); } - protected void onDriveStateUpdated() { + private void updateBlock() { if (level == null) { return; } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridBlock.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridBlock.java index 55526d16b..e933ac388 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridBlock.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridBlock.java @@ -1,5 +1,7 @@ package com.refinedmods.refinedstorage2.platform.common.storage.portablegrid; +import com.refinedmods.refinedstorage2.platform.api.PlatformApi; +import com.refinedmods.refinedstorage2.platform.api.grid.Grid; import com.refinedmods.refinedstorage2.platform.common.content.BlockConstants; import com.refinedmods.refinedstorage2.platform.common.support.AbstractDirectionalBlock; import com.refinedmods.refinedstorage2.platform.common.support.direction.BiDirection; @@ -9,7 +11,9 @@ import java.util.function.BiFunction; import net.minecraft.core.BlockPos; +import net.minecraft.world.MenuProvider; import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -61,4 +65,14 @@ public VoxelShape getShape(final BlockState state, public BlockEntity newBlockEntity(final BlockPos blockPos, final BlockState blockState) { return blockEntityFactory.apply(blockPos, blockState); } + + @Override + @SuppressWarnings("deprecation") + public MenuProvider getMenuProvider(final BlockState state, final Level level, final BlockPos pos) { + final BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof Grid grid && blockEntity instanceof MenuProvider menuProvider) { + return PlatformApi.INSTANCE.getGridMenuProvider(grid, menuProvider); + } + return null; + } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridContainerMenu.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridContainerMenu.java new file mode 100644 index 000000000..0e17a7086 --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridContainerMenu.java @@ -0,0 +1,35 @@ +package com.refinedmods.refinedstorage2.platform.common.storage.portablegrid; + +import com.refinedmods.refinedstorage2.platform.api.storage.StorageContainerItem; +import com.refinedmods.refinedstorage2.platform.common.content.Menus; +import com.refinedmods.refinedstorage2.platform.common.grid.AbstractGridContainerMenu; +import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ValidatedSlot; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; + +public class PortableGridContainerMenu extends AbstractGridContainerMenu { + private final SimpleContainer diskInventory; + + public PortableGridContainerMenu(final int syncId, final Inventory playerInventory, final FriendlyByteBuf buf) { + super(Menus.INSTANCE.getPortableGrid(), syncId, playerInventory, buf); + this.diskInventory = new SimpleContainer(1); + addSlots(0); + } + + PortableGridContainerMenu(final int syncId, + final Inventory playerInventory, + final AbstractPortableGridBlockEntity portableGrid) { + super(Menus.INSTANCE.getPortableGrid(), syncId, playerInventory, portableGrid); + this.diskInventory = portableGrid.getDiskInventory(); + addSlots(0); + } + + @Override + public void addSlots(final int playerInventoryY) { + super.addSlots(playerInventoryY); + addSlot(new ValidatedSlot(diskInventory, 0, -19, 8, stack -> stack.getItem() instanceof StorageContainerItem)); + transferManager.addBiTransfer(playerInventory, diskInventory); + } +} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridScreen.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridScreen.java new file mode 100644 index 000000000..753e0f6dd --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridScreen.java @@ -0,0 +1,67 @@ +package com.refinedmods.refinedstorage2.platform.common.storage.portablegrid; + +import com.refinedmods.refinedstorage2.platform.common.grid.screen.AbstractGridScreen; + +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; + +import static com.refinedmods.refinedstorage2.platform.common.util.IdentifierUtil.createIdentifier; + +public class PortableGridScreen extends AbstractGridScreen { + private static final int DISK_SLOT_WIDTH = 30; + private static final int DISK_SLOT_HEIGHT = 26; + + private static final ResourceLocation TEXTURE = createIdentifier("textures/gui/portable_grid.png"); + + public PortableGridScreen(final PortableGridContainerMenu menu, final Inventory inventory, final Component title) { + super(menu, inventory, title, 99); + this.inventoryLabelY = 75; + this.imageWidth = 193; + this.imageHeight = 176; + } + + @Override + protected int getSideButtonY() { + return super.getSideButtonY() + DISK_SLOT_HEIGHT; + } + + @Override + protected boolean hasClickedOutside(final double mouseX, + final double mouseY, + final int leftPos, + final int topPos, + final int clickedButton) { + if (mouseX >= leftPos - DISK_SLOT_WIDTH + 3 && mouseX <= leftPos + && mouseY >= topPos + 3 && mouseY <= topPos + 3 + DISK_SLOT_HEIGHT) { + return false; + } + return super.hasClickedOutside(mouseX, mouseY, leftPos, topPos, clickedButton); + } + + @Override + protected void init() { + super.init(); + getExclusionZones().add(new Rect2i( + leftPos - DISK_SLOT_WIDTH + 3, + topPos + 3, + DISK_SLOT_WIDTH, + DISK_SLOT_HEIGHT + )); + } + + @Override + protected void renderBg(final GuiGraphics graphics, final float delta, final int mouseX, final int mouseY) { + super.renderBg(graphics, delta, mouseX, mouseY); + final int x = (width - imageWidth) / 2; + final int y = (height - imageHeight) / 2; + graphics.blit(getTexture(), x - DISK_SLOT_WIDTH + 3, y + 3, 226, 0, DISK_SLOT_WIDTH, DISK_SLOT_HEIGHT); + } + + @Override + protected ResourceLocation getTexture() { + return TEXTURE; + } +} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/AbstractBaseScreen.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/AbstractBaseScreen.java index b54951840..95cb62ed7 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/AbstractBaseScreen.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/AbstractBaseScreen.java @@ -58,11 +58,15 @@ protected AbstractBaseScreen(final T menu, final Inventory playerInventory, fina this.inventoryLabelX = 7; } + protected int getSideButtonY() { + return 6; + } + @Override protected void init() { clearWidgets(); super.init(); - sideButtonY = 6; + sideButtonY = getSideButtonY(); } @Override diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/render/AbstractDiskLedBlockEntityRenderer.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/render/AbstractDiskLedBlockEntityRenderer.java index 69120652a..47e132420 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/render/AbstractDiskLedBlockEntityRenderer.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/render/AbstractDiskLedBlockEntityRenderer.java @@ -1,6 +1,6 @@ package com.refinedmods.refinedstorage2.platform.common.support.render; -import com.refinedmods.refinedstorage2.api.network.impl.node.StorageState; +import com.refinedmods.refinedstorage2.api.storage.StorageState; import com.refinedmods.refinedstorage2.platform.common.storage.Disk; import com.mojang.blaze3d.vertex.PoseStack; diff --git a/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/textures/gui/portable_grid.png b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/textures/gui/portable_grid.png new file mode 100644 index 0000000000000000000000000000000000000000..6c8a7b4046db7d2ecc6d8a2346f14b488961e98e GIT binary patch literal 1330 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$6%N?Bp530R%N1DIGxWOHUWa zkcv5P?>Yu4c}lcB^f|n^fX!e<_7Zl*MK-P6dJp-|F&%>>@*T?>UvSRBrqrDt4f34Oe+i3LU?!Q0% zX;I{<5~UCOUl;7ZAOF{$Ka-QTxlt zwPDTaTdsLsFO~oI=iiC@PrL8cbro2C{`u#Hu(@w`?uGsDfB$>IU%@DmVK={jZ_EB$ z>Hab29_PJbWq2&ez@f$<;KQIWgTcXou_1wp;UEh`6DI@9XTJlC&puba{9X4Z^*}%8 z0fyM?m9w?X&+0O;SpVdDAS3VGqS#m4^Hu%)>GO7cv)}b^XVBNzzaGIZV>76lHP zKcaqY3tsQqbpQQ&ps3LK)1M2ufkD_{@%n4k8&#iUC!-l=Xo-KUtYAHG*7Ew%{Wo*G zG?&gxz0v!Lt6}!nDn@?6+K@F(H$n#_#_ZWZ=O^#tlfI)``-ub zhR0==t(+Fb*M4~6lps5qJr7(IikBHY|J&)1zhCx7{&(4Poes}@>iUEm^^VIiun;g9 zC27s!NICc9d4Z)Li&6Tg;yD~8NUU#|X%L^$&w#E{vu{6bS*ax8Gf}wl+;L#agawt_ zg5bupGY`%AzMQGp&X3g$XjzV5d|xzaDacav#+;Mq9~RBwI&-#A>%-3-tdRWCF#FTD zPxC+T&|f+wD*NW!vVX;jXJUVD?F^cJ`st1AM*Zr$3@Hn~Td!yj3}d{X{#_nekWdEP zg2lU!Ccc<(E$U|8_Ga;9zjt$%FJEp|A#gtoD6w#>S%$~`?@u2-TsR~7od5GHQLG6p z<;nUC68&g-8c%q7eEajK#)7^0jAYWA*9uqd=XY)Qs+g_58{}|LS3j3^P6 implements TrackedStorage { +public class StateTrackedStorage implements TrackedStorage { + private static final double NEAR_CAPACITY_THRESHOLD = .75; + private final Storage delegate; - private final StorageChannelType storageChannelType; @Nullable - private final MultiStorageListener listener; + private final Listener listener; private StorageState state; - public MultiStorageInternalStorage(final Storage delegate, - final StorageChannelType storageChannelType, - @Nullable final MultiStorageListener listener) { + public StateTrackedStorage(final Storage delegate, @Nullable final Listener listener) { this.delegate = delegate; - this.storageChannelType = storageChannelType; this.listener = listener; - this.state = getState(); + this.state = computeState(); } - StorageState getState() { - return StorageState.compute(delegate); + public StorageState getState() { + return state; } - public StorageChannelType getStorageChannelType() { - return storageChannelType; + private StorageState computeState() { + if (delegate instanceof LimitedStorage limitedStorage) { + return computeState(limitedStorage.getCapacity(), delegate.getStored()); + } + return StorageState.NORMAL; + } + + private StorageState computeState(final long capacity, final long stored) { + final double fullness = stored / (double) capacity; + if (fullness >= 1D) { + return StorageState.FULL; + } else if (fullness >= NEAR_CAPACITY_THRESHOLD) { + return StorageState.NEAR_CAPACITY; + } + return StorageState.NORMAL; } private void checkStateChanged() { - final StorageState currentState = getState(); + final StorageState currentState = computeState(); if (state != currentState) { this.state = currentState; notifyListener(); @@ -47,7 +55,7 @@ private void checkStateChanged() { private void notifyListener() { if (listener != null) { - listener.onStorageChanged(); + listener.onStorageStateChanged(); } } @@ -86,4 +94,9 @@ public Optional findTrackedResourceByActorType(final T resource ? trackedStorage.findTrackedResourceByActorType(resource, actorType) : Optional.empty(); } + + @FunctionalInterface + public interface Listener { + void onStorageStateChanged(); + } } diff --git a/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StorageState.java b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StorageState.java new file mode 100644 index 000000000..917882dae --- /dev/null +++ b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StorageState.java @@ -0,0 +1,30 @@ +package com.refinedmods.refinedstorage2.api.storage; + +import org.apiguardian.api.API; + +/** + * The storage state can be cached and obtained by {@link StateTrackedStorage}. + */ +@API(status = API.Status.STABLE, since = "2.0.0-milestone.3.3") +public enum StorageState { + /** + * There is no storage in the container. + */ + NONE, + /** + * There is a storage present in the container, but the container is inactive. + */ + INACTIVE, + /** + * The storage is active and has enough capacity to store more resources. + */ + NORMAL, + /** + * The storage is active and has less than 25% capacity left. + */ + NEAR_CAPACITY, + /** + * The storage is active and full. + */ + FULL +} diff --git a/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/TypedStorage.java b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/TypedStorage.java index 4d798ded7..37d6a3be3 100644 --- a/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/TypedStorage.java +++ b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/TypedStorage.java @@ -2,5 +2,5 @@ import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType; -public record TypedStorage(Storage storage, StorageChannelType storageChannelType) { +public record TypedStorage>(S storage, StorageChannelType storageChannelType) { } 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 new file mode 100644 index 000000000..4c6a7bcab --- /dev/null +++ b/refinedstorage2-storage-api/src/test/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorageTest.java @@ -0,0 +1,118 @@ +package com.refinedmods.refinedstorage2.api.storage; + +import com.refinedmods.refinedstorage2.api.core.Action; +import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorageImpl; +import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedStorageImpl; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.mockito.verification.VerificationMode; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +class StateTrackedStorageTest { + @Test + void shouldSetInitialState() { + // Arrange + final StateTrackedStorage.Listener listener = mock(StateTrackedStorage.Listener.class); + final Storage underlyingStorage = new LimitedStorageImpl<>(100); + underlyingStorage.insert("A", 75, Action.EXECUTE, EmptyActor.INSTANCE); + final StateTrackedStorage sut = new StateTrackedStorage<>(underlyingStorage, listener); + + // Act + final StorageState state = sut.getState(); + + // Assert + verify(listener, never()).onStorageStateChanged(); + assertThat(state).isEqualTo(StorageState.NEAR_CAPACITY); + } + + @Test + void shouldUseStorageTracking() { + // Arrange + final Storage underlyingStorage = new TrackedStorageImpl<>( + new LimitedStorageImpl<>(100), + () -> 0L + ); + final StateTrackedStorage sut = new StateTrackedStorage<>(underlyingStorage, null); + + // Act + sut.insert("A", 75, Action.EXECUTE, EmptyActor.INSTANCE); + + // Assert + assertThat(sut.findTrackedResourceByActorType("A", EmptyActor.class)).isNotEmpty(); + } + + @ParameterizedTest + @EnumSource(Action.class) + void shouldCallStateChangeListenerWhenExtracting(final Action action) { + // Arrange + final StateTrackedStorage.Listener listener = mock(StateTrackedStorage.Listener.class); + final Storage underlyingStorage = new LimitedStorageImpl<>(100); + underlyingStorage.insert("A", 75, Action.EXECUTE, EmptyActor.INSTANCE); + final StateTrackedStorage sut = new StateTrackedStorage<>(underlyingStorage, listener); + + // Act + sut.extract("A", 1, action, EmptyActor.INSTANCE); + sut.extract("A", 1, action, EmptyActor.INSTANCE); + + // Assert + final VerificationMode expectedTimes = action == Action.EXECUTE ? times(1) : never(); + verify(listener, expectedTimes).onStorageStateChanged(); + assertThat(sut.findTrackedResourceByActorType("A", EmptyActor.class)).isEmpty(); + } + + @ParameterizedTest + @EnumSource(Action.class) + void shouldCallStateChangeListenerWhenInserting(final Action action) { + // Arrange + final StateTrackedStorage.Listener listener = mock(StateTrackedStorage.Listener.class); + final Storage underlyingStorage = new LimitedStorageImpl<>(100); + underlyingStorage.insert("A", 74, Action.EXECUTE, EmptyActor.INSTANCE); + final StateTrackedStorage sut = new StateTrackedStorage<>(underlyingStorage, listener); + + // Act + sut.insert("A", 1, action, EmptyActor.INSTANCE); + sut.insert("A", 1, action, EmptyActor.INSTANCE); + + // Assert + final VerificationMode expectedTimes = action == Action.EXECUTE ? times(1) : never(); + verify(listener, expectedTimes).onStorageStateChanged(); + } + + @ParameterizedTest + @EnumSource(Action.class) + void shouldNotCallStateChangeListenerWhenUnnecessaryOnExtracting(final Action action) { + // Arrange + final StateTrackedStorage.Listener listener = mock(StateTrackedStorage.Listener.class); + final Storage underlyingStorage = new LimitedStorageImpl<>(100); + underlyingStorage.insert("A", 76, Action.EXECUTE, EmptyActor.INSTANCE); + final StateTrackedStorage sut = new StateTrackedStorage<>(underlyingStorage, listener); + + // Act + sut.extract("A", 1, action, EmptyActor.INSTANCE); + + // Assert + verify(listener, never()).onStorageStateChanged(); + } + + @ParameterizedTest + @EnumSource(Action.class) + void shouldNotCallStateChangeListenerWhenUnnecessaryOnInserting(final Action action) { + // Arrange + final StateTrackedStorage.Listener listener = mock(StateTrackedStorage.Listener.class); + final Storage underlyingStorage = new LimitedStorageImpl<>(100); + final StateTrackedStorage sut = new StateTrackedStorage<>(underlyingStorage, listener); + + // Act + sut.insert("A", 74, action, EmptyActor.INSTANCE); + + // Assert + verify(listener, never()).onStorageStateChanged(); + } +}