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 222bc3a8e..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 @@ -97,7 +97,7 @@ private Set initializeStorage(final int index) { if (provider != null) { provider.resolve(index).ifPresentOrElse(resolved -> { - cache[index] = (TypedStorage) trackState(resolved); + 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); @@ -106,13 +106,6 @@ private Set initializeStorage(final int index) { return results; } - private TypedStorage> trackState(final TypedStorage> resolved) { - return new TypedStorage<>( - new StateTrackedStorage<>(resolved.storage(), listener), - resolved.storageChannelType() - ); - } - @SuppressWarnings({"unchecked", "rawtypes"}) private void processStorageChange(final StorageChange change) { if (!isActive()) { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java index 000a9c18a..f08864058 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/DiskInventory.java @@ -2,17 +2,25 @@ 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; @@ -64,6 +72,42 @@ private Optional validateAndGetStack(final int slot) { 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/diskdrive/AbstractDiskDriveBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/diskdrive/AbstractDiskDriveBlockEntity.java index 5355441a2..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,14 +1,13 @@ package com.refinedmods.refinedstorage2.platform.common.storage.diskdrive; import com.refinedmods.refinedstorage2.api.network.impl.node.multistorage.MultiStorageNetworkNode; -import com.refinedmods.refinedstorage2.api.storage.StateTrackedStorage; -import com.refinedmods.refinedstorage2.api.storage.StorageState; import com.refinedmods.refinedstorage2.platform.api.PlatformApi; import com.refinedmods.refinedstorage2.platform.common.Platform; import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities; import com.refinedmods.refinedstorage2.platform.common.content.ContentNames; import com.refinedmods.refinedstorage2.platform.common.storage.Disk; import com.refinedmods.refinedstorage2.platform.common.storage.DiskInventory; +import com.refinedmods.refinedstorage2.platform.common.storage.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; @@ -20,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; @@ -40,22 +36,15 @@ 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, StateTrackedStorage.Listener, 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; @@ -63,9 +52,7 @@ public abstract class AbstractDiskDriveBlockEntity 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( @@ -87,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()); } @@ -105,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 @@ -156,7 +130,7 @@ private void initialize(final Level level) { @Override public void activenessChanged(final boolean newActive) { super.activenessChanged(newActive); - updateBlock(); + diskStateListener.immediateUpdate(); } @Override @@ -201,50 +175,28 @@ private void onDiskChanged(final int slot) { return; } getNode().onStorageChanged(slot); - updateBlock(); + diskStateListener.immediateUpdate(); setChanged(); } - @Override - public void onStorageStateChanged() { - 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)); - } + disks = diskInventory.fromSyncTag(tag.getList(TAG_DISKS, Tag.TAG_COMPOUND)); onClientDriveStateUpdated(); } protected void onClientDriveStateUpdated() { - updateBlock(); - } - - 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]; + diskStateListener.immediateUpdate(); } @Override @@ -253,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/portablegrid/AbstractPortableGridBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/storage/portablegrid/AbstractPortableGridBlockEntity.java index 6d15a3643..b2da70424 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 @@ -8,20 +8,22 @@ 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.grid.Grid; import com.refinedmods.refinedstorage2.platform.api.storage.channel.PlatformStorageChannelType; import com.refinedmods.refinedstorage2.platform.api.support.resource.ItemResource; import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities; import com.refinedmods.refinedstorage2.platform.common.content.ContentNames; -import com.refinedmods.refinedstorage2.platform.common.content.Items; import com.refinedmods.refinedstorage2.platform.common.grid.AbstractGridContainerMenu; import com.refinedmods.refinedstorage2.platform.common.storage.Disk; import com.refinedmods.refinedstorage2.platform.common.storage.DiskInventory; -import com.refinedmods.refinedstorage2.platform.common.storage.ItemStorageType; +import com.refinedmods.refinedstorage2.platform.common.storage.DiskStateChangeListener; import com.refinedmods.refinedstorage2.platform.common.util.ContainerUtil; import java.util.Collections; @@ -30,49 +32,100 @@ import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; 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.world.MenuProvider; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.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; public abstract class AbstractPortableGridBlockEntity extends BlockEntity implements Grid, MenuProvider { private static final String TAG_DISK_INVENTORY = "inv"; + private static final String TAG_DISKS = "disks"; @Nullable - protected Disk disk = new Disk( - Items.INSTANCE.getItemStorageDisk(ItemStorageType.Variant.ONE_K), - StorageState.NEAR_CAPACITY - ); + protected Disk disk; + private final DiskInventory diskInventory; + private final DiskStateChangeListener diskStateListener = new DiskStateChangeListener(this); + @Nullable + 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); } + void updateDiskStateIfNecessaryInLevel() { + diskStateListener.updateIfNecessary(); + } + private void onDiskChanged(final int slot) { - // Level will not yet be present final boolean isJustPlacedIntoLevelOrLoading = level == null || level.isClientSide(); if (isJustPlacedIntoLevelOrLoading) { return; } - updateBlock(); + 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); } super.load(tag); } + 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); @@ -80,13 +133,29 @@ public void saveAdditional(final CompoundTag tag) { } @Override - public void addWatcher(final GridWatcher watcher, final Class actorType) { + public Packet getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + @Override + public CompoundTag getUpdateTag() { + final CompoundTag tag = new CompoundTag(); + tag.put(TAG_DISKS, diskInventory.toSyncTag(idx -> getState())); + return tag; + } + + private StorageState getState() { + return storage != null ? storage.storage().getState() : StorageState.NONE; } @Override - public void removeWatcher(final GridWatcher watcher) { + public void addWatcher(final GridWatcher watcher, final Class actorType) { + // TODO + } + @Override + public void removeWatcher(final GridWatcher watcher) { + // TODO } @Override @@ -96,18 +165,23 @@ public Storage getItemStorage() { @Override public boolean isGridActive() { + // TODO: add energy component + // TODO: sync activeness to block state + // TODO: energy level in GUI return true; } @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, @@ -138,17 +212,6 @@ public SimpleContainer getDiskInventory() { return diskInventory; } - protected void onClientDriveStateUpdated() { - updateBlock(); - } - - private void updateBlock() { - if (level == null) { - return; - } - level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), Block.UPDATE_ALL); - } - private static BlockEntityType getBlockEntityType(final PortableGridType type) { return type == PortableGridType.CREATIVE ? BlockEntities.INSTANCE.getCreativePortableGrid() 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 e933ac388..cfe7a58bc 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 @@ -3,6 +3,7 @@ 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.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; @@ -16,6 +17,8 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; @@ -27,13 +30,15 @@ public class PortableGridBlock extends AbstractDirectionalBlock imp 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; } @@ -67,7 +72,14 @@ public BlockEntity newBlockEntity(final BlockPos blockPos, final BlockState bloc } @Override - @SuppressWarnings("deprecation") + public BlockEntityTicker getTicker(final Level level, + final BlockState state, + final BlockEntityType type) { + return ticker.get(level, type); + } + + @Override + @SuppressWarnings("deprecation") // Forge deprecates this 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) { 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..d7e29d843 --- /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.updateDiskStateIfNecessaryInLevel(); + } +} 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-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 9eaf264f0..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 @@ -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..f0e660c6a 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,32 @@ 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); + } + } + 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); + diskModel.emitBlockQuads(blockView, state, pos, randomSupplier, context); context.popTransform(); context.popTransform(); - inactiveModel.emitBlockQuads(blockView, state, pos, randomSupplier, context); - context.popTransform(); } } diff --git a/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java index ce20a0b2b..980d7dd4d 100644 --- a/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java +++ b/refinedstorage2-storage-api/src/main/java/com/refinedmods/refinedstorage2/api/storage/StateTrackedStorage.java @@ -95,6 +95,16 @@ public Optional findTrackedResourceByActorType(final T resource : 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();