diff --git a/CHANGELOG.md b/CHANGELOG.md index 50d7f0f8e..de4579a08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Custom disk models. Fluid disks now have a different model. - Portable Grid +### Changed + +- The Portable Grid now shows an energy bar in the UI. +- The energy bar on creative items now shows the infinity symbol instead of the whole amount. + ## [2.0.0-milestone.3.2] - 2023-11-03 ### Added 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..a2e90bb16 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,23 +88,18 @@ 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) StateTrackedStorage.of(resolved, listener); + final ExposedStorage relevantComposite = exposedStorages.get(resolved.storageChannelType()); + results.add(new StorageChange(false, relevantComposite, cache[index].storage())); }, () -> cache[index] = null); } @@ -145,19 +142,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 +175,7 @@ public StorageState getState(final int index) { if (!isActive()) { return StorageState.INACTIVE; } - return storage.getState(); + return storage.storage().getState(); } @Override @@ -189,7 +186,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 +194,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..72e3cf9f6 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 @@ -97,6 +97,8 @@ public interface PlatformApi { PlatformRegistry getGridSynchronizerRegistry(); + void writeGridScreenOpeningData(Grid grid, FriendlyByteBuf buf); + 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..9820d7009 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 @@ -161,6 +161,11 @@ public PlatformRegistry getGridSynchronizerRegistry() { return ensureLoaded().getGridSynchronizerRegistry(); } + @Override + public void writeGridScreenOpeningData(final Grid grid, final FriendlyByteBuf buf) { + ensureLoaded().writeGridScreenOpeningData(grid, buf); + } + @Override public UpgradeRegistry getUpgradeRegistry() { return ensureLoaded().getUpgradeRegistry(); diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/configurationcard/ConfigurationCardTarget.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/configurationcard/ConfigurationCardTarget.java index 16500540f..e3f8c79d0 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/configurationcard/ConfigurationCardTarget.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/configurationcard/ConfigurationCardTarget.java @@ -1,5 +1,6 @@ package com.refinedmods.refinedstorage2.platform.api.configurationcard; +import java.util.Collections; import java.util.List; import net.minecraft.nbt.CompoundTag; @@ -15,7 +16,11 @@ public interface ConfigurationCardTarget { void readConfiguration(CompoundTag tag); - List getUpgradeItems(); + default List getUpgradeItems() { + return Collections.emptyList(); + } - boolean addUpgradeItem(Item upgradeItem); + default boolean addUpgradeItem(Item upgradeItem) { + return false; + } } 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/Config.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/Config.java index 8e20884c5..54bdec5c8 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/Config.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/Config.java @@ -50,6 +50,8 @@ public interface Config { SimpleEnergyUsageEntry getNetworkTransmitter(); + PortableGridEntry getPortableGrid(); + interface SimpleEnergyUsageEntry { long getEnergyUsage(); } @@ -167,4 +169,14 @@ interface WirelessGridEntry { interface WirelessTransmitterEntry extends SimpleEnergyUsageEntry { int getBaseRange(); } + + interface PortableGridEntry { + long getEnergyCapacity(); + + long getOpenEnergyUsage(); + + long getInsertEnergyUsage(); + + long getExtractEnergyUsage(); + } } 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..91cc2fc01 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 @@ -45,6 +45,7 @@ import com.refinedmods.refinedstorage2.platform.api.upgrade.UpgradeRegistry; import com.refinedmods.refinedstorage2.platform.api.wirelesstransmitter.WirelessTransmitterRangeModifier; import com.refinedmods.refinedstorage2.platform.common.grid.NoOpGridSynchronizer; +import com.refinedmods.refinedstorage2.platform.common.grid.screen.AbstractGridScreen; import com.refinedmods.refinedstorage2.platform.common.grid.screen.hint.GridInsertionHintsImpl; import com.refinedmods.refinedstorage2.platform.common.grid.screen.hint.ItemGridInsertionHint; import com.refinedmods.refinedstorage2.platform.common.grid.screen.hint.SingleItemGridInsertionHint; @@ -277,6 +278,11 @@ public PlatformRegistry getGridSynchronizerRegistry() { return gridSynchronizerRegistry; } + @Override + public void writeGridScreenOpeningData(final Grid grid, final FriendlyByteBuf buf) { + AbstractGridScreen.writeScreenOpeningData(storageChannelTypeRegistry, grid, buf); + } + @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/DefaultEnergyUsage.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/DefaultEnergyUsage.java index 041f44474..bdbd5caf9 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/DefaultEnergyUsage.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/DefaultEnergyUsage.java @@ -50,6 +50,11 @@ public final class DefaultEnergyUsage { public static final long WIRELESS_TRANSMITTER = 16; public static final int WIRELESS_TRANSMITTER_BASE_RANGE = 16; + public static final long PORTABLE_GRID_CAPACITY = 1000; + public static final long PORTABLE_GRID_OPEN = 5; + public static final long PORTABLE_GRID_INSERT = 5; + public static final long PORTABLE_GRID_EXTRACT = 5; + private DefaultEnergyUsage() { } } 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/controller/ControllerContainerMenu.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/controller/ControllerContainerMenu.java index dd6f8497a..9e2e29515 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/controller/ControllerContainerMenu.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/controller/ControllerContainerMenu.java @@ -1,56 +1,39 @@ package com.refinedmods.refinedstorage2.platform.common.controller; -import com.refinedmods.refinedstorage2.platform.common.Platform; import com.refinedmods.refinedstorage2.platform.common.content.Menus; import com.refinedmods.refinedstorage2.platform.common.support.AbstractBaseContainerMenu; import com.refinedmods.refinedstorage2.platform.common.support.RedstoneMode; import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ClientProperty; import com.refinedmods.refinedstorage2.platform.common.support.containermenu.PropertyTypes; import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ServerProperty; +import com.refinedmods.refinedstorage2.platform.common.support.energy.EnergyContainerMenu; +import com.refinedmods.refinedstorage2.platform.common.support.energy.EnergyInfo; -import javax.annotation.Nullable; - -import com.google.common.util.concurrent.RateLimiter; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; -public class ControllerContainerMenu extends AbstractBaseContainerMenu { - private final Player player; - private final RateLimiter energyUpdateRateLimiter = RateLimiter.create(4); - - private long stored; - private long capacity; - - @Nullable - private ControllerBlockEntity controller; +public class ControllerContainerMenu extends AbstractBaseContainerMenu implements EnergyContainerMenu { + private final EnergyInfo energyInfo; public ControllerContainerMenu(final int syncId, final Inventory playerInventory, final FriendlyByteBuf buf) { super(Menus.INSTANCE.getController(), syncId); - addPlayerInventory(playerInventory, 8, 107); - - this.stored = buf.readLong(); - this.capacity = buf.readLong(); - this.player = playerInventory.player; - + this.energyInfo = EnergyInfo.forClient(playerInventory.player, buf.readLong(), buf.readLong()); registerProperty(new ClientProperty<>(PropertyTypes.REDSTONE_MODE, RedstoneMode.IGNORE)); } ControllerContainerMenu(final int syncId, final Inventory playerInventory, final ControllerBlockEntity controller, - final Player playerEntity) { + final Player player) { super(Menus.INSTANCE.getController(), syncId); - - this.controller = controller; - this.stored = controller.getActualStored(); - this.capacity = controller.getActualCapacity(); - this.player = playerEntity; - + this.energyInfo = EnergyInfo.forServer( + player, + controller::getActualStored, + controller::getActualCapacity + ); addPlayerInventory(playerInventory, 8, 107); - registerProperty(new ServerProperty<>( PropertyTypes.REDSTONE_MODE, controller::getRedstoneMode, @@ -61,30 +44,11 @@ public ControllerContainerMenu(final int syncId, final Inventory playerInventory @Override public void broadcastChanges() { super.broadcastChanges(); - if (controller == null) { - return; - } - final boolean changed = stored != controller.getActualStored() || capacity != controller.getActualCapacity(); - if (changed && energyUpdateRateLimiter.tryAcquire()) { - setEnergyInfo(controller.getActualStored(), controller.getActualCapacity()); - Platform.INSTANCE.getServerToClientCommunications().sendControllerEnergyInfo( - (ServerPlayer) player, - stored, - capacity - ); - } - } - - public void setEnergyInfo(final long newStored, final long newCapacity) { - this.stored = newStored; - this.capacity = newCapacity; + energyInfo.detectChanges(); } - long getStored() { - return stored; - } - - long getCapacity() { - return capacity; + @Override + public EnergyInfo getEnergyInfo() { + return energyInfo; } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/controller/ControllerScreen.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/controller/ControllerScreen.java index 424a3624c..3bffb46c5 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/controller/ControllerScreen.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/controller/ControllerScreen.java @@ -5,39 +5,26 @@ import com.refinedmods.refinedstorage2.platform.common.support.widget.ProgressWidget; import com.refinedmods.refinedstorage2.platform.common.support.widget.RedstoneModeSideButtonWidget; -import java.util.Collections; -import java.util.List; +import javax.annotation.Nullable; -import net.minecraft.client.gui.GuiGraphics; 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; -import static com.refinedmods.refinedstorage2.platform.common.util.IdentifierUtil.createStoredWithCapacityTranslation; import static com.refinedmods.refinedstorage2.platform.common.util.IdentifierUtil.createTranslation; public class ControllerScreen extends AbstractBaseScreen { private static final ResourceLocation TEXTURE = createIdentifier("textures/gui/controller.png"); - private final ProgressWidget progressWidget; + @Nullable + private ProgressWidget progressWidget; public ControllerScreen(final ControllerContainerMenu menu, final Inventory playerInventory, final Component text) { super(menu, playerInventory, text); - this.inventoryLabelY = 94; this.imageWidth = 176; this.imageHeight = 189; - - this.progressWidget = new ProgressWidget( - 80, - 20, - 16, - 70, - this::getPercentageFull, - this::createTooltip - ); - addRenderableWidget(progressWidget); } @Override @@ -47,28 +34,24 @@ protected void init() { getMenu().getProperty(PropertyTypes.REDSTONE_MODE), createTranslation("gui", "controller.redstone_mode_help") )); + if (progressWidget == null) { + progressWidget = new ProgressWidget( + leftPos + 80, + topPos + 20, + 16, + 70, + getMenu().getEnergyInfo()::getPercentageFull, + getMenu().getEnergyInfo()::createTooltip + ); + } else { + progressWidget.setX(leftPos + 80); + progressWidget.setY(topPos + 20); + } + addRenderableWidget(progressWidget); } @Override protected ResourceLocation getTexture() { return TEXTURE; } - - private double getPercentageFull() { - return (double) getMenu().getStored() / (double) getMenu().getCapacity(); - } - - private List createTooltip() { - return Collections.singletonList(createStoredWithCapacityTranslation( - getMenu().getStored(), - getMenu().getCapacity(), - getPercentageFull() - )); - } - - @Override - protected void renderLabels(final GuiGraphics graphics, final int mouseX, final int mouseY) { - super.renderLabels(graphics, mouseX, mouseY); - progressWidget.render(graphics, mouseX - leftPos, mouseY - topPos, 0); - } } 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..7719cb5bc 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 @@ -1,7 +1,5 @@ package com.refinedmods.refinedstorage2.platform.common.grid; -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.BlockItemProvider; @@ -10,14 +8,10 @@ import com.refinedmods.refinedstorage2.platform.common.support.direction.BiDirectionType; import com.refinedmods.refinedstorage2.platform.common.support.direction.DirectionType; -import net.minecraft.core.BlockPos; import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.MenuProvider; import net.minecraft.world.item.DyeColor; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BooleanProperty; @@ -66,18 +60,4 @@ public DyeColor getColor() { public boolean canAlwaysConnect() { return true; } - - @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 new GridExtendedMenuProvider( - grid, - PlatformApi.INSTANCE.getStorageChannelTypeRegistry(), - menuProvider - ); - } - return null; - } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridBlockEntity.java index ff94c75b5..c5a8aa47c 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/AbstractGridBlockEntity.java @@ -16,19 +16,21 @@ import com.refinedmods.refinedstorage2.platform.api.support.resource.ItemResource; import com.refinedmods.refinedstorage2.platform.common.storage.channel.StorageChannelTypes; import com.refinedmods.refinedstorage2.platform.common.support.AbstractDirectionalBlock; +import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ExtendedMenuProvider; import com.refinedmods.refinedstorage2.platform.common.support.network.AbstractRedstoneModeNetworkNodeContainerBlockEntity; import java.util.List; import java.util.Objects; import net.minecraft.core.BlockPos; -import net.minecraft.world.MenuProvider; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; public abstract class AbstractGridBlockEntity extends AbstractRedstoneModeNetworkNodeContainerBlockEntity - implements Grid, MenuProvider { + implements Grid, ExtendedMenuProvider { protected AbstractGridBlockEntity(final BlockEntityType type, final BlockPos pos, final BlockState state, @@ -39,6 +41,11 @@ protected AbstractGridBlockEntity(final BlockEntityType List> getResources(final StorageChannelType type, final Class actorType) { 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 deleted file mode 100644 index c29c3e4d0..000000000 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/GridExtendedMenuProvider.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.refinedmods.refinedstorage2.platform.common.grid; - -import com.refinedmods.refinedstorage2.api.storage.TrackedResourceAmount; -import com.refinedmods.refinedstorage2.platform.api.grid.Grid; -import com.refinedmods.refinedstorage2.platform.api.storage.PlayerActor; -import com.refinedmods.refinedstorage2.platform.api.storage.channel.PlatformStorageChannelType; -import com.refinedmods.refinedstorage2.platform.api.support.registry.PlatformRegistry; -import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ExtendedMenuProvider; -import com.refinedmods.refinedstorage2.platform.common.util.PacketUtil; - -import java.util.List; -import javax.annotation.Nullable; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; - -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) { - this.grid = grid; - this.storageChannelTypeRegistry = storageChannelTypeRegistry; - this.menuProvider = menuProvider; - } - - @Override - public void writeScreenOpeningData(final ServerPlayer player, final FriendlyByteBuf buf) { - buf.writeBoolean(grid.isGridActive()); - final List> types = storageChannelTypeRegistry.getAll(); - buf.writeInt(types.size()); - types.forEach(type -> writeStorageChannel(type, buf)); - } - - private void writeStorageChannel(final PlatformStorageChannelType storageChannelType, - final FriendlyByteBuf buf) { - final ResourceLocation id = storageChannelTypeRegistry.getId(storageChannelType).orElseThrow(); - buf.writeResourceLocation(id); - final List> resources = grid.getResources(storageChannelType, PlayerActor.class); - buf.writeInt(resources.size()); - resources.forEach(resource -> writeGridResource(storageChannelType, resource, buf)); - } - - private void writeGridResource(final PlatformStorageChannelType storageChannelType, - final TrackedResourceAmount resource, - final FriendlyByteBuf buf) { - storageChannelType.toBuffer(resource.resourceAmount().getResource(), buf); - buf.writeLong(resource.resourceAmount().getAmount()); - PacketUtil.writeTrackedResource(buf, resource.trackedResource()); - } - - @Override - public Component getDisplayName() { - return menuProvider.getDisplayName(); - } - - @Nullable - @Override - public AbstractContainerMenu createMenu(final int syncId, final Inventory inventory, final Player player) { - return menuProvider.createMenu(syncId, inventory, player); - } -} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/WirelessGridExtendedMenuProvider.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/WirelessGridExtendedMenuProvider.java index eb7c93a64..f8d5bd446 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/WirelessGridExtendedMenuProvider.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/WirelessGridExtendedMenuProvider.java @@ -2,43 +2,42 @@ import com.refinedmods.refinedstorage2.platform.api.PlatformApi; import com.refinedmods.refinedstorage2.platform.api.grid.Grid; -import com.refinedmods.refinedstorage2.platform.api.storage.channel.PlatformStorageChannelType; import com.refinedmods.refinedstorage2.platform.api.support.network.bounditem.SlotReference; -import com.refinedmods.refinedstorage2.platform.api.support.registry.PlatformRegistry; import com.refinedmods.refinedstorage2.platform.common.content.ContentNames; +import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ExtendedMenuProvider; + +import javax.annotation.Nullable; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -class WirelessGridExtendedMenuProvider extends GridExtendedMenuProvider { +class WirelessGridExtendedMenuProvider implements ExtendedMenuProvider { + private final Grid grid; private final SlotReference slotReference; - WirelessGridExtendedMenuProvider(final Grid grid, - final PlatformRegistry> - storageChannelTypeRegistry, - final SlotReference slotReference) { - super(grid, storageChannelTypeRegistry, new MenuProvider() { - @Override - public Component getDisplayName() { - return ContentNames.WIRELESS_GRID; - } - - @Override - public AbstractContainerMenu createMenu(final int syncId, final Inventory inventory, final Player player) { - return new WirelessGridContainerMenu(syncId, inventory, grid, slotReference); - } - }); + WirelessGridExtendedMenuProvider(final Grid grid, final SlotReference slotReference) { + this.grid = grid; this.slotReference = slotReference; } @Override public void writeScreenOpeningData(final ServerPlayer player, final FriendlyByteBuf buf) { - super.writeScreenOpeningData(player, buf); + PlatformApi.INSTANCE.writeGridScreenOpeningData(grid, buf); PlatformApi.INSTANCE.writeSlotReference(slotReference, buf); } + + @Override + public Component getDisplayName() { + return ContentNames.WIRELESS_GRID; + } + + @Nullable + @Override + public AbstractContainerMenu createMenu(final int syncId, final Inventory inventory, final Player player) { + return new WirelessGridContainerMenu(syncId, inventory, grid, slotReference); + } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/WirelessGridItem.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/WirelessGridItem.java index 9ceb7db11..5dc2340d1 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/WirelessGridItem.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/grid/WirelessGridItem.java @@ -44,10 +44,6 @@ public void use(final ServerPlayer player, final NetworkBoundItemSession session) { session.drainEnergy(Platform.INSTANCE.getConfig().getWirelessGrid().getOpenEnergyUsage()); final Grid grid = new WirelessGrid(session); - Platform.INSTANCE.getMenuOpener().openMenu(player, new WirelessGridExtendedMenuProvider( - grid, - PlatformApi.INSTANCE.getStorageChannelTypeRegistry(), - slotReference - )); + Platform.INSTANCE.getMenuOpener().openMenu(player, new WirelessGridExtendedMenuProvider(grid, slotReference)); } } 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..4394a64de 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 @@ -4,11 +4,15 @@ import com.refinedmods.refinedstorage2.api.grid.operations.GridInsertMode; import com.refinedmods.refinedstorage2.api.grid.view.GridResource; import com.refinedmods.refinedstorage2.api.grid.view.GridView; +import com.refinedmods.refinedstorage2.api.storage.TrackedResourceAmount; import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedResource; import com.refinedmods.refinedstorage2.platform.api.PlatformApi; +import com.refinedmods.refinedstorage2.platform.api.grid.Grid; import com.refinedmods.refinedstorage2.platform.api.grid.GridScrollMode; import com.refinedmods.refinedstorage2.platform.api.grid.GridSynchronizer; import com.refinedmods.refinedstorage2.platform.api.grid.view.PlatformGridResource; +import com.refinedmods.refinedstorage2.platform.api.storage.PlayerActor; +import com.refinedmods.refinedstorage2.platform.api.storage.channel.PlatformStorageChannelType; import com.refinedmods.refinedstorage2.platform.api.support.registry.PlatformRegistry; import com.refinedmods.refinedstorage2.platform.api.support.resource.ItemResource; import com.refinedmods.refinedstorage2.platform.common.Platform; @@ -22,6 +26,7 @@ import com.refinedmods.refinedstorage2.platform.common.support.widget.History; import com.refinedmods.refinedstorage2.platform.common.support.widget.RedstoneModeSideButtonWidget; import com.refinedmods.refinedstorage2.platform.common.support.widget.ScrollbarWidget; +import com.refinedmods.refinedstorage2.platform.common.util.PacketUtil; import com.refinedmods.refinedstorage2.query.lexer.SyntaxHighlighter; import com.refinedmods.refinedstorage2.query.lexer.SyntaxHighlighterColors; @@ -34,8 +39,10 @@ import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; @@ -122,8 +129,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 +200,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 +209,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; @@ -632,4 +639,35 @@ public boolean keyReleased(final int key, final int scanCode, final int modifier return super.keyReleased(key, scanCode, modifiers); } + + public static void writeScreenOpeningData(final PlatformRegistry> + storageChannelTypeRegistry, + final Grid grid, + final FriendlyByteBuf buf) { + buf.writeBoolean(grid.isGridActive()); + final List> types = storageChannelTypeRegistry.getAll(); + buf.writeInt(types.size()); + types.forEach(type -> writeStorageChannel(storageChannelTypeRegistry, type, grid, buf)); + } + + private static void writeStorageChannel( + final PlatformRegistry> storageChannelTypeRegistry, + final PlatformStorageChannelType storageChannelType, + final Grid grid, + final FriendlyByteBuf buf + ) { + final ResourceLocation id = storageChannelTypeRegistry.getId(storageChannelType).orElseThrow(); + buf.writeResourceLocation(id); + final List> resources = grid.getResources(storageChannelType, PlayerActor.class); + buf.writeInt(resources.size()); + resources.forEach(resource -> writeGridResource(storageChannelType, resource, buf)); + } + + private static void writeGridResource(final PlatformStorageChannelType storageChannelType, + final TrackedResourceAmount resource, + final FriendlyByteBuf buf) { + storageChannelType.toBuffer(resource.resourceAmount().getResource(), buf); + buf.writeLong(resource.resourceAmount().getAmount()); + PacketUtil.writeTrackedResource(buf, resource.trackedResource()); + } } 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/DiskInventory.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java new file mode 100644 index 000000000..f08864058 --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java @@ -0,0 +1,115 @@ +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.StorageState; +import com.refinedmods.refinedstorage2.api.storage.TypedStorage; +import com.refinedmods.refinedstorage2.platform.api.storage.StorageContainerItem; +import com.refinedmods.refinedstorage2.platform.api.storage.StorageRepository; + +import java.util.Optional; +import java.util.function.IntFunction; +import javax.annotation.Nullable; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.item.ItemStack; + +public class DiskInventory extends SimpleContainer implements MultiStorageProvider { + private static final String TAG_DISK_STATE = "s"; + private static final String TAG_DISK_ITEM_ID = "i"; + + private final DiskListener listener; + @Nullable + private StorageRepository storageRepository; + + public DiskInventory(final DiskListener listener, final int diskCount) { + super(diskCount); + this.listener = listener; + } + + public void setStorageRepository(@Nullable final StorageRepository storageRepository) { + this.storageRepository = storageRepository; + } + + @Override + public boolean canPlaceItem(final int slot, final ItemStack stack) { + return stack.getItem() instanceof StorageContainerItem; + } + + @Override + public ItemStack removeItem(final int slot, final int amount) { + // Forge InvWrapper calls this instead of setItem. + final ItemStack result = super.removeItem(slot, amount); + listener.onDiskChanged(slot); + return result; + } + + @Override + public void setItem(final int slot, final ItemStack stack) { + super.setItem(slot, stack); + listener.onDiskChanged(slot); + } + + @Override + public Optional>> resolve(final int index) { + if (storageRepository == null) { + return Optional.empty(); + } + return validateAndGetStack(index).flatMap(stack -> ((StorageContainerItem) stack.getItem()).resolve( + storageRepository, + stack + )); + } + + private Optional validateAndGetStack(final int slot) { + final ItemStack stack = getItem(slot); + if (stack.isEmpty() || !(stack.getItem() instanceof StorageContainerItem)) { + return Optional.empty(); + } + return Optional.of(stack); + } + + @SuppressWarnings("deprecation") // Forge deprecates registry access this way + public ListTag toSyncTag(final IntFunction stateProvider) { + final ListTag list = new ListTag(); + for (int i = 0; i < getContainerSize(); ++i) { + final CompoundTag disk = new CompoundTag(); + disk.putByte(TAG_DISK_STATE, (byte) stateProvider.apply(i).ordinal()); + final ItemStack diskItem = getItem(i); + if (!diskItem.isEmpty()) { + disk.putInt(TAG_DISK_ITEM_ID, BuiltInRegistries.ITEM.getId(diskItem.getItem())); + } + list.add(disk); + } + return list; + } + + @SuppressWarnings("deprecation") // Forge deprecates registry access this way + public Disk[] fromSyncTag(final ListTag list) { + final Disk[] disks = new Disk[list.size()]; + for (int i = 0; i < list.size(); ++i) { + final CompoundTag diskTag = list.getCompound(i); + disks[i] = BuiltInRegistries.ITEM.getHolder(diskTag.getInt(TAG_DISK_ITEM_ID)) + .map(item -> new Disk(item.value(), getState(diskTag))) + .orElse(new Disk(null, StorageState.NONE)); + } + return disks; + } + + private StorageState getState(final CompoundTag tag) { + final int stateOrdinal = tag.getByte(TAG_DISK_STATE); + final StorageState[] values = StorageState.values(); + if (stateOrdinal < 0 || stateOrdinal >= values.length) { + return StorageState.NONE; + } + return values[stateOrdinal]; + } + + @FunctionalInterface + public interface DiskListener { + void onDiskChanged(int slot); + } +} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskStateChangeListener.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskStateChangeListener.java new file mode 100644 index 000000000..b2be6cb39 --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskStateChangeListener.java @@ -0,0 +1,53 @@ +package com.refinedmods.refinedstorage2.platform.common.storage; + +import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage; + +import com.google.common.util.concurrent.RateLimiter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DiskStateChangeListener implements StateTrackedStorage.Listener { + private static final Logger LOGGER = LoggerFactory.getLogger(DiskStateChangeListener.class); + + private final BlockEntity blockEntity; + private final RateLimiter rateLimiter = RateLimiter.create(1); + + private boolean syncRequested; + + public DiskStateChangeListener(final BlockEntity blockEntity) { + this.blockEntity = blockEntity; + } + + @Override + public void onStorageStateChanged() { + syncRequested = true; + } + + public void updateIfNecessary() { + if (!syncRequested) { + return; + } + if (!rateLimiter.tryAcquire()) { + return; + } + LOGGER.debug("Disk state change for block at {}", blockEntity.getBlockPos()); + syncRequested = false; + immediateUpdate(); + } + + public void immediateUpdate() { + final Level level = blockEntity.getLevel(); + if (level == null) { + return; + } + level.sendBlockUpdated( + blockEntity.getBlockPos(), + blockEntity.getBlockState(), + blockEntity.getBlockState(), + Block.UPDATE_ALL + ); + } +} 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..7623c431b 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,13 @@ 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.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.DiskStateChangeListener; import com.refinedmods.refinedstorage2.platform.common.storage.StorageConfigurationContainerImpl; import com.refinedmods.refinedstorage2.platform.common.support.AbstractDirectionalBlock; import com.refinedmods.refinedstorage2.platform.common.support.BlockEntityWithDrops; @@ -19,12 +19,9 @@ import javax.annotation.Nullable; -import com.google.common.util.concurrent.RateLimiter; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -39,32 +36,23 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public abstract class AbstractDiskDriveBlockEntity extends AbstractRedstoneModeNetworkNodeContainerBlockEntity - implements BlockEntityWithDrops, MultiStorageListener, ExtendedMenuProvider { + implements BlockEntityWithDrops, ExtendedMenuProvider { public static final int AMOUNT_OF_DISKS = 8; - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDiskDriveBlockEntity.class); - private static final String TAG_DISK_INVENTORY = "inv"; - private static final String TAG_DISKS = "states"; - private static final String TAG_DISK_STATE = "s"; - private static final String TAG_DISK_ITEM_ID = "i"; + private static final String TAG_DISKS = "disks"; @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); - - private boolean syncRequested; + private final DiskStateChangeListener diskStateListener = new DiskStateChangeListener(this); protected AbstractDiskDriveBlockEntity(final BlockPos pos, final BlockState state) { super(BlockEntities.INSTANCE.getDiskDrive(), pos, state, new MultiStorageNetworkNode( @@ -73,7 +61,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, @@ -86,7 +74,7 @@ protected AbstractDiskDriveBlockEntity(final BlockPos pos, final BlockState stat this::getRedstoneMode, this::setRedstoneMode ); - getNode().setListener(this); + getNode().setListener(diskStateListener); getNode().setNormalizer(filter.createNormalizer()); } @@ -104,20 +92,7 @@ public static Item getDisk(final CompoundTag tag, final int slot) { } void updateDiskStateIfNecessaryInLevel() { - if (!syncRequested) { - return; - } - if (diskStateChangeRateLimiter.tryAcquire()) { - LOGGER.debug("Disk state change for block at {}", getBlockPos()); - this.syncRequested = false; - sync(); - } - } - - private void sync() { - if (level != null) { - level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), Block.UPDATE_ALL); - } + diskStateListener.updateIfNecessary(); } @Override @@ -155,7 +130,7 @@ private void initialize(final Level level) { @Override public void activenessChanged(final boolean newActive) { super.activenessChanged(newActive); - updateBlock(); + diskStateListener.immediateUpdate(); } @Override @@ -191,52 +166,37 @@ 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(); + diskStateListener.immediateUpdate(); setChanged(); } - @Override - public void onStorageChanged() { - this.syncRequested = true; - } - @Override protected void onNetworkInNodeInitialized() { super.onNetworkInNodeInitialized(); // It's important to sync here as the initial update packet might have failed as the network // could possibly be not initialized yet. - updateBlock(); + diskStateListener.immediateUpdate(); } - @SuppressWarnings("deprecation") // Forge deprecates registry access this way private void fromClientTag(final CompoundTag tag) { if (!tag.contains(TAG_DISKS)) { return; } - final ListTag disksList = tag.getList(TAG_DISKS, Tag.TAG_COMPOUND); - disks = new Disk[disksList.size()]; - for (int i = 0; i < disksList.size(); ++i) { - final CompoundTag diskTag = disksList.getCompound(i); - disks[i] = BuiltInRegistries.ITEM.getHolder(diskTag.getInt(TAG_DISK_ITEM_ID)) - .map(item -> new Disk(item.value(), getState(diskTag))) - .orElse(new Disk(null, StorageState.NONE)); - } - onDriveStateUpdated(); + disks = diskInventory.fromSyncTag(tag.getList(TAG_DISKS, Tag.TAG_COMPOUND)); + onClientDriveStateUpdated(); } - private StorageState getState(final CompoundTag tag) { - final int stateOrdinal = tag.getByte(TAG_DISK_STATE); - final StorageState[] values = StorageState.values(); - if (stateOrdinal < 0 || stateOrdinal >= values.length) { - return StorageState.NONE; - } - return values[stateOrdinal]; - } - - protected void onDriveStateUpdated() { - updateBlock(); + protected void onClientDriveStateUpdated() { + diskStateListener.immediateUpdate(); } @Override @@ -245,24 +205,13 @@ public Packet getUpdatePacket() { } @Override - @SuppressWarnings("deprecation") // Forge deprecates registry access this way public CompoundTag getUpdateTag() { final CompoundTag tag = new CompoundTag(); // This null check is important. #getUpdateTag() can be called before the node's network is initialized! if (getNode().getNetwork() == null) { return tag; } - final ListTag disksList = new ListTag(); - for (int i = 0; i < getNode().getSize(); ++i) { - final CompoundTag disk = new CompoundTag(); - disk.putByte(TAG_DISK_STATE, (byte) getNode().getState(i).ordinal()); - final ItemStack diskItem = diskInventory.getItem(i); - if (!diskItem.isEmpty()) { - disk.putInt(TAG_DISK_ITEM_ID, BuiltInRegistries.ITEM.getId(diskItem.getItem())); - } - disksList.add(disk); - } - tag.put(TAG_DISKS, disksList); + tag.put(TAG_DISKS, diskInventory.toSyncTag(getNode()::getState)); return tag; } 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/diskdrive/DiskDriveInventory.java deleted file mode 100644 index 69903ed5b..000000000 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/DiskDriveInventory.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.refinedmods.refinedstorage2.platform.common.storage.diskdrive; - -import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageProvider; -import com.refinedmods.refinedstorage2.api.storage.TypedStorage; -import com.refinedmods.refinedstorage2.platform.api.storage.StorageContainerItem; -import com.refinedmods.refinedstorage2.platform.api.storage.StorageRepository; - -import java.util.Optional; -import javax.annotation.Nullable; - -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.item.ItemStack; - -class DiskDriveInventory extends SimpleContainer implements MultiStorageProvider { - private final AbstractDiskDriveBlockEntity diskDrive; - @Nullable - private StorageRepository storageRepository; - - DiskDriveInventory(final AbstractDiskDriveBlockEntity diskDrive, final int diskCount) { - super(diskCount); - this.diskDrive = diskDrive; - } - - void setStorageRepository(@Nullable final StorageRepository storageRepository) { - this.storageRepository = storageRepository; - } - - @Override - public boolean canPlaceItem(final int slot, final ItemStack stack) { - return stack.getItem() instanceof StorageContainerItem; - } - - @Override - 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); - 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); - } - - @Override - public Optional> resolve(final int index) { - if (storageRepository == null) { - return Optional.empty(); - } - return validateAndGetStack(index).flatMap(stack -> ((StorageContainerItem) stack.getItem()).resolve( - storageRepository, - stack - )); - } - - private Optional validateAndGetStack(final int slot) { - final ItemStack stack = getItem(slot); - if (stack.isEmpty() || !(stack.getItem() instanceof StorageContainerItem)) { - return Optional.empty(); - } - return Optional.of(stack); - } -} 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..da2692490 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,35 +1,311 @@ package com.refinedmods.refinedstorage2.platform.common.storage.portablegrid; -import com.refinedmods.refinedstorage2.api.network.impl.node.StorageState; +import com.refinedmods.refinedstorage2.api.core.Action; +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.network.energy.EnergyStorage; +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.StateTrackedStorage; +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.TypedStorage; +import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType; +import com.refinedmods.refinedstorage2.platform.api.PlatformApi; +import com.refinedmods.refinedstorage2.platform.api.configurationcard.ConfigurationCardTarget; +import com.refinedmods.refinedstorage2.platform.api.grid.Grid; +import com.refinedmods.refinedstorage2.platform.api.storage.channel.PlatformStorageChannelType; +import com.refinedmods.refinedstorage2.platform.api.support.energy.EnergyBlockEntity; +import com.refinedmods.refinedstorage2.platform.api.support.resource.ItemResource; +import com.refinedmods.refinedstorage2.platform.common.Platform; import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities; -import com.refinedmods.refinedstorage2.platform.common.content.Items; +import com.refinedmods.refinedstorage2.platform.common.content.ContentNames; +import com.refinedmods.refinedstorage2.platform.common.grid.AbstractGridContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storage.Disk; -import com.refinedmods.refinedstorage2.platform.common.storage.ItemStorageType; +import com.refinedmods.refinedstorage2.platform.common.storage.DiskInventory; +import com.refinedmods.refinedstorage2.platform.common.storage.DiskStateChangeListener; +import com.refinedmods.refinedstorage2.platform.common.support.RedstoneMode; +import com.refinedmods.refinedstorage2.platform.common.support.RedstoneModeSettings; +import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ExtendedMenuProvider; +import com.refinedmods.refinedstorage2.platform.common.support.energy.BlockEntityEnergyStorage; +import com.refinedmods.refinedstorage2.platform.common.support.energy.CreativeEnergyStorage; +import com.refinedmods.refinedstorage2.platform.common.util.ContainerUtil; +import java.util.Collections; +import java.util.List; import javax.annotation.Nullable; +import com.google.common.util.concurrent.RateLimiter; import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.Block; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public abstract class AbstractPortableGridBlockEntity extends BlockEntity { +public abstract class AbstractPortableGridBlockEntity extends BlockEntity implements Grid, ExtendedMenuProvider, + EnergyBlockEntity, ConfigurationCardTarget { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPortableGridBlockEntity.class); + + private static final String TAG_DISK_INVENTORY = "inv"; + private static final String TAG_DISKS = "disks"; + private static final String TAG_STORED = "stored"; + private static final String TAG_REDSTONE_MODE = "rm"; + + @Nullable + protected Disk disk; + + private final DiskInventory diskInventory; + private final DiskStateChangeListener diskStateListener = new DiskStateChangeListener(this); + private final EnergyStorage energyStorage; + private final RateLimiter activenessChangeRateLimiter = RateLimiter.create(1); + + private RedstoneMode redstoneMode = RedstoneMode.IGNORE; @Nullable - protected Disk disk = new Disk( - Items.INSTANCE.getItemStorageDisk(ItemStorageType.Variant.ONE_K), - StorageState.NEAR_CAPACITY - ); + private TypedStorage> storage; protected AbstractPortableGridBlockEntity(final PortableGridType type, final BlockPos pos, final BlockState state) { super(getBlockEntityType(type), pos, state); + this.diskInventory = new DiskInventory(this::onDiskChanged, 1); + this.energyStorage = createEnergyStorage(type, this); + } + + private static EnergyStorage createEnergyStorage(final PortableGridType type, final BlockEntity blockEntity) { + if (type == PortableGridType.CREATIVE) { + return CreativeEnergyStorage.INSTANCE; + } + return new BlockEntityEnergyStorage( + Platform.INSTANCE.getConfig().getPortableGrid().getEnergyCapacity(), + blockEntity + ); + } + + void update(final BlockState state) { + diskStateListener.updateIfNecessary(); + final boolean newActive = isGridActive(); + final boolean activenessNeedsUpdate = state.getValue(PortableGridBlock.ACTIVE) != newActive; + if (activenessNeedsUpdate && activenessChangeRateLimiter.tryAcquire()) { + updateActivenessBlockState(state, newActive); + } } - protected void onDriveStateUpdated() { - if (level == null) { + private void updateActivenessBlockState(final BlockState state, final boolean active) { + if (level != null) { + LOGGER.debug( + "Sending block update at {} due to activeness change: {} -> {}", + getBlockPos(), + state.getValue(PortableGridBlock.ACTIVE), + active + ); + level.setBlockAndUpdate(getBlockPos(), state.setValue(PortableGridBlock.ACTIVE, active)); + } + } + + private void onDiskChanged(final int slot) { + final boolean isJustPlacedIntoLevelOrLoading = level == null || level.isClientSide(); + if (isJustPlacedIntoLevelOrLoading) { return; } - level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); + updateStorage(); + diskStateListener.immediateUpdate(); + setChanged(); + } + + @Override + public void setLevel(final Level level) { + super.setLevel(level); + if (!level.isClientSide()) { + initialize(level); + } + } + + @Override + public void setChanged() { + super.setChanged(); + if (level != null && !level.isClientSide()) { + initialize(level); + } + } + + private void initialize(final Level level) { + diskInventory.setStorageRepository(PlatformApi.INSTANCE.getStorageRepository(level)); + updateStorage(); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private void updateStorage() { + this.storage = diskInventory.resolve(0) + .map(resolved -> (TypedStorage) StateTrackedStorage.of(resolved, diskStateListener)) + .orElse(null); + } + + @Override + public void load(final CompoundTag tag) { + fromClientTag(tag); + if (tag.contains(TAG_DISK_INVENTORY)) { + ContainerUtil.read(tag.getCompound(TAG_DISK_INVENTORY), diskInventory); + } + if (tag.contains(TAG_STORED)) { + energyStorage.receive(tag.getLong(TAG_STORED), Action.EXECUTE); + } + readConfiguration(tag); + super.load(tag); + } + + @Override + public void readConfiguration(final CompoundTag tag) { + if (tag.contains(TAG_REDSTONE_MODE)) { + redstoneMode = RedstoneModeSettings.getRedstoneMode(tag.getInt(TAG_REDSTONE_MODE)); + } + } + + private void fromClientTag(final CompoundTag tag) { + if (!tag.contains(TAG_DISKS)) { + return; + } + disk = diskInventory.fromSyncTag(tag.getList(TAG_DISKS, Tag.TAG_COMPOUND))[0]; + onClientDriveStateUpdated(); + } + + protected void onClientDriveStateUpdated() { + diskStateListener.immediateUpdate(); + } + + @Override + public void saveAdditional(final CompoundTag tag) { + super.saveAdditional(tag); + tag.put(TAG_DISK_INVENTORY, ContainerUtil.write(diskInventory)); + tag.putLong(TAG_STORED, energyStorage.getStored()); + writeConfiguration(tag); + } + + @Override + public void writeConfiguration(final CompoundTag tag) { + tag.putInt(TAG_REDSTONE_MODE, RedstoneModeSettings.getRedstoneMode(redstoneMode)); + } + + @Override + public Packet getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override + public CompoundTag getUpdateTag() { + final CompoundTag tag = new CompoundTag(); + tag.put(TAG_DISKS, diskInventory.toSyncTag(idx -> getStorageState())); + return tag; + } + + public RedstoneMode getRedstoneMode() { + return redstoneMode; + } + + public void setRedstoneMode(final RedstoneMode redstoneMode) { + this.redstoneMode = redstoneMode; + setChanged(); + } + + private StorageState getStorageState() { + if (storage == null) { + return StorageState.NONE; + } + if (!isGridActive()) { + return StorageState.INACTIVE; + } + return storage.storage().getState(); + } + + @Override + public void addWatcher(final GridWatcher watcher, final Class actorType) { + // TODO + } + + @Override + public void removeWatcher(final GridWatcher watcher) { + // TODO + } + + @Override + public Storage getItemStorage() { + // TODO + return new InMemoryStorageImpl<>(); + } + + @Override + public boolean isGridActive() { + return energyStorage.getStored() > 0 + && level != null + && redstoneMode.isActive(level.hasNeighborSignal(worldPosition)); + } + + @Override + public List> getResources(final StorageChannelType type, + final Class actorType) { + // TODO + return Collections.emptyList(); + } + + @Override + public GridOperations createOperations(final PlatformStorageChannelType storageChannelType, + final Actor actor) { + // TODO + 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); + } + + @Override + public void writeScreenOpeningData(final ServerPlayer player, final FriendlyByteBuf buf) { + PlatformApi.INSTANCE.writeGridScreenOpeningData(this, buf); + buf.writeLong(energyStorage.getStored()); + buf.writeLong(energyStorage.getCapacity()); + } + + public SimpleContainer getDiskInventory() { + return diskInventory; + } + + @Override + public EnergyStorage getEnergyStorage() { + return energyStorage; } private static BlockEntityType getBlockEntityType(final PortableGridType type) { 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..80d3a0d0b 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,6 +1,7 @@ package com.refinedmods.refinedstorage2.platform.common.storage.portablegrid; import com.refinedmods.refinedstorage2.platform.common.content.BlockConstants; +import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities; import com.refinedmods.refinedstorage2.platform.common.support.AbstractDirectionalBlock; import com.refinedmods.refinedstorage2.platform.common.support.direction.BiDirection; import com.refinedmods.refinedstorage2.platform.common.support.direction.BiDirectionType; @@ -10,29 +11,50 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; public class PortableGridBlock extends AbstractDirectionalBlock implements EntityBlock { + public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); + private static final VoxelShape SHAPE_HORIZONTAL = box(0, 0, 0, 16, 13.2, 16); private static final VoxelShape SHAPE_VERTICAL_SOUTH = box(0, 0, 0, 16, 16, 13.2); private static final VoxelShape SHAPE_VERTICAL_NORTH = box(0, 0, 16 - 13.2, 16, 16, 16); private static final VoxelShape SHAPE_VERTICAL_EAST = box(0, 0, 0, 13.2, 16, 16); private static final VoxelShape SHAPE_VERTICAL_WEST = box(16 - 13.2, 0, 0, 16, 16, 16); - private final PortableGridType type; + private final PortableGridBlockEntityTicker ticker; private final BiFunction blockEntityFactory; public PortableGridBlock(final PortableGridType type, final BiFunction factory) { super(BlockConstants.PROPERTIES); - this.type = type; + this.ticker = new PortableGridBlockEntityTicker(() -> type == PortableGridType.NORMAL + ? BlockEntities.INSTANCE.getPortableGrid() + : BlockEntities.INSTANCE.getCreativePortableGrid()); this.blockEntityFactory = factory; } + @Override + protected BlockState getDefaultState() { + return super.getDefaultState().setValue(ACTIVE, false); + } + + @Override + protected void createBlockStateDefinition(final StateDefinition.Builder builder) { + super.createBlockStateDefinition(builder); + builder.add(ACTIVE); + } + @Override protected DirectionType getDirectionType() { return BiDirectionType.INSTANCE; @@ -61,4 +83,11 @@ public VoxelShape getShape(final BlockState state, public BlockEntity newBlockEntity(final BlockPos blockPos, final BlockState blockState) { return blockEntityFactory.apply(blockPos, blockState); } + + @Override + public BlockEntityTicker getTicker(final Level level, + final BlockState state, + final BlockEntityType type) { + return ticker.get(level, type); + } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridBlockEntityTicker.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridBlockEntityTicker.java new file mode 100644 index 000000000..c0b0b1390 --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridBlockEntityTicker.java @@ -0,0 +1,26 @@ +package com.refinedmods.refinedstorage2.platform.common.storage.portablegrid; + +import com.refinedmods.refinedstorage2.platform.common.support.AbstractBlockEntityTicker; + +import java.util.function.Supplier; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +class PortableGridBlockEntityTicker extends AbstractBlockEntityTicker { + PortableGridBlockEntityTicker( + final Supplier> allowedTypeSupplier + ) { + super(allowedTypeSupplier); + } + + @Override + public void tick(final Level level, + final BlockPos pos, + final BlockState state, + final AbstractPortableGridBlockEntity blockEntity) { + blockEntity.update(state); + } +} 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..4ba36f4d6 --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridContainerMenu.java @@ -0,0 +1,65 @@ +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.RedstoneMode; +import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ClientProperty; +import com.refinedmods.refinedstorage2.platform.common.support.containermenu.PropertyTypes; +import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ServerProperty; +import com.refinedmods.refinedstorage2.platform.common.support.containermenu.ValidatedSlot; +import com.refinedmods.refinedstorage2.platform.common.support.energy.EnergyContainerMenu; +import com.refinedmods.refinedstorage2.platform.common.support.energy.EnergyInfo; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; + +public class PortableGridContainerMenu extends AbstractGridContainerMenu implements EnergyContainerMenu { + private final SimpleContainer diskInventory; + private final EnergyInfo energyInfo; + + public PortableGridContainerMenu(final int syncId, final Inventory playerInventory, final FriendlyByteBuf buf) { + super(Menus.INSTANCE.getPortableGrid(), syncId, playerInventory, buf); + this.diskInventory = new SimpleContainer(1); + this.energyInfo = EnergyInfo.forClient(playerInventory.player, buf.readLong(), buf.readLong()); + addSlots(0); + registerProperty(new ClientProperty<>(PropertyTypes.REDSTONE_MODE, RedstoneMode.IGNORE)); + } + + PortableGridContainerMenu(final int syncId, + final Inventory playerInventory, + final AbstractPortableGridBlockEntity portableGrid) { + super(Menus.INSTANCE.getPortableGrid(), syncId, playerInventory, portableGrid); + this.diskInventory = portableGrid.getDiskInventory(); + this.energyInfo = EnergyInfo.forServer( + playerInventory.player, + portableGrid.getEnergyStorage()::getStored, + portableGrid.getEnergyStorage()::getCapacity + ); + addSlots(0); + registerProperty(new ServerProperty<>( + PropertyTypes.REDSTONE_MODE, + portableGrid::getRedstoneMode, + portableGrid::setRedstoneMode + )); + } + + @Override + public void broadcastChanges() { + super.broadcastChanges(); + energyInfo.detectChanges(); + } + + @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); + } + + @Override + public EnergyInfo getEnergyInfo() { + return energyInfo; + } +} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridLootItemFunction.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridLootItemFunction.java index 0eeaca775..de9c1fc5b 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridLootItemFunction.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridLootItemFunction.java @@ -15,7 +15,7 @@ public LootItemFunctionType getType() { @Override public ItemStack apply(final ItemStack itemStack, final LootContext lootContext) { - // todo ! + // TODO: item representation of the portable grid return itemStack; } } 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..d3b0787a8 --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/PortableGridScreen.java @@ -0,0 +1,89 @@ +package com.refinedmods.refinedstorage2.platform.common.storage.portablegrid; + +import com.refinedmods.refinedstorage2.platform.common.grid.screen.AbstractGridScreen; +import com.refinedmods.refinedstorage2.platform.common.support.widget.ProgressWidget; + +import javax.annotation.Nullable; + +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"); + + @Nullable + private ProgressWidget progressWidget; + + 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 + )); + final int progressX = 172; + final int progressY = imageHeight - 10 - 70; + if (progressWidget == null) { + progressWidget = new ProgressWidget( + leftPos + progressX, + topPos + progressY, + 16, + 70, + getMenu().getEnergyInfo()::getPercentageFull, + getMenu().getEnergyInfo()::createTooltip + ); + } else { + progressWidget.setX(leftPos + progressX); + progressWidget.setY(topPos + progressY); + } + addRenderableWidget(progressWidget); + } + + @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/ServerToClientCommunications.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/ServerToClientCommunications.java index 59d2fda68..8eeb6223a 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/ServerToClientCommunications.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/ServerToClientCommunications.java @@ -12,7 +12,7 @@ import net.minecraft.server.level.ServerPlayer; public interface ServerToClientCommunications { - void sendControllerEnergyInfo(ServerPlayer player, long stored, long capacity); + void sendEnergyInfo(ServerPlayer player, long stored, long capacity); void sendWirelessTransmitterRange(ServerPlayer player, int range); diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/energy/EnergyContainerMenu.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/energy/EnergyContainerMenu.java new file mode 100644 index 000000000..16569962a --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/energy/EnergyContainerMenu.java @@ -0,0 +1,6 @@ +package com.refinedmods.refinedstorage2.platform.common.support.energy; + +@FunctionalInterface +public interface EnergyContainerMenu { + EnergyInfo getEnergyInfo(); +} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/energy/EnergyInfo.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/energy/EnergyInfo.java new file mode 100644 index 000000000..df26a4ee0 --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/energy/EnergyInfo.java @@ -0,0 +1,83 @@ +package com.refinedmods.refinedstorage2.platform.common.support.energy; + +import com.refinedmods.refinedstorage2.platform.common.Platform; + +import java.util.Collections; +import java.util.List; +import java.util.function.LongSupplier; + +import com.google.common.util.concurrent.RateLimiter; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; + +import static com.refinedmods.refinedstorage2.platform.common.util.IdentifierUtil.createStoredWithCapacityTranslation; + +public class EnergyInfo { + private final Player player; + private final LongSupplier storedSupplier; + private final LongSupplier capacitySupplier; + private final RateLimiter rateLimiter = RateLimiter.create(4); + + private long stored; + private long capacity; + + private EnergyInfo(final ServerPlayer player, + final LongSupplier storedSupplier, + final LongSupplier capacitySupplier) { + this.player = player; + this.storedSupplier = storedSupplier; + this.capacitySupplier = capacitySupplier; + this.stored = storedSupplier.getAsLong(); + this.capacity = capacitySupplier.getAsLong(); + } + + private EnergyInfo(final Player player, final long stored, final long capacity) { + this.player = player; + this.storedSupplier = () -> 0L; + this.capacitySupplier = () -> 0L; + this.stored = stored; + this.capacity = capacity; + } + + public void detectChanges() { + final long newStored = storedSupplier.getAsLong(); + final long newCapacity = capacitySupplier.getAsLong(); + final boolean changed = stored != newStored || capacity != newCapacity; + if (changed && rateLimiter.tryAcquire()) { + setEnergy(newStored, newCapacity); + Platform.INSTANCE.getServerToClientCommunications().sendEnergyInfo( + (ServerPlayer) player, + newStored, + newCapacity + ); + } + } + + public void setEnergy(final long newStored, final long newCapacity) { + this.stored = newStored; + this.capacity = newCapacity; + } + + public List createTooltip() { + return Collections.singletonList(createStoredWithCapacityTranslation( + stored, + capacity, + getPercentageFull() + )); + } + + public double getPercentageFull() { + return (double) stored / (double) capacity; + } + + public static EnergyInfo forServer(final Player player, + final LongSupplier storedSupplier, + final LongSupplier capacitySupplier) { + return new EnergyInfo((ServerPlayer) player, storedSupplier, capacitySupplier); + } + + public static EnergyInfo forClient(final Player player, final long stored, final long capacity) { + return new EnergyInfo(player, stored, capacity); + } +} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/AbstractRedstoneModeNetworkNodeContainerBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/AbstractRedstoneModeNetworkNodeContainerBlockEntity.java index 49787cd0e..68a1f934f 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/AbstractRedstoneModeNetworkNodeContainerBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/AbstractRedstoneModeNetworkNodeContainerBlockEntity.java @@ -7,8 +7,6 @@ import com.refinedmods.refinedstorage2.platform.common.support.RedstoneMode; import com.refinedmods.refinedstorage2.platform.common.support.RedstoneModeSettings; -import java.util.Collections; -import java.util.List; import java.util.UUID; import javax.annotation.Nullable; @@ -16,7 +14,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -71,16 +68,6 @@ public void readConfiguration(final CompoundTag tag) { } } - @Override - public List getUpgradeItems() { - return Collections.emptyList(); - } - - @Override - public boolean addUpgradeItem(final Item upgradeItem) { - return false; - } - public RedstoneMode getRedstoneMode() { return redstoneMode; } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/NetworkNodeContainerBlockEntityImpl.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/NetworkNodeContainerBlockEntityImpl.java index a3461c809..14ada3bcd 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/NetworkNodeContainerBlockEntityImpl.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/support/network/NetworkNodeContainerBlockEntityImpl.java @@ -13,7 +13,6 @@ import com.google.common.util.concurrent.RateLimiter; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BooleanProperty; @@ -137,13 +136,6 @@ protected final Direction getDirection() { return directionalBlock.extractDirection(blockState); } - protected final void updateBlock() { - if (level == null) { - return; - } - level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); - } - protected boolean doesBlockStateChangeWarrantNetworkNodeUpdate( final BlockState oldBlockState, final BlockState newBlockState 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/java/com/refinedmods/refinedstorage2/platform/common/util/IdentifierUtil.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/util/IdentifierUtil.java index 880eb27c4..8965e7670 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/util/IdentifierUtil.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/util/IdentifierUtil.java @@ -40,10 +40,12 @@ public static MutableComponent createStoredWithCapacityTranslation( return createTranslation( "misc", "stored_with_capacity", - AmountFormatting.format(stored), - AmountFormatting.format(capacity), - String.valueOf((int) (pct * 100D)) - ); + Component.literal(stored == Long.MAX_VALUE ? "∞" : AmountFormatting.format(stored)) + .withStyle(ChatFormatting.WHITE), + Component.literal(capacity == Long.MAX_VALUE ? "∞" : AmountFormatting.format(capacity)) + .withStyle(ChatFormatting.WHITE), + Component.literal(String.valueOf((int) (pct * 100D))) + ).withStyle(ChatFormatting.GRAY); } public static MutableComponent createTranslationAsHeading(final String category, final String value) { diff --git a/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/lang/en_us.json b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/lang/en_us.json index e7ea7a9a2..aca94c00e 100644 --- a/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/lang/en_us.json +++ b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/lang/en_us.json @@ -306,7 +306,6 @@ "text.autoconfig.refinedstorage2.option.externalStorage": "External Storage", "text.autoconfig.refinedstorage2.option.externalStorage.energyUsage": "Energy usage", "text.autoconfig.refinedstorage2.option.wirelessGrid": "Wireless Grid", - "text.autoconfig.refinedstorage2.option.wirelessGrid.useEnergy": "Use energy", "text.autoconfig.refinedstorage2.option.wirelessGrid.energyCapacity": "Energy capacity", "text.autoconfig.refinedstorage2.option.wirelessGrid.openEnergyUsage": "Open energy usage", "text.autoconfig.refinedstorage2.option.wirelessGrid.insertEnergyUsage": "Insert energy usage", @@ -318,6 +317,13 @@ "text.autoconfig.refinedstorage2.option.storageMonitor.energyUsage": "Energy usage", "text.autoconfig.refinedstorage2.option.networkReceiver": "Network Receiver", "text.autoconfig.refinedstorage2.option.networkReceiver.energyUsage": "Energy usage", + "text.autoconfig.refinedstorage2.option.networkTransmitter": "Network Transmitter", + "text.autoconfig.refinedstorage2.option.networkTransmitter.energyUsage": "Energy usage", + "text.autoconfig.refinedstorage2.option.portableGrid": "Portable Grid", + "text.autoconfig.refinedstorage2.option.portableGrid.energyCapacity": "Energy capacity", + "text.autoconfig.refinedstorage2.option.portableGrid.openEnergyUsage": "Open energy usage", + "text.autoconfig.refinedstorage2.option.portableGrid.insertEnergyUsage": "Insert energy usage", + "text.autoconfig.refinedstorage2.option.portableGrid.extractEnergyUsage": "Extract energy usage", "advancements.refinedstorage2.root.description": "Use one or multiple Controllers in a network to provide your network with energy", "advancements.refinedstorage2.connecting": "Connecting", "advancements.refinedstorage2.connecting.description": "Use Cable to connect devices with each other, or place devices against each other", 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 000000000..5e9695c55 Binary files /dev/null and b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/textures/gui/portable_grid.png differ diff --git a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/ClientModInitializerImpl.java b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/ClientModInitializerImpl.java index 9ca328ff4..15a13e0d4 100644 --- a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/ClientModInitializerImpl.java +++ b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/ClientModInitializerImpl.java @@ -22,7 +22,7 @@ import com.refinedmods.refinedstorage2.platform.common.upgrade.UpgradeDestinationClientTooltipComponent; import com.refinedmods.refinedstorage2.platform.fabric.mixin.ItemPropertiesAccessor; import com.refinedmods.refinedstorage2.platform.fabric.packet.PacketIds; -import com.refinedmods.refinedstorage2.platform.fabric.packet.s2c.ControllerEnergyInfoPacket; +import com.refinedmods.refinedstorage2.platform.fabric.packet.s2c.EnergyInfoPacket; import com.refinedmods.refinedstorage2.platform.fabric.packet.s2c.GridActivePacket; import com.refinedmods.refinedstorage2.platform.fabric.packet.s2c.GridClearPacket; import com.refinedmods.refinedstorage2.platform.fabric.packet.s2c.GridUpdatePacket; @@ -273,7 +273,7 @@ private void registerPackets() { ClientPlayNetworking.registerGlobalReceiver(PacketIds.GRID_UPDATE, new GridUpdatePacket()); ClientPlayNetworking.registerGlobalReceiver(PacketIds.GRID_CLEAR, new GridClearPacket()); ClientPlayNetworking.registerGlobalReceiver(PacketIds.GRID_ACTIVE, new GridActivePacket()); - ClientPlayNetworking.registerGlobalReceiver(PacketIds.CONTROLLER_ENERGY_INFO, new ControllerEnergyInfoPacket()); + ClientPlayNetworking.registerGlobalReceiver(PacketIds.ENERGY_INFO, new EnergyInfoPacket()); ClientPlayNetworking.registerGlobalReceiver( PacketIds.WIRELESS_TRANSMITTER_RANGE, new WirelessTransmitterRangePacket() diff --git a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/ConfigImpl.java b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/ConfigImpl.java index df268b19a..d6d95a1c5 100644 --- a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/ConfigImpl.java +++ b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/ConfigImpl.java @@ -85,6 +85,9 @@ public class ConfigImpl implements ConfigData, com.refinedmods.refinedstorage2.p DefaultEnergyUsage.NETWORK_TRANSMITTER ); + @ConfigEntry.Gui.CollapsibleObject + private PortableGridEntryImpl portableGrid = new PortableGridEntryImpl(); + public static ConfigImpl get() { return AutoConfig.getConfigHolder(ConfigImpl.class).getConfig(); } @@ -189,6 +192,11 @@ public SimpleEnergyUsageEntry getNetworkTransmitter() { return networkTransmitter; } + @Override + public PortableGridEntry getPortableGrid() { + return portableGrid; + } + private static class GridEntryImpl implements GridEntry { private boolean largeFont = false; @@ -578,4 +586,34 @@ public int getBaseRange() { return baseRange; } } + + private static class PortableGridEntryImpl implements PortableGridEntry { + private long energyCapacity = DefaultEnergyUsage.PORTABLE_GRID_CAPACITY; + + private long openEnergyUsage = DefaultEnergyUsage.PORTABLE_GRID_OPEN; + + private long insertEnergyUsage = DefaultEnergyUsage.PORTABLE_GRID_INSERT; + + private long extractEnergyUsage = DefaultEnergyUsage.PORTABLE_GRID_EXTRACT; + + @Override + public long getEnergyCapacity() { + return energyCapacity; + } + + @Override + public long getOpenEnergyUsage() { + return openEnergyUsage; + } + + @Override + public long getInsertEnergyUsage() { + return insertEnergyUsage; + } + + @Override + public long getExtractEnergyUsage() { + return extractEnergyUsage; + } + } } diff --git a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/PacketIds.java b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/PacketIds.java index 0484186f9..bb84ba954 100644 --- a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/PacketIds.java +++ b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/PacketIds.java @@ -7,7 +7,7 @@ public final class PacketIds { public static final ResourceLocation STORAGE_INFO_RESPONSE = createIdentifier("storage_info_response"); public static final ResourceLocation STORAGE_INFO_REQUEST = createIdentifier("storage_info_request"); - public static final ResourceLocation CONTROLLER_ENERGY_INFO = createIdentifier("controller_energy"); + public static final ResourceLocation ENERGY_INFO = createIdentifier("controller_energy"); public static final ResourceLocation WIRELESS_TRANSMITTER_RANGE = createIdentifier("wireless_transmitter_range"); public static final ResourceLocation GRID_ACTIVE = createIdentifier("grid_active"); public static final ResourceLocation GRID_UPDATE = createIdentifier("grid_update"); diff --git a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/ControllerEnergyInfoPacket.java b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/EnergyInfoPacket.java similarity index 68% rename from refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/ControllerEnergyInfoPacket.java rename to refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/EnergyInfoPacket.java index 5ea8ef168..f7e890587 100644 --- a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/ControllerEnergyInfoPacket.java +++ b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/EnergyInfoPacket.java @@ -1,6 +1,6 @@ package com.refinedmods.refinedstorage2.platform.fabric.packet.s2c; -import com.refinedmods.refinedstorage2.platform.common.controller.ControllerContainerMenu; +import com.refinedmods.refinedstorage2.platform.common.support.energy.EnergyContainerMenu; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PacketSender; @@ -8,7 +8,7 @@ import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.network.FriendlyByteBuf; -public class ControllerEnergyInfoPacket implements ClientPlayNetworking.PlayChannelHandler { +public class EnergyInfoPacket implements ClientPlayNetworking.PlayChannelHandler { @Override public void receive(final Minecraft client, final ClientPacketListener handler, @@ -18,8 +18,8 @@ public void receive(final Minecraft client, final long capacity = buf.readLong(); client.execute(() -> { - if (client.player.containerMenu instanceof ControllerContainerMenu controller) { - controller.setEnergyInfo(stored, capacity); + if (client.player.containerMenu instanceof EnergyContainerMenu energyContainer) { + energyContainer.getEnergyInfo().setEnergy(stored, capacity); } }); } diff --git a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/ServerToClientCommunicationsImpl.java b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/ServerToClientCommunicationsImpl.java index e0769e543..dcc73b274 100644 --- a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/ServerToClientCommunicationsImpl.java +++ b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/packet/s2c/ServerToClientCommunicationsImpl.java @@ -22,8 +22,8 @@ public class ServerToClientCommunicationsImpl implements ServerToClientCommunications { @Override - public void sendControllerEnergyInfo(final ServerPlayer player, final long stored, final long capacity) { - sendToPlayer(player, PacketIds.CONTROLLER_ENERGY_INFO, buf -> { + public void sendEnergyInfo(final ServerPlayer player, final long stored, final long capacity) { + sendToPlayer(player, PacketIds.ENERGY_INFO, buf -> { buf.writeLong(stored); buf.writeLong(capacity); }); diff --git a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/storage/diskdrive/DiskDriveBakedModel.java b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/storage/diskdrive/DiskDriveBakedModel.java index 36ed45695..c88e9823a 100644 --- a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/storage/diskdrive/DiskDriveBakedModel.java +++ b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/storage/diskdrive/DiskDriveBakedModel.java @@ -1,6 +1,6 @@ package com.refinedmods.refinedstorage2.platform.fabric.storage.diskdrive; -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.refinedmods.refinedstorage2.platform.common.storage.diskdrive.AbstractDiskDriveBlockEntity; import com.refinedmods.refinedstorage2.platform.common.storage.diskdrive.DiskDriveBlock; @@ -26,24 +26,10 @@ import net.minecraft.world.level.block.state.BlockState; class DiskDriveBakedModel extends ForwardingBakedModel { - private static final QuadTranslator[] TRANSLATORS = new QuadTranslator[8]; - - static { - int i = 0; - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 2; ++x) { - TRANSLATORS[i++] = new QuadTranslator( - x == 0 ? -(2F / 16F) : -(9F / 16F), - -((y * 3F) / 16F) - (2F / 16F), - 0 - ); - } - } - } - private final Map diskModels; private final BakedModel inactiveLedModel; private final QuadRotators quadRotators; + private final QuadTranslator[] diskTranslations = new QuadTranslator[8]; DiskDriveBakedModel(final BakedModel baseModel, final Map diskModels, @@ -53,6 +39,16 @@ class DiskDriveBakedModel extends ForwardingBakedModel { this.diskModels = diskModels; this.inactiveLedModel = inactiveLedModel; this.quadRotators = quadRotators; + int i = 0; + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 2; ++x) { + diskTranslations[i++] = new QuadTranslator( + x == 0 ? -(2F / 16F) : -(9F / 16F), + -((y * 3F) / 16F) - (2F / 16F), + 0 + ); + } + } } @Override @@ -69,7 +65,7 @@ public void emitItemQuads(final ItemStack stack, if (tag == null) { return; } - for (int i = 0; i < TRANSLATORS.length; ++i) { + for (int i = 0; i < diskTranslations.length; ++i) { final Item diskItem = AbstractDiskDriveBlockEntity.getDisk(tag, i); emitDiskQuads(stack, randomSupplier, context, diskItem, i); } @@ -105,7 +101,7 @@ private void emitDiskQuads(final BlockAndTintGetter blockView, final Supplier randomSupplier, final RenderContext context, final Disk[] disks) { - for (int i = 0; i < TRANSLATORS.length; ++i) { + for (int i = 0; i < diskTranslations.length; ++i) { final Disk disk = disks[i]; emitDiskQuads(blockView, state, pos, randomSupplier, context, disk, i); } @@ -125,7 +121,7 @@ private void emitDiskQuads(final BlockAndTintGetter blockView, if (model == null) { return; } - context.pushTransform(TRANSLATORS[index]); + context.pushTransform(diskTranslations[index]); model.emitBlockQuads(blockView, state, pos, randomSupplier, context); context.popTransform(); } @@ -143,7 +139,7 @@ private void emitDiskQuads(final ItemStack stack, if (diskModel == null) { return; } - context.pushTransform(TRANSLATORS[index]); + context.pushTransform(diskTranslations[index]); diskModel.emitItemQuads(stack, randomSupplier, context); inactiveLedModel.emitItemQuads(stack, randomSupplier, context); context.popTransform(); diff --git a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/storage/portablegrid/PortableGridBakedModel.java b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/storage/portablegrid/PortableGridBakedModel.java index 181d856a8..1fab9829e 100644 --- a/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/storage/portablegrid/PortableGridBakedModel.java +++ b/refinedstorage2-platform-fabric/src/main/java/com/refinedmods/refinedstorage2/platform/fabric/storage/portablegrid/PortableGridBakedModel.java @@ -1,7 +1,6 @@ package com.refinedmods.refinedstorage2.platform.fabric.storage.portablegrid; -import com.refinedmods.refinedstorage2.platform.common.content.Items; -import com.refinedmods.refinedstorage2.platform.common.storage.ItemStorageType; +import com.refinedmods.refinedstorage2.platform.common.storage.Disk; import com.refinedmods.refinedstorage2.platform.common.storage.portablegrid.PortableGridBlock; import com.refinedmods.refinedstorage2.platform.common.support.direction.BiDirection; import com.refinedmods.refinedstorage2.platform.fabric.support.render.QuadRotators; @@ -12,6 +11,7 @@ import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; import net.minecraft.util.RandomSource; @@ -65,13 +65,33 @@ public void emitBlockQuads(final BlockAndTintGetter blockView, return; } context.pushTransform(quadRotators.forDirection(direction)); + if (blockView instanceof RenderAttachedBlockView renderAttachedBlockView) { + final Object renderAttachment = renderAttachedBlockView.getBlockEntityRenderAttachment(pos); + if (renderAttachment instanceof Disk disk) { + emitDiskQuads(blockView, state, pos, randomSupplier, context, disk); + } + } + final boolean active = state.getValue(PortableGridBlock.ACTIVE); + (active ? activeModel : inactiveModel).emitBlockQuads(blockView, state, pos, randomSupplier, context); + context.popTransform(); + } + + private void emitDiskQuads( + final BlockAndTintGetter blockView, + final BlockState state, + final BlockPos pos, + final Supplier randomSupplier, + final RenderContext context, + final Disk disk + ) { + final BakedModel diskModel = diskModels.get(disk.item()); + if (diskModel == null) { + return; + } context.pushTransform(MOVE_TO_DISK_LOCATION); context.pushTransform(quadRotators.forDirection(BiDirection.WEST)); - diskModels.get(Items.INSTANCE.getItemStorageDisk(ItemStorageType.Variant.ONE_K)) - .emitBlockQuads(blockView, state, pos, randomSupplier, context); - context.popTransform(); + diskModel.emitBlockQuads(blockView, state, pos, randomSupplier, context); context.popTransform(); - inactiveModel.emitBlockQuads(blockView, state, pos, randomSupplier, context); context.popTransform(); } } diff --git a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/ConfigImpl.java b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/ConfigImpl.java index d7a1309fa..3d4344c94 100644 --- a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/ConfigImpl.java +++ b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/ConfigImpl.java @@ -14,6 +14,7 @@ public class ConfigImpl implements Config { private static final String ENERGY_USAGE = "energyUsage"; + private static final String ENERGY_CAPACITY = "energyCapacity"; private final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); private final ForgeConfigSpec spec; @@ -38,6 +39,7 @@ public class ConfigImpl implements Config { private final SimpleEnergyUsageEntry storageMonitor; private final SimpleEnergyUsageEntry networkReceiver; private final SimpleEnergyUsageEntry networkTransmitter; + private final PortableGridEntry portableGrid; public ConfigImpl() { cable = new SimpleEnergyUsageEntryImpl("cable", "Cable", DefaultEnergyUsage.CABLE); @@ -76,6 +78,7 @@ public ConfigImpl() { "Network Transmitter", DefaultEnergyUsage.NETWORK_TRANSMITTER ); + portableGrid = new PortableGridEntryImpl(); spec = builder.build(); } @@ -183,6 +186,11 @@ public SimpleEnergyUsageEntry getNetworkTransmitter() { return networkTransmitter; } + @Override + public PortableGridEntry getPortableGrid() { + return portableGrid; + } + private class SimpleEnergyUsageEntryImpl implements SimpleEnergyUsageEntry { private final ForgeConfigSpec.LongValue energyUsage; @@ -206,7 +214,7 @@ private class ControllerEntryImpl implements ControllerEntry { private ControllerEntryImpl() { builder.push("controller"); energyCapacity = builder.comment("The energy capacity of the Controller") - .defineInRange("energyCapacity", DefaultEnergyUsage.CONTROLLER_CAPACITY, 0, Long.MAX_VALUE); + .defineInRange(ENERGY_CAPACITY, DefaultEnergyUsage.CONTROLLER_CAPACITY, 0, Long.MAX_VALUE); builder.pop(); } @@ -680,7 +688,7 @@ private class WirelessGridEntryImpl implements WirelessGridEntry { WirelessGridEntryImpl() { builder.push("wirelessGrid"); energyCapacity = builder.comment("The energy capacity of the Wireless Grid") - .defineInRange("energyCapacity", DefaultEnergyUsage.WIRELESS_GRID_CAPACITY, 0, Long.MAX_VALUE); + .defineInRange(ENERGY_CAPACITY, DefaultEnergyUsage.WIRELESS_GRID_CAPACITY, 0, Long.MAX_VALUE); openEnergyUsage = builder.comment("The energy used by the Wireless Grid to open") .defineInRange("openEnergyUsage", DefaultEnergyUsage.WIRELESS_GRID_OPEN, 0, Long.MAX_VALUE); extractEnergyUsage = builder.comment("The energy used by the Wireless Grid to extract resources") @@ -730,4 +738,40 @@ public int getBaseRange() { return baseRange.get(); } } + + private class PortableGridEntryImpl implements PortableGridEntry { + private final ForgeConfigSpec.LongValue energyCapacity; + private final ForgeConfigSpec.LongValue openEnergyUsage; + private final ForgeConfigSpec.LongValue extractEnergyUsage; + private final ForgeConfigSpec.LongValue insertEnergyUsage; + + PortableGridEntryImpl() { + builder.push("portableGrid"); + energyCapacity = builder.comment("The energy capacity of the Portable Grid") + .defineInRange(ENERGY_CAPACITY, DefaultEnergyUsage.PORTABLE_GRID_CAPACITY, 0, Long.MAX_VALUE); + openEnergyUsage = builder.comment("The energy used by the Portable Grid to open") + .defineInRange("openEnergyUsage", DefaultEnergyUsage.PORTABLE_GRID_OPEN, 0, Long.MAX_VALUE); + extractEnergyUsage = builder.comment("The energy used by the Portable Grid to extract resources") + .defineInRange("extractEnergyUsage", DefaultEnergyUsage.PORTABLE_GRID_EXTRACT, 0, Long.MAX_VALUE); + insertEnergyUsage = builder.comment("The energy used by the Portable Grid to insert resources") + .defineInRange("insertEnergyUsage", DefaultEnergyUsage.PORTABLE_GRID_INSERT, 0, Long.MAX_VALUE); + builder.pop(); + } + + public long getEnergyCapacity() { + return energyCapacity.get(); + } + + public long getOpenEnergyUsage() { + return openEnergyUsage.get(); + } + + public long getExtractEnergyUsage() { + return extractEnergyUsage.get(); + } + + public long getInsertEnergyUsage() { + return insertEnergyUsage.get(); + } + } } diff --git a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/NetworkManager.java b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/NetworkManager.java index 90d63b97d..c6aa77220 100644 --- a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/NetworkManager.java +++ b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/NetworkManager.java @@ -12,7 +12,7 @@ import com.refinedmods.refinedstorage2.platform.forge.packet.c2s.SingleAmountChangePacket; import com.refinedmods.refinedstorage2.platform.forge.packet.c2s.StorageInfoRequestPacket; import com.refinedmods.refinedstorage2.platform.forge.packet.c2s.UseNetworkBoundItemPacket; -import com.refinedmods.refinedstorage2.platform.forge.packet.s2c.ControllerEnergyInfoPacket; +import com.refinedmods.refinedstorage2.platform.forge.packet.s2c.EnergyInfoPacket; import com.refinedmods.refinedstorage2.platform.forge.packet.s2c.GridActivePacket; import com.refinedmods.refinedstorage2.platform.forge.packet.s2c.GridClearPacket; import com.refinedmods.refinedstorage2.platform.forge.packet.s2c.GridUpdatePacket; @@ -44,10 +44,10 @@ public NetworkManager() { int id = 0; handler.registerMessage( id++, - ControllerEnergyInfoPacket.class, - ControllerEnergyInfoPacket::encode, - ControllerEnergyInfoPacket::decode, - ControllerEnergyInfoPacket::handle + EnergyInfoPacket.class, + EnergyInfoPacket::encode, + EnergyInfoPacket::decode, + EnergyInfoPacket::handle ); handler.registerMessage( id++, diff --git a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/ControllerEnergyInfoPacket.java b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/ControllerEnergyInfoPacket.java deleted file mode 100644 index 4dd6e0bce..000000000 --- a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/ControllerEnergyInfoPacket.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.refinedmods.refinedstorage2.platform.forge.packet.s2c; - -import com.refinedmods.refinedstorage2.platform.common.controller.ControllerContainerMenu; - -import java.util.function.Supplier; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraftforge.network.NetworkEvent; - -public class ControllerEnergyInfoPacket { - private final long stored; - private final long capacity; - - public ControllerEnergyInfoPacket(final long stored, final long capacity) { - this.stored = stored; - this.capacity = capacity; - } - - public static ControllerEnergyInfoPacket decode(final FriendlyByteBuf buf) { - return new ControllerEnergyInfoPacket(buf.readLong(), buf.readLong()); - } - - public static void encode(final ControllerEnergyInfoPacket packet, final FriendlyByteBuf buf) { - buf.writeLong(packet.stored); - buf.writeLong(packet.capacity); - } - - public static void handle(final ControllerEnergyInfoPacket packet, final Supplier ctx) { - ctx.get().enqueueWork(() -> ClientProxy.getPlayer().ifPresent(player -> handle(player, packet))); - ctx.get().setPacketHandled(true); - } - - private static void handle(final Player player, final ControllerEnergyInfoPacket packet) { - final AbstractContainerMenu menu = player.containerMenu; - if (menu instanceof ControllerContainerMenu controller) { - controller.setEnergyInfo(packet.stored, packet.capacity); - } - } -} diff --git a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/EnergyInfoPacket.java b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/EnergyInfoPacket.java new file mode 100644 index 000000000..f51476e95 --- /dev/null +++ b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/EnergyInfoPacket.java @@ -0,0 +1,41 @@ +package com.refinedmods.refinedstorage2.platform.forge.packet.s2c; + +import com.refinedmods.refinedstorage2.platform.common.support.energy.EnergyContainerMenu; + +import java.util.function.Supplier; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraftforge.network.NetworkEvent; + +public class EnergyInfoPacket { + private final long stored; + private final long capacity; + + public EnergyInfoPacket(final long stored, final long capacity) { + this.stored = stored; + this.capacity = capacity; + } + + public static EnergyInfoPacket decode(final FriendlyByteBuf buf) { + return new EnergyInfoPacket(buf.readLong(), buf.readLong()); + } + + public static void encode(final EnergyInfoPacket packet, final FriendlyByteBuf buf) { + buf.writeLong(packet.stored); + buf.writeLong(packet.capacity); + } + + public static void handle(final EnergyInfoPacket packet, final Supplier ctx) { + ctx.get().enqueueWork(() -> ClientProxy.getPlayer().ifPresent(player -> handle(player, packet))); + ctx.get().setPacketHandled(true); + } + + private static void handle(final Player player, final EnergyInfoPacket packet) { + final AbstractContainerMenu menu = player.containerMenu; + if (menu instanceof EnergyContainerMenu energy) { + energy.getEnergyInfo().setEnergy(packet.stored, packet.capacity); + } + } +} diff --git a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/ServerToClientCommunicationsImpl.java b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/ServerToClientCommunicationsImpl.java index 6c05e45f3..66a23a460 100644 --- a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/ServerToClientCommunicationsImpl.java +++ b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/packet/s2c/ServerToClientCommunicationsImpl.java @@ -22,8 +22,8 @@ public ServerToClientCommunicationsImpl(final NetworkManager networkManager) { } @Override - public void sendControllerEnergyInfo(final ServerPlayer player, final long stored, final long capacity) { - networkManager.send(player, new ControllerEnergyInfoPacket(stored, capacity)); + public void sendEnergyInfo(final ServerPlayer player, final long stored, final long capacity) { + networkManager.send(player, new EnergyInfoPacket(stored, capacity)); } @Override diff --git a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/diskdrive/DiskDriveBakedModel.java b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/diskdrive/DiskDriveBakedModel.java index 9918af879..0ab217024 100644 --- a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/diskdrive/DiskDriveBakedModel.java +++ b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/diskdrive/DiskDriveBakedModel.java @@ -1,6 +1,6 @@ package com.refinedmods.refinedstorage2.platform.forge.storage.diskdrive; -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.refinedmods.refinedstorage2.platform.common.storage.diskdrive.AbstractDiskDriveBlockEntity; import com.refinedmods.refinedstorage2.platform.common.storage.diskdrive.DiskDriveBlock; diff --git a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/diskdrive/ForgeDiskDriveBlockEntity.java b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/diskdrive/ForgeDiskDriveBlockEntity.java index 50dade2cd..427d5ec76 100644 --- a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/diskdrive/ForgeDiskDriveBlockEntity.java +++ b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/diskdrive/ForgeDiskDriveBlockEntity.java @@ -18,9 +18,9 @@ public ForgeDiskDriveBlockEntity(final BlockPos pos, final BlockState state) { } @Override - protected void onDriveStateUpdated() { + protected void onClientDriveStateUpdated() { requestModelDataUpdate(); - super.onDriveStateUpdated(); + super.onClientDriveStateUpdated(); } @Nonnull diff --git a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/portablegrid/ForgePortableGridBlockEntity.java b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/portablegrid/ForgePortableGridBlockEntity.java index d0033bb30..fba568027 100644 --- a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/portablegrid/ForgePortableGridBlockEntity.java +++ b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/portablegrid/ForgePortableGridBlockEntity.java @@ -19,9 +19,9 @@ public ForgePortableGridBlockEntity(final PortableGridType type, final BlockPos } @Override - protected void onDriveStateUpdated() { + protected void onClientDriveStateUpdated() { requestModelDataUpdate(); - super.onDriveStateUpdated(); + super.onClientDriveStateUpdated(); } @Nonnull diff --git a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/portablegrid/PortableGridBakedModel.java b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/portablegrid/PortableGridBakedModel.java index e307c8db3..acdb86400 100644 --- a/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/portablegrid/PortableGridBakedModel.java +++ b/refinedstorage2-platform-forge/src/main/java/com/refinedmods/refinedstorage2/platform/forge/storage/portablegrid/PortableGridBakedModel.java @@ -1,6 +1,6 @@ package com.refinedmods.refinedstorage2.platform.forge.storage.portablegrid; -import com.refinedmods.refinedstorage2.api.network.impl.node.StorageState; +import com.refinedmods.refinedstorage2.api.storage.StorageState; import com.refinedmods.refinedstorage2.platform.common.content.Items; import com.refinedmods.refinedstorage2.platform.common.storage.Disk; import com.refinedmods.refinedstorage2.platform.common.storage.FluidStorageType; @@ -83,7 +83,8 @@ public List getQuads(@Nullable final BlockState state, if (disk == null) { return super.getQuads(state, side, randomSource); } - return cache.getUnchecked(new CacheKey(side, direction, true, disk)); + final boolean active = state.getValue(PortableGridBlock.ACTIVE); + return cache.getUnchecked(new CacheKey(side, direction, active, disk)); } @Override diff --git a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageInternalStorage.java b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java similarity index 55% rename from refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageInternalStorage.java rename to refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java index 2d25d90fd..980d7dd4d 100644 --- a/refinedstorage2-network/src/main/java/com/refinedmods/refinedstorage2/api/network/impl/node/multistorage/MultiStorageInternalStorage.java +++ b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java @@ -1,11 +1,8 @@ -package com.refinedmods.refinedstorage2.api.network.impl.node.multistorage; +package com.refinedmods.refinedstorage2.api.storage; import com.refinedmods.refinedstorage2.api.core.Action; -import com.refinedmods.refinedstorage2.api.network.impl.node.StorageState; import com.refinedmods.refinedstorage2.api.resource.ResourceAmount; -import com.refinedmods.refinedstorage2.api.storage.Actor; -import com.refinedmods.refinedstorage2.api.storage.Storage; -import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType; +import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorage; import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedResource; import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedStorage; @@ -13,32 +10,43 @@ import java.util.Optional; import javax.annotation.Nullable; -public class MultiStorageInternalStorage 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,19 @@ public Optional findTrackedResourceByActorType(final T resource ? trackedStorage.findTrackedResourceByActorType(resource, actorType) : Optional.empty(); } + + public static TypedStorage> of( + final TypedStorage> delegate, + @Nullable final Listener listener + ) { + return new TypedStorage<>( + new StateTrackedStorage<>(delegate.storage(), listener), + delegate.storageChannelType() + ); + } + + @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..4815bcc67 --- /dev/null +++ b/refinedstorage2-storage-api/src/test/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorageTest.java @@ -0,0 +1,172 @@ +package com.refinedmods.refinedstorage2.api.storage; + +import com.refinedmods.refinedstorage2.api.core.Action; +import com.refinedmods.refinedstorage2.api.resource.ResourceAmount; +import com.refinedmods.refinedstorage2.api.storage.limited.LimitedStorageImpl; +import com.refinedmods.refinedstorage2.api.storage.tracked.TrackedStorageImpl; + +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; +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 { + @ParameterizedTest + @MethodSource("states") + void testStates(final long amount, final StorageState expectedState) { + // Arrange + final StateTrackedStorage.Listener listener = mock(StateTrackedStorage.Listener.class); + final Storage underlyingStorage = new LimitedStorageImpl<>(100); + underlyingStorage.insert("A", amount, Action.EXECUTE, EmptyActor.INSTANCE); + final StateTrackedStorage sut = new StateTrackedStorage<>(underlyingStorage, listener); + + // Act + final StorageState state = sut.getState(); + + // Assert + assertThat(state).isEqualTo(expectedState); + } + + private static Stream states() { + return Stream.of( + Arguments.of(1L, StorageState.NORMAL), + Arguments.of(74L, StorageState.NORMAL), + Arguments.of(75L, StorageState.NEAR_CAPACITY), + Arguments.of(99L, StorageState.NEAR_CAPACITY), + Arguments.of(100L, StorageState.FULL) + ); + } + + @Test + void shouldSetInitialState() { + // Arrange + final StateTrackedStorage.Listener listener = mock(StateTrackedStorage.Listener.class); + final Storage underlyingStorage = new InMemoryStorageImpl<>(); + 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.NORMAL); + assertThat(sut.getAll()).usingRecursiveFieldByFieldElementComparator().containsExactly( + new ResourceAmount<>("A", 75) + ); + assertThat(sut.getStored()).isEqualTo(75); + } + + + @Test + void shouldSetInitialStateForLimitedStorage() { + // 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 + final long extracted = sut.extract("A", 1, action, EmptyActor.INSTANCE); + sut.extract("A", 1, action, EmptyActor.INSTANCE); + + // Assert + assertThat(extracted).isEqualTo(1); + 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 + final long inserted = sut.insert("A", 1, action, EmptyActor.INSTANCE); + sut.insert("A", 1, action, EmptyActor.INSTANCE); + + // Assert + assertThat(inserted).isEqualTo(1); + 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(); + } +}