From 36e1ac0ec57e98870526a16b87a52fa4e1bdc6a2 Mon Sep 17 00:00:00 2001 From: Raoul Van den Berge Date: Tue, 31 Oct 2023 09:53:40 +0100 Subject: [PATCH 1/3] fix: cleanup some storage monitor code --- .../common/block/StorageMonitorBlock.java | 23 +++++++++++++------ .../StorageMonitorBlockEntity.java | 17 +++++++++----- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/StorageMonitorBlock.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/StorageMonitorBlock.java index 74a6fef2f..16f02315f 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/StorageMonitorBlock.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/StorageMonitorBlock.java @@ -11,6 +11,7 @@ import javax.annotation.Nullable; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; @@ -29,7 +30,7 @@ public class StorageMonitorBlock extends AbstractDirectionalBlock i new NetworkNodeBlockEntityTicker<>(BlockEntities.INSTANCE::getStorageMonitor); public StorageMonitorBlock() { - super(BlockConstants.PROPERTIES.strength(1.5F, 6.0F)); + super(BlockConstants.PROPERTIES.strength(2.5F, 6.0F)); } @Override @@ -60,6 +61,10 @@ public InteractionResult use(final BlockState state, if (player.isCrouching()) { return super.use(state, level, pos, player, hand, hit); } + final BiDirection direction = getDirection(state); + if (direction == null || hit.getDirection() != direction.asDirection()) { + return InteractionResult.FAIL; + } if (!level.isClientSide()) { final BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof StorageMonitorBlockEntity storageMonitor) { @@ -83,19 +88,23 @@ public void attack(final BlockState state, final Level level, final BlockPos pos if (direction == null) { return; } + final Direction hitDirection = getHitDirection(level, player); + if (hitDirection != direction.asDirection()) { + return; + } + storageMonitor.extract(player); + } + + private Direction getHitDirection(final Level level, final Player player) { final Vec3 base = player.getEyePosition(1.0F); final Vec3 look = player.getLookAngle(); final Vec3 target = base.add(look.x * 20, look.y * 20, look.z * 20); - final BlockHitResult hitResult = level.clip(new ClipContext( + return level.clip(new ClipContext( base, target, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player - )); - if (hitResult.getDirection() != direction.asDirection()) { - return; - } - storageMonitor.extract(player); + )).getDirection(); } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storagemonitor/StorageMonitorBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storagemonitor/StorageMonitorBlockEntity.java index 21586c41c..2f3c0730c 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storagemonitor/StorageMonitorBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storagemonitor/StorageMonitorBlockEntity.java @@ -64,9 +64,7 @@ public StorageMonitorBlockEntity(final BlockPos pos, final BlockState state) { final ResourceContainer resourceContainer = ResourceContainerImpl.createForFilter(1); this.filter = FilterWithFuzzyMode.create(resourceContainer, () -> { setChanged(); - if (level != null) { - sendDisplayUpdate(level, getAmount(), getNode().isActive()); - } + sendDisplayUpdate(); }); } @@ -139,7 +137,7 @@ private void extract( if (!success) { return; } - sendDisplayUpdate(level, getAmount(), getNode().isActive()); + sendDisplayUpdate(); level.playSound( null, getBlockPos(), @@ -152,7 +150,7 @@ private void extract( public void insert(final Player player, final InteractionHand hand) { if (level != null && doInsert(player, hand)) { - sendDisplayUpdate(level, getAmount(), getNode().isActive()); + sendDisplayUpdate(); } } @@ -308,10 +306,17 @@ public CompoundTag getUpdateTag() { return tag; } + private void sendDisplayUpdate() { + if (level == null) { + return; + } + sendDisplayUpdate(level, getAmount(), getNode().isActive()); + } + private void sendDisplayUpdate(final Level level, final long amount, final boolean active) { currentAmount = amount; currentlyActive = active; level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), Block.UPDATE_ALL); - LOGGER.info("Sending display update for storage monitor {} with amount {}", worldPosition, amount); + LOGGER.debug("Sending display update for storage monitor {} with amount {}", worldPosition, amount); } } From 872885724a47539f5a3cd3c721b2d1a4aac9e706 Mon Sep 17 00:00:00 2001 From: Raoul Van den Berge Date: Tue, 31 Oct 2023 10:24:13 +0100 Subject: [PATCH 2/3] refactor: split up configuration read/writes from unique read/writes --- .../blockentity/ConfigurationCardTarget.java | 12 + ...ternalNetworkNodeContainerBlockEntity.java | 26 +- ...actingNetworkNodeContainerBlockEntity.java | 3 +- ...dulingNetworkNodeContainerBlockEntity.java | 8 +- .../block/entity/ImporterBlockEntity.java | 10 +- .../StorageConfigurationContainerImpl.java | 3 +- .../constructor/ConstructorBlockEntity.java | 8 +- .../destructor/DestructorBlockEntity.java | 8 +- .../entity/detector/DetectorBlockEntity.java | 16 +- .../AbstractDiskDriveBlockEntity.java | 13 +- .../ExternalStorageBlockEntity.java | 339 +++++++++--------- .../entity/iface/InterfaceBlockEntity.java | 12 +- .../AbstractStorageBlockBlockEntity.java | 12 +- .../StorageMonitorBlockEntity.java | 12 +- 14 files changed, 274 insertions(+), 208 deletions(-) create mode 100644 refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/blockentity/ConfigurationCardTarget.java diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/blockentity/ConfigurationCardTarget.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/blockentity/ConfigurationCardTarget.java new file mode 100644 index 000000000..09f7ebc5d --- /dev/null +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/blockentity/ConfigurationCardTarget.java @@ -0,0 +1,12 @@ +package com.refinedmods.refinedstorage2.platform.api.blockentity; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; + +public interface ConfigurationCardTarget { + BlockEntityType getBlockEntityType(); + + void writeConfiguration(CompoundTag tag); + + void readConfiguration(CompoundTag tag); +} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractInternalNetworkNodeContainerBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractInternalNetworkNodeContainerBlockEntity.java index 7c32c3318..474cd4c8c 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractInternalNetworkNodeContainerBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractInternalNetworkNodeContainerBlockEntity.java @@ -3,6 +3,7 @@ import com.refinedmods.refinedstorage2.api.network.component.EnergyNetworkComponent; import com.refinedmods.refinedstorage2.api.network.node.AbstractNetworkNode; import com.refinedmods.refinedstorage2.platform.api.blockentity.AbstractNetworkNodeContainerBlockEntity; +import com.refinedmods.refinedstorage2.platform.api.blockentity.ConfigurationCardTarget; import com.refinedmods.refinedstorage2.platform.common.Platform; import com.refinedmods.refinedstorage2.platform.common.block.AbstractDirectionalBlock; import com.refinedmods.refinedstorage2.platform.common.block.ColorableBlock; @@ -25,7 +26,7 @@ public abstract class AbstractInternalNetworkNodeContainerBlockEntity extends AbstractNetworkNodeContainerBlockEntity - implements PlayerAware { + implements PlayerAware, ConfigurationCardTarget { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractInternalNetworkNodeContainerBlockEntity.class); private static final String TAG_REDSTONE_MODE = "rm"; @@ -56,23 +57,38 @@ && getNode().getNetwork() != null @Override public void saveAdditional(final CompoundTag tag) { super.saveAdditional(tag); - tag.putInt(TAG_REDSTONE_MODE, RedstoneModeSettings.getRedstoneMode(getRedstoneMode())); + writeConfiguration(tag); if (placedByPlayerId != null) { tag.putUUID(TAG_PLACED_BY_PLAYER_ID, placedByPlayerId); } } + @Override + public void writeConfiguration(final CompoundTag tag) { + tag.putInt(TAG_REDSTONE_MODE, RedstoneModeSettings.getRedstoneMode(getRedstoneMode())); + } + @Override public void load(final CompoundTag tag) { super.load(tag); - if (tag.contains(TAG_REDSTONE_MODE)) { - redstoneMode = RedstoneModeSettings.getRedstoneMode(tag.getInt(TAG_REDSTONE_MODE)); - } + readConfiguration(tag); if (tag.hasUUID(TAG_PLACED_BY_PLAYER_ID)) { placedByPlayerId = tag.getUUID(TAG_PLACED_BY_PLAYER_ID); } } + @Override + public void readConfiguration(final CompoundTag tag) { + if (tag.contains(TAG_REDSTONE_MODE)) { + redstoneMode = RedstoneModeSettings.getRedstoneMode(tag.getInt(TAG_REDSTONE_MODE)); + } + } + + @Override + public BlockEntityType getBlockEntityType() { + return getType(); + } + public void updateActiveness(final BlockState state, @Nullable final BooleanProperty activenessProperty) { final boolean newActive = isActive(); diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractLevelInteractingNetworkNodeContainerBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractLevelInteractingNetworkNodeContainerBlockEntity.java index 8c66c1785..a0904f263 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractLevelInteractingNetworkNodeContainerBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractLevelInteractingNetworkNodeContainerBlockEntity.java @@ -14,7 +14,7 @@ public abstract class AbstractLevelInteractingNetworkNodeContainerBlockEntity extends AbstractInternalNetworkNodeContainerBlockEntity { private static final Logger LOGGER = LoggerFactory.getLogger( - AbstractLevelInteractingNetworkNodeContainerBlockEntity.class + AbstractLevelInteractingNetworkNodeContainerBlockEntity.class ); protected AbstractLevelInteractingNetworkNodeContainerBlockEntity( @@ -28,7 +28,6 @@ protected AbstractLevelInteractingNetworkNodeContainerBlockEntity( // used to handle rotations @Override - @SuppressWarnings("deprecation") public void setBlockState(final BlockState newBlockState) { super.setBlockState(newBlockState); if (!(level instanceof ServerLevel serverLevel)) { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractSchedulingNetworkNodeContainerBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractSchedulingNetworkNodeContainerBlockEntity.java index e298d8b87..636538a98 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractSchedulingNetworkNodeContainerBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractSchedulingNetworkNodeContainerBlockEntity.java @@ -43,17 +43,17 @@ protected AbstractSchedulingNetworkNodeContainerBlockEntity( } @Override - public void saveAdditional(final CompoundTag tag) { - super.saveAdditional(tag); + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); schedulingMode.writeToTag(tag); filter.save(tag); } @Override - public void load(final CompoundTag tag) { + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); schedulingMode.load(tag); filter.load(tag); - super.load(tag); } public void setSchedulingModeType(final SchedulingModeType type) { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/ImporterBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/ImporterBlockEntity.java index 71b12cea2..be7b11fc4 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/ImporterBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/ImporterBlockEntity.java @@ -79,21 +79,19 @@ private CompositeImporterTransferStrategy createStrategy(final ServerLevel serve } @Override - public void saveAdditional(final CompoundTag tag) { - super.saveAdditional(tag); + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); tag.putInt(TAG_FILTER_MODE, FilterModeSettings.getFilterMode(getNode().getFilterMode())); filter.save(tag); } @Override - public void load(final CompoundTag tag) { + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); if (tag.contains(TAG_FILTER_MODE)) { getNode().setFilterMode(FilterModeSettings.getFilterMode(tag.getInt(TAG_FILTER_MODE))); } - filter.load(tag); - - super.load(tag); } public boolean isFuzzyMode() { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/StorageConfigurationContainerImpl.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/StorageConfigurationContainerImpl.java index 3fb40d138..f1890948f 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/StorageConfigurationContainerImpl.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/StorageConfigurationContainerImpl.java @@ -26,8 +26,7 @@ public StorageConfigurationContainerImpl(final StorageConfiguration config, final FilterWithFuzzyMode filter, final Runnable listener, final Supplier redstoneModeSupplier, - final Consumer redstoneModeConsumer - ) { + final Consumer redstoneModeConsumer) { this.config = config; this.filter = filter; this.listener = listener; diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/constructor/ConstructorBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/constructor/ConstructorBlockEntity.java index 104736dc4..6137b4f8a 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/constructor/ConstructorBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/constructor/ConstructorBlockEntity.java @@ -99,17 +99,17 @@ public void postDoWork() { } @Override - public void saveAdditional(final CompoundTag tag) { - super.saveAdditional(tag); + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); tag.putBoolean(TAG_DROP_ITEMS, dropItems); } @Override - public void load(final CompoundTag tag) { + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); if (tag.contains(TAG_DROP_ITEMS)) { dropItems = tag.getBoolean(TAG_DROP_ITEMS); } - super.load(tag); } public boolean isDropItems() { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/destructor/DestructorBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/destructor/DestructorBlockEntity.java index f9e4f9aa9..3d2e7ad75 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/destructor/DestructorBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/destructor/DestructorBlockEntity.java @@ -83,15 +83,16 @@ public void setFilterMode(final FilterMode mode) { } @Override - public void saveAdditional(final CompoundTag tag) { - super.saveAdditional(tag); + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); tag.putInt(TAG_FILTER_MODE, FilterModeSettings.getFilterMode(filter.getMode())); tag.putBoolean(TAG_PICKUP_ITEMS, pickupItems); filterWithFuzzyMode.save(tag); } @Override - public void load(final CompoundTag tag) { + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); filterWithFuzzyMode.load(tag); if (tag.contains(TAG_FILTER_MODE)) { filter.setMode(FilterModeSettings.getFilterMode(tag.getInt(TAG_FILTER_MODE))); @@ -99,7 +100,6 @@ public void load(final CompoundTag tag) { if (tag.contains(TAG_PICKUP_ITEMS)) { pickupItems = tag.getBoolean(TAG_PICKUP_ITEMS); } - super.load(tag); } @Override diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/detector/DetectorBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/detector/DetectorBlockEntity.java index 98afeed4f..696c62b01 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/detector/DetectorBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/detector/DetectorBlockEntity.java @@ -64,10 +64,9 @@ public DetectorBlockEntity(final BlockPos pos, final BlockState state) { initialize(); } - @Override - public void saveAdditional(final CompoundTag tag) { - super.saveAdditional(tag); + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); filter.save(tag); tag.putDouble(TAG_AMOUNT, amount); tag.putInt(TAG_MODE, DetectorModeSettings.getDetectorMode(getNode().getMode())); @@ -75,6 +74,14 @@ public void saveAdditional(final CompoundTag tag) { @Override public void load(final CompoundTag tag) { + super.load(tag); + initialize(); + propagateAmount(); + } + + @Override + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); filter.load(tag); if (tag.contains(TAG_AMOUNT)) { this.amount = tag.getDouble(TAG_AMOUNT); @@ -82,9 +89,6 @@ public void load(final CompoundTag tag) { if (tag.contains(TAG_MODE)) { getNode().setMode(DetectorModeSettings.getDetectorMode(tag.getInt(TAG_MODE))); } - initialize(); - propagateAmount(); - super.load(tag); } public void setAmount(final double amount) { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/diskdrive/AbstractDiskDriveBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/diskdrive/AbstractDiskDriveBlockEntity.java index 2e99a8364..625bcd74d 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/diskdrive/AbstractDiskDriveBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/diskdrive/AbstractDiskDriveBlockEntity.java @@ -155,21 +155,28 @@ public void activenessChanged(final BlockState state, @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); + } + @Override + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); configContainer.load(tag); filter.load(tag); - - super.load(tag); } @Override public void saveAdditional(final CompoundTag tag) { super.saveAdditional(tag); tag.put(TAG_DISK_INVENTORY, ContainerUtil.write(diskInventory)); + } + + @Override + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); configContainer.save(tag); filter.save(tag); } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/externalstorage/ExternalStorageBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/externalstorage/ExternalStorageBlockEntity.java index 94bebab8c..d16595b60 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/externalstorage/ExternalStorageBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/externalstorage/ExternalStorageBlockEntity.java @@ -1,165 +1,174 @@ -package com.refinedmods.refinedstorage2.platform.common.block.entity.externalstorage; - -import com.refinedmods.refinedstorage2.api.network.impl.node.externalstorage.ExternalStorageNetworkNode; -import com.refinedmods.refinedstorage2.api.network.node.externalstorage.ExternalStorageProviderFactory; -import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType; -import com.refinedmods.refinedstorage2.api.storage.external.ExternalStorageProvider; -import com.refinedmods.refinedstorage2.platform.api.PlatformApi; -import com.refinedmods.refinedstorage2.platform.common.Platform; -import com.refinedmods.refinedstorage2.platform.common.block.entity.AbstractInternalNetworkNodeContainerBlockEntity; -import com.refinedmods.refinedstorage2.platform.common.block.entity.FilterWithFuzzyMode; -import com.refinedmods.refinedstorage2.platform.common.block.entity.StorageConfigurationContainerImpl; -import com.refinedmods.refinedstorage2.platform.common.containermenu.storage.ExternalStorageContainerMenu; -import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities; -import com.refinedmods.refinedstorage2.platform.common.content.ContentNames; -import com.refinedmods.refinedstorage2.platform.common.internal.resource.ResourceContainerImpl; -import com.refinedmods.refinedstorage2.platform.common.menu.ExtendedMenuProvider; - -import java.util.Optional; -import javax.annotation.Nullable; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ExternalStorageBlockEntity - extends AbstractInternalNetworkNodeContainerBlockEntity - implements ExtendedMenuProvider { - private static final Logger LOGGER = LoggerFactory.getLogger(ExternalStorageBlockEntity.class); - private static final String TAG_TRACKED_RESOURCES = "tr"; - - private final FilterWithFuzzyMode filter; - private final StorageConfigurationContainerImpl configContainer; - private final ExternalStorageTrackedStorageRepositoryProvider trackedStorageRepositoryProvider; - private final WorkRate workRate = new WorkRate(); - private boolean initialized; - - public ExternalStorageBlockEntity(final BlockPos pos, final BlockState state) { - super(BlockEntities.INSTANCE.getExternalStorage(), pos, state, new ExternalStorageNetworkNode( - Platform.INSTANCE.getConfig().getExternalStorage().getEnergyUsage() - )); - this.filter = FilterWithFuzzyMode.createAndListenForUniqueTemplates( - ResourceContainerImpl.createForFilter(), - this::setChanged, - templates -> getNode().setFilterTemplates(templates) - ); - this.trackedStorageRepositoryProvider = new ExternalStorageTrackedStorageRepositoryProvider( - PlatformApi.INSTANCE.getStorageChannelTypeRegistry(), - this::setChanged - ); - getNode().setNormalizer(filter.createNormalizer()); - getNode().initialize( - PlatformApi.INSTANCE.getStorageChannelTypeRegistry().getAll(), - System::currentTimeMillis, - trackedStorageRepositoryProvider - ); - this.configContainer = new StorageConfigurationContainerImpl( - getNode(), - filter, - this::setChanged, - this::getRedstoneMode, - this::setRedstoneMode - ); - } - - @Override - @SuppressWarnings("deprecation") - public void setBlockState(final BlockState newBlockState) { - super.setBlockState(newBlockState); - if (level instanceof ServerLevel serverLevel) { - LOGGER.debug("Reloading external storage @ {} as block state has changed", worldPosition); - loadStorage(serverLevel); - } - } - - @Override - protected void activenessChanged(final BlockState state, - final boolean newActive, - @Nullable final BooleanProperty activenessProperty) { - super.activenessChanged(state, newActive, activenessProperty); - if (!initialized && level instanceof ServerLevel serverLevel) { - LOGGER.debug("Triggering initial load of external storage {}", worldPosition); - loadStorage(serverLevel); - initialized = true; - } - } - - public void loadStorage(final ServerLevel serverLevel) { - final Direction direction = getDirection(); - LOGGER.debug("Loading storage for external storage with direction {} @ {}", direction, worldPosition); - if (direction == null) { - return; - } - getNode().initialize(new ExternalStorageProviderFactory() { - @Override - public Optional> create(final StorageChannelType channelType) { - final Direction incomingDirection = direction.getOpposite(); - final BlockPos sourcePosition = worldPosition.relative(direction); - return PlatformApi.INSTANCE - .getExternalStorageProviderFactories() - .stream() - .flatMap(factory -> factory.create(serverLevel, sourcePosition, incomingDirection, channelType) - .stream()) - .findFirst(); - } - }); - } - - @Override - public void doWork() { - super.doWork(); - if (workRate.canDoWork()) { - final boolean hasChanges = getNode().detectChanges(); - if (hasChanges) { - LOGGER.debug("External storage @ {} has changed!", worldPosition); - workRate.faster(); - } else { - workRate.slower(); - } - } - } - - @Override - public void saveAdditional(final CompoundTag tag) { - super.saveAdditional(tag); - filter.save(tag); - configContainer.save(tag); - tag.put(TAG_TRACKED_RESOURCES, trackedStorageRepositoryProvider.toTag()); - } - - @Override - public void load(final CompoundTag tag) { - super.load(tag); - filter.load(tag); - configContainer.load(tag); - trackedStorageRepositoryProvider.fromTag(tag.getList(TAG_TRACKED_RESOURCES, Tag.TAG_COMPOUND)); - } - - @Override - public void writeScreenOpeningData(final ServerPlayer player, final FriendlyByteBuf buf) { - filter.getFilterContainer().writeToUpdatePacket(buf); - } - - @Override - public Component getDisplayName() { - return ContentNames.EXTERNAL_STORAGE; - } - - @Nullable - @Override - public AbstractContainerMenu createMenu(final int syncId, final Inventory inventory, final Player player) { - return new ExternalStorageContainerMenu(syncId, player, filter.getFilterContainer(), configContainer); - } -} +package com.refinedmods.refinedstorage2.platform.common.block.entity.externalstorage; + +import com.refinedmods.refinedstorage2.api.network.impl.node.externalstorage.ExternalStorageNetworkNode; +import com.refinedmods.refinedstorage2.api.network.node.externalstorage.ExternalStorageProviderFactory; +import com.refinedmods.refinedstorage2.api.storage.channel.StorageChannelType; +import com.refinedmods.refinedstorage2.api.storage.external.ExternalStorageProvider; +import com.refinedmods.refinedstorage2.platform.api.PlatformApi; +import com.refinedmods.refinedstorage2.platform.common.Platform; +import com.refinedmods.refinedstorage2.platform.common.block.entity.AbstractInternalNetworkNodeContainerBlockEntity; +import com.refinedmods.refinedstorage2.platform.common.block.entity.FilterWithFuzzyMode; +import com.refinedmods.refinedstorage2.platform.common.block.entity.StorageConfigurationContainerImpl; +import com.refinedmods.refinedstorage2.platform.common.containermenu.storage.ExternalStorageContainerMenu; +import com.refinedmods.refinedstorage2.platform.common.content.BlockEntities; +import com.refinedmods.refinedstorage2.platform.common.content.ContentNames; +import com.refinedmods.refinedstorage2.platform.common.internal.resource.ResourceContainerImpl; +import com.refinedmods.refinedstorage2.platform.common.menu.ExtendedMenuProvider; + +import java.util.Optional; +import javax.annotation.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ExternalStorageBlockEntity + extends AbstractInternalNetworkNodeContainerBlockEntity + implements ExtendedMenuProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(ExternalStorageBlockEntity.class); + private static final String TAG_TRACKED_RESOURCES = "tr"; + + private final FilterWithFuzzyMode filter; + private final StorageConfigurationContainerImpl configContainer; + private final ExternalStorageTrackedStorageRepositoryProvider trackedStorageRepositoryProvider; + private final WorkRate workRate = new WorkRate(); + private boolean initialized; + + public ExternalStorageBlockEntity(final BlockPos pos, final BlockState state) { + super(BlockEntities.INSTANCE.getExternalStorage(), pos, state, new ExternalStorageNetworkNode( + Platform.INSTANCE.getConfig().getExternalStorage().getEnergyUsage() + )); + this.filter = FilterWithFuzzyMode.createAndListenForUniqueTemplates( + ResourceContainerImpl.createForFilter(), + this::setChanged, + templates -> getNode().setFilterTemplates(templates) + ); + this.trackedStorageRepositoryProvider = new ExternalStorageTrackedStorageRepositoryProvider( + PlatformApi.INSTANCE.getStorageChannelTypeRegistry(), + this::setChanged + ); + getNode().setNormalizer(filter.createNormalizer()); + getNode().initialize( + PlatformApi.INSTANCE.getStorageChannelTypeRegistry().getAll(), + System::currentTimeMillis, + trackedStorageRepositoryProvider + ); + this.configContainer = new StorageConfigurationContainerImpl( + getNode(), + filter, + this::setChanged, + this::getRedstoneMode, + this::setRedstoneMode + ); + } + + @Override + public void setBlockState(final BlockState newBlockState) { + super.setBlockState(newBlockState); + if (level instanceof ServerLevel serverLevel) { + LOGGER.debug("Reloading external storage @ {} as block state has changed", worldPosition); + loadStorage(serverLevel); + } + } + + @Override + protected void activenessChanged(final BlockState state, + final boolean newActive, + @Nullable final BooleanProperty activenessProperty) { + super.activenessChanged(state, newActive, activenessProperty); + if (!initialized && level instanceof ServerLevel serverLevel) { + LOGGER.debug("Triggering initial load of external storage {}", worldPosition); + loadStorage(serverLevel); + initialized = true; + } + } + + public void loadStorage(final ServerLevel serverLevel) { + final Direction direction = getDirection(); + LOGGER.debug("Loading storage for external storage with direction {} @ {}", direction, worldPosition); + if (direction == null) { + return; + } + getNode().initialize(new ExternalStorageProviderFactory() { + @Override + public Optional> create(final StorageChannelType channelType) { + final Direction incomingDirection = direction.getOpposite(); + final BlockPos sourcePosition = worldPosition.relative(direction); + return PlatformApi.INSTANCE + .getExternalStorageProviderFactories() + .stream() + .flatMap(factory -> factory.create(serverLevel, sourcePosition, incomingDirection, channelType) + .stream()) + .findFirst(); + } + }); + } + + @Override + public void doWork() { + super.doWork(); + if (workRate.canDoWork()) { + final boolean hasChanges = getNode().detectChanges(); + if (hasChanges) { + LOGGER.debug("External storage @ {} has changed!", worldPosition); + workRate.faster(); + } else { + workRate.slower(); + } + } + } + + @Override + public void saveAdditional(final CompoundTag tag) { + super.saveAdditional(tag); + tag.put(TAG_TRACKED_RESOURCES, trackedStorageRepositoryProvider.toTag()); + } + + @Override + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); + filter.save(tag); + configContainer.save(tag); + } + + @Override + public void load(final CompoundTag tag) { + super.load(tag); + trackedStorageRepositoryProvider.fromTag(tag.getList(TAG_TRACKED_RESOURCES, Tag.TAG_COMPOUND)); + } + + @Override + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); + filter.load(tag); + configContainer.load(tag); + } + + @Override + public void writeScreenOpeningData(final ServerPlayer player, final FriendlyByteBuf buf) { + filter.getFilterContainer().writeToUpdatePacket(buf); + } + + @Override + public Component getDisplayName() { + return ContentNames.EXTERNAL_STORAGE; + } + + @Nullable + @Override + public AbstractContainerMenu createMenu(final int syncId, final Inventory inventory, final Player player) { + return new ExternalStorageContainerMenu(syncId, player, filter.getFilterContainer(), configContainer); + } +} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/iface/InterfaceBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/iface/InterfaceBlockEntity.java index 9edacdb05..d08df7577 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/iface/InterfaceBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/iface/InterfaceBlockEntity.java @@ -107,6 +107,11 @@ static long getTransferQuota(final ResourceTemplate resourceTemplate) { public void saveAdditional(final CompoundTag tag) { super.saveAdditional(tag); tag.put(TAG_EXPORT_ITEMS, exportedResources.toTag()); + } + + @Override + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); filter.save(tag); } @@ -115,10 +120,15 @@ public void load(final CompoundTag tag) { if (tag.contains(TAG_EXPORT_ITEMS)) { exportedResources.fromTag(tag.getCompound(TAG_EXPORT_ITEMS)); } - filter.load(tag); super.load(tag); } + @Override + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); + filter.load(tag); + } + public boolean isFuzzyMode() { return filter.isFuzzyMode(); } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storage/AbstractStorageBlockBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storage/AbstractStorageBlockBlockEntity.java index ccce42bcf..df47b9537 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storage/AbstractStorageBlockBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storage/AbstractStorageBlockBlockEntity.java @@ -114,11 +114,14 @@ public void load(final CompoundTag tag) { } storageId = actualStorageId; } + super.load(tag); + } + @Override + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); configContainer.load(tag); filter.load(tag); - - super.load(tag); } @SuppressWarnings("unchecked") @@ -149,6 +152,11 @@ public void saveAdditional(final CompoundTag tag) { if (storageId != null) { tag.putUUID(TAG_STORAGE_ID, storageId); } + } + + @Override + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); configContainer.save(tag); filter.save(tag); } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storagemonitor/StorageMonitorBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storagemonitor/StorageMonitorBlockEntity.java index 2f3c0730c..caee98062 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storagemonitor/StorageMonitorBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/storagemonitor/StorageMonitorBlockEntity.java @@ -259,8 +259,8 @@ public boolean isCurrentlyActive() { } @Override - public void saveAdditional(final CompoundTag tag) { - super.saveAdditional(tag); + public void writeConfiguration(final CompoundTag tag) { + super.writeConfiguration(tag); filter.save(tag); } @@ -270,12 +270,16 @@ public void load(final CompoundTag tag) { filter.getFilterContainer().fromTag(tag.getCompound(TAG_CLIENT_FILTER)); currentAmount = tag.getLong(TAG_CLIENT_AMOUNT); currentlyActive = tag.getBoolean(TAG_CLIENT_ACTIVE); - } else { - filter.load(tag); } super.load(tag); } + @Override + public void readConfiguration(final CompoundTag tag) { + super.readConfiguration(tag); + filter.load(tag); + } + @Override public void writeScreenOpeningData(final ServerPlayer player, final FriendlyByteBuf buf) { filter.getFilterContainer().writeToUpdatePacket(buf); From 8330c0d3726b9aa01c9bbe9925f1eef217f8e22c Mon Sep 17 00:00:00 2001 From: Raoul Van den Berge Date: Tue, 31 Oct 2023 14:39:53 +0100 Subject: [PATCH 3/3] feat: configuration card --- CHANGELOG.md | 1 + .../blockentity/ConfigurationCardTarget.java | 12 +- .../common/AbstractModInitializer.java | 5 + ...ternalNetworkNodeContainerBlockEntity.java | 12 +- ...deableNetworkNodeContainerBlockEntity.java | 22 ++ .../entity/detector/DetectorBlockEntity.java | 9 +- .../platform/common/content/ContentIds.java | 1 + .../common/content/CreativeModeTabItems.java | 1 + .../platform/common/content/Items.java | 10 + .../common/item/ConfigurationCardItem.java | 205 ++++++++++++++++++ ...ConfigurationCardItemPropertyFunction.java | 26 +++ .../assets/refinedstorage2/lang/en_us.json | 11 +- .../models/item/configuration_card.json | 17 ++ .../item/configuration_card/active.json | 6 + .../item/configuration_card/inactive.json | 6 + .../item/configuration_card/active.png | Bin 0 -> 997 bytes .../item/configuration_card/inactive.png | Bin 0 -> 852 bytes .../recipes/configuration_card.json | 22 ++ .../fabric/ClientModInitializerImpl.java | 6 + .../platform/forge/ClientModInitializer.java | 6 + 20 files changed, 365 insertions(+), 13 deletions(-) create mode 100644 refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/item/ConfigurationCardItem.java create mode 100644 refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/render/ConfigurationCardItemPropertyFunction.java create mode 100644 refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card.json create mode 100644 refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card/active.json create mode 100644 refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card/inactive.json create mode 100644 refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/textures/item/configuration_card/active.png create mode 100644 refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/textures/item/configuration_card/inactive.png create mode 100644 refinedstorage2-platform-common/src/main/resources/data/refinedstorage2/recipes/configuration_card.json diff --git a/CHANGELOG.md b/CHANGELOG.md index e8b229e26..3799f1e1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Curios integration on Forge. - Trinkets integration on Fabric. - Storage Monitor +- Configuration Card. It copies device configurations and can transfer upgrades. ### Changed diff --git a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/blockentity/ConfigurationCardTarget.java b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/blockentity/ConfigurationCardTarget.java index 09f7ebc5d..1d5dd88bf 100644 --- a/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/blockentity/ConfigurationCardTarget.java +++ b/refinedstorage2-platform-api/src/main/java/com/refinedmods/refinedstorage2/platform/api/blockentity/ConfigurationCardTarget.java @@ -1,12 +1,18 @@ package com.refinedmods.refinedstorage2.platform.api.blockentity; +import java.util.List; + import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.item.Item; +import org.apiguardian.api.API; +@API(status = API.Status.STABLE, since = "2.0.0-milestone.3.2") public interface ConfigurationCardTarget { - BlockEntityType getBlockEntityType(); - void writeConfiguration(CompoundTag tag); void readConfiguration(CompoundTag tag); + + List getUpgradeItems(); + + boolean addUpgradeItem(Item upgradeItem); } 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 161c294ef..2b343c38d 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 @@ -77,6 +77,7 @@ import com.refinedmods.refinedstorage2.platform.common.internal.storage.type.ItemStorageType; import com.refinedmods.refinedstorage2.platform.common.internal.storage.type.StorageTypes; import com.refinedmods.refinedstorage2.platform.common.internal.upgrade.UpgradeDestinations; +import com.refinedmods.refinedstorage2.platform.common.item.ConfigurationCardItem; import com.refinedmods.refinedstorage2.platform.common.item.FluidStorageDiskItem; import com.refinedmods.refinedstorage2.platform.common.item.FortuneUpgradeItem; import com.refinedmods.refinedstorage2.platform.common.item.ItemStorageDiskItem; @@ -321,6 +322,10 @@ private void registerSimpleItems(final RegistryCallback callback) { for (final ProcessorItem.Type type : ProcessorItem.Type.values()) { registerProcessor(callback, type); } + Items.INSTANCE.setConfigurationCard(callback.register( + ContentIds.CONFIGURATION_CARD, + ConfigurationCardItem::new + )); } private void registerProcessor(final RegistryCallback callback, final ProcessorItem.Type type) { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractInternalNetworkNodeContainerBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractInternalNetworkNodeContainerBlockEntity.java index 474cd4c8c..1fd6f3861 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractInternalNetworkNodeContainerBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractInternalNetworkNodeContainerBlockEntity.java @@ -9,6 +9,8 @@ import com.refinedmods.refinedstorage2.platform.common.block.ColorableBlock; import com.refinedmods.refinedstorage2.platform.common.util.RedstoneMode; +import java.util.Collections; +import java.util.List; import java.util.UUID; import javax.annotation.Nullable; @@ -18,6 +20,7 @@ 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; import net.minecraft.world.level.block.state.properties.BooleanProperty; @@ -85,8 +88,13 @@ public void readConfiguration(final CompoundTag tag) { } @Override - public BlockEntityType getBlockEntityType() { - return getType(); + public List getUpgradeItems() { + return Collections.emptyList(); + } + + @Override + public boolean addUpgradeItem(final Item upgradeItem) { + return false; } public void updateActiveness(final BlockState state, diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractUpgradeableNetworkNodeContainerBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractUpgradeableNetworkNodeContainerBlockEntity.java index c1a725fe3..030524f05 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractUpgradeableNetworkNodeContainerBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/AbstractUpgradeableNetworkNodeContainerBlockEntity.java @@ -5,12 +5,16 @@ import com.refinedmods.refinedstorage2.platform.common.content.Items; import com.refinedmods.refinedstorage2.platform.common.internal.upgrade.UpgradeDestinations; +import java.util.ArrayList; +import java.util.List; + import com.google.common.util.concurrent.RateLimiter; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -63,6 +67,24 @@ private void upgradeContainerChanged() { } } + @Override + public List getUpgradeItems() { + final List upgradeItems = new ArrayList<>(); + for (int i = 0; i < upgradeContainer.getContainerSize(); ++i) { + final ItemStack itemStack = upgradeContainer.getItem(i); + if (itemStack.isEmpty()) { + continue; + } + upgradeItems.add(itemStack.getItem()); + } + return upgradeItems; + } + + @Override + public boolean addUpgradeItem(final Item upgradeItem) { + return upgradeContainer.addItem(new ItemStack(upgradeItem)).isEmpty(); + } + @Override public void saveAdditional(final CompoundTag tag) { super.saveAdditional(tag); diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/detector/DetectorBlockEntity.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/detector/DetectorBlockEntity.java index 696c62b01..4391e381e 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/detector/DetectorBlockEntity.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/block/entity/detector/DetectorBlockEntity.java @@ -72,13 +72,6 @@ public void writeConfiguration(final CompoundTag tag) { tag.putInt(TAG_MODE, DetectorModeSettings.getDetectorMode(getNode().getMode())); } - @Override - public void load(final CompoundTag tag) { - super.load(tag); - initialize(); - propagateAmount(); - } - @Override public void readConfiguration(final CompoundTag tag) { super.readConfiguration(tag); @@ -89,6 +82,8 @@ public void readConfiguration(final CompoundTag tag) { if (tag.contains(TAG_MODE)) { getNode().setMode(DetectorModeSettings.getDetectorMode(tag.getInt(TAG_MODE))); } + initialize(); + propagateAmount(); } public void setAmount(final double amount) { diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/ContentIds.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/ContentIds.java index cd3f251c8..2ca3bd93a 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/ContentIds.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/ContentIds.java @@ -48,6 +48,7 @@ public final class ContentIds { public static final ResourceLocation RANGE_UPGRADE = createIdentifier("range_upgrade"); public static final ResourceLocation CREATIVE_RANGE_UPGRADE = createIdentifier("creative_range_upgrade"); public static final ResourceLocation STORAGE_MONITOR = createIdentifier("storage_monitor"); + public static final ResourceLocation CONFIGURATION_CARD = createIdentifier("configuration_card"); private ContentIds() { } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/CreativeModeTabItems.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/CreativeModeTabItems.java index 5af4cd217..002b99b20 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/CreativeModeTabItems.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/CreativeModeTabItems.java @@ -95,5 +95,6 @@ private static void appendItems(final Consumer consumer) { itemConsumer.accept(Items.INSTANCE.getWirelessGrid()); consumer.accept(Items.INSTANCE.getWirelessGrid().createAtEnergyCapacity()); itemConsumer.accept(Items.INSTANCE.getCreativeWirelessGrid()); + itemConsumer.accept(Items.INSTANCE.getConfigurationCard()); } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/Items.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/Items.java index 6734b231a..fdfcdc5f3 100644 --- a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/Items.java +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/content/Items.java @@ -78,6 +78,8 @@ public final class Items { private Supplier wirelessGrid; @Nullable private Supplier creativeWirelessGrid; + @Nullable + private Supplier configurationCard; private Items() { } @@ -353,4 +355,12 @@ public WirelessGridItem getCreativeWirelessGrid() { public void setCreativeWirelessGrid(final Supplier supplier) { this.creativeWirelessGrid = supplier; } + + public Item getConfigurationCard() { + return Objects.requireNonNull(configurationCard).get(); + } + + public void setConfigurationCard(final Supplier supplier) { + this.configurationCard = supplier; + } } diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/item/ConfigurationCardItem.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/item/ConfigurationCardItem.java new file mode 100644 index 000000000..045bf8b18 --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/item/ConfigurationCardItem.java @@ -0,0 +1,205 @@ +package com.refinedmods.refinedstorage2.platform.common.item; + +import com.refinedmods.refinedstorage2.platform.api.blockentity.ConfigurationCardTarget; +import com.refinedmods.refinedstorage2.platform.api.item.HelpTooltipComponent; + +import java.util.List; +import java.util.Optional; +import javax.annotation.Nullable; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; + +import static com.refinedmods.refinedstorage2.platform.common.util.IdentifierUtil.createTranslation; +import static java.util.Objects.requireNonNull; + +// TODO: textures +public class ConfigurationCardItem extends Item { + private static final Component EMPTY_HELP = createTranslation("item", "configuration_card.empty_help"); + private static final Component CONFIGURED_HELP = createTranslation("item", "configuration_card.configured_help"); + + private static final Component EMPTY = createTranslation("item", "configuration_card.empty") + .withStyle(ChatFormatting.GRAY); + + private static final String TAG_TYPE = "type"; + private static final String TAG_CONFIG = "config"; + private static final String TAG_UPGRADES = "upgrades"; + + public ConfigurationCardItem() { + super(new Item.Properties().stacksTo(1)); + } + + @Override + public InteractionResult useOn(final UseOnContext ctx) { + if (ctx.getLevel().isClientSide() || ctx.getPlayer() == null) { + return InteractionResult.CONSUME; + } + final BlockEntity blockEntity = ctx.getLevel().getBlockEntity(ctx.getClickedPos()); + if (!(blockEntity instanceof ConfigurationCardTarget target)) { + return InteractionResult.CONSUME; + } + final ItemStack stack = ctx.getItemInHand(); + if (stack.getTag() == null) { + writeConfiguration(stack, ctx.getPlayer(), target, blockEntity.getType()); + return InteractionResult.CONSUME; + } + return applyConfiguration(ctx.getPlayer(), blockEntity, target, stack.getTag()); + } + + private InteractionResult applyConfiguration( + final Player player, + final BlockEntity targetBlockEntity, + final ConfigurationCardTarget target, + final CompoundTag tag + ) { + final BlockEntityType existingConfiguredType = getConfiguredType(tag); + if (existingConfiguredType != targetBlockEntity.getType()) { + return configurationCardIsConfiguredForDifferentType(player, existingConfiguredType); + } + target.readConfiguration(tag.getCompound(TAG_CONFIG)); + tryTransferUpgrades(player, target, tag); + targetBlockEntity.setChanged(); + player.sendSystemMessage(createTranslation("item", "configuration_card.applied_configuration")); + return InteractionResult.SUCCESS; + } + + private void tryTransferUpgrades(final Player player, final ConfigurationCardTarget target, final CompoundTag tag) { + final ListTag upgradesTag = tag.getList(TAG_UPGRADES, Tag.TAG_STRING); + for (final Tag upgradeItemTag : upgradesTag) { + final ResourceLocation upgradeItemKey = new ResourceLocation(upgradeItemTag.getAsString()); + final Item upgradeItem = BuiltInRegistries.ITEM.get(upgradeItemKey); + final int upgradeIndexInPlayerInventory = player.getInventory().findSlotMatchingItem( + new ItemStack(upgradeItem) + ); + if (upgradeIndexInPlayerInventory >= 0 && target.addUpgradeItem(upgradeItem)) { + player.getInventory().removeItem(upgradeIndexInPlayerInventory, 1); + } + } + } + + private InteractionResult configurationCardIsConfiguredForDifferentType( + final Player player, + @Nullable final BlockEntityType existingConfiguredType + ) { + if (existingConfiguredType != null) { + player.sendSystemMessage(createTranslation( + "item", + "configuration_card.cannot_apply_configuration", + getConfiguredTypeTranslation(existingConfiguredType).withStyle(ChatFormatting.YELLOW) + )); + } + return InteractionResult.CONSUME; + } + + private void writeConfiguration(final ItemStack stack, + final Player player, + final ConfigurationCardTarget target, + final BlockEntityType type) { + final CompoundTag tag = new CompoundTag(); + tag.putString(TAG_TYPE, requireNonNull(BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(type)).toString()); + tag.put(TAG_CONFIG, createConfigTag(target)); + tag.put(TAG_UPGRADES, createUpgradesTag(target)); + stack.setTag(tag); + sendCopiedConfigurationMessage(player, type); + } + + private CompoundTag createConfigTag(final ConfigurationCardTarget target) { + final CompoundTag tag = new CompoundTag(); + target.writeConfiguration(tag); + return tag; + } + + private ListTag createUpgradesTag(final ConfigurationCardTarget target) { + final ListTag tag = new ListTag(); + target.getUpgradeItems().forEach(item -> { + final ResourceLocation itemKey = BuiltInRegistries.ITEM.getKey(item); + tag.add(StringTag.valueOf(itemKey.toString())); + }); + return tag; + } + + private void sendCopiedConfigurationMessage(final Player player, final BlockEntityType configuredType) { + if (player.level().isClientSide()) { + return; + } + player.sendSystemMessage(createTranslation( + "item", + "configuration_card.copied_configuration", + getConfiguredTypeTranslation(configuredType).withStyle(ChatFormatting.YELLOW) + )); + } + + @Override + public InteractionResultHolder use(final Level level, final Player player, final InteractionHand hand) { + if (player.isCrouching()) { + if (!level.isClientSide()) { + player.sendSystemMessage(createTranslation("item", "configuration_card.cleared_configuration")); + } + return new InteractionResultHolder<>(InteractionResult.CONSUME, new ItemStack(this)); + } + return super.use(level, player, hand); + } + + @Override + public void appendHoverText(final ItemStack stack, + @Nullable final Level level, + final List lines, + final TooltipFlag flag) { + super.appendHoverText(stack, level, lines, flag); + if (stack.getTag() == null) { + lines.add(EMPTY); + return; + } + final BlockEntityType configuredType = getConfiguredType(stack.getTag()); + if (configuredType == null) { + return; + } + lines.add(createTranslation( + "item", + "configuration_card.configured", + getConfiguredTypeTranslation(configuredType).withStyle(ChatFormatting.WHITE) + ).withStyle(ChatFormatting.GRAY)); + } + + @Nullable + private BlockEntityType getConfiguredType(final CompoundTag tag) { + final ResourceLocation type = new ResourceLocation(tag.getString(TAG_TYPE)); + return BuiltInRegistries.BLOCK_ENTITY_TYPE.get(type); + } + + private MutableComponent getConfiguredTypeTranslation(final BlockEntityType type) { + final ResourceLocation typeId = BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(type); + if (typeId == null) { + return Component.empty(); + } + return Component.translatable("block." + typeId.getNamespace() + "." + typeId.getPath()); + } + + @Override + public Optional getTooltipImage(final ItemStack stack) { + return Optional.of(new HelpTooltipComponent(isActive(stack) ? CONFIGURED_HELP : EMPTY_HELP)); + } + + public boolean isActive(final ItemStack stack) { + return stack.getTag() != null && stack.getTag().contains(TAG_TYPE); + } +} diff --git a/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/render/ConfigurationCardItemPropertyFunction.java b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/render/ConfigurationCardItemPropertyFunction.java new file mode 100644 index 000000000..e60ee181e --- /dev/null +++ b/refinedstorage2-platform-common/src/main/java/com/refinedmods/refinedstorage2/platform/common/render/ConfigurationCardItemPropertyFunction.java @@ -0,0 +1,26 @@ +package com.refinedmods.refinedstorage2.platform.common.render; + +import com.refinedmods.refinedstorage2.platform.common.item.ConfigurationCardItem; + +import javax.annotation.Nullable; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.item.ClampedItemPropertyFunction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; + +public class ConfigurationCardItemPropertyFunction implements ClampedItemPropertyFunction { + public static final ResourceLocation NAME = new ResourceLocation("active"); + + @Override + public float unclampedCall(final ItemStack itemStack, + @Nullable final ClientLevel clientLevel, + @Nullable final LivingEntity livingEntity, + final int i) { + if (itemStack.getItem() instanceof ConfigurationCardItem cardItem) { + return cardItem.isActive(itemStack) ? 1 : 0; + } + return 0; + } +} 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 59ef8d0bb..f2fc84abb 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 @@ -194,6 +194,15 @@ "item.refinedstorage2.network_item.bound_to": "Bound to %d, %d, %d.", "item.refinedstorage2.network_item.cannot_open_with_shortcut_due_to_duplicate": "There is more than one %s in your inventory.", "item.refinedstorage2.network_item.cannot_open_because_not_found": "There isn't any %s in your inventory.", + "item.refinedstorage2.configuration_card": "Configuration Card", + "item.refinedstorage2.configuration_card.empty": "Empty.", + "item.refinedstorage2.configuration_card.configured": "Contains configuration for %s.", + "item.refinedstorage2.configuration_card.copied_configuration": "Copied configuration for %s.", + "item.refinedstorage2.configuration_card.cleared_configuration": "Cleared configuration.", + "item.refinedstorage2.configuration_card.cannot_apply_configuration": "Cannot apply configuration card to different type of device. It is configured for %s.", + "item.refinedstorage2.configuration_card.applied_configuration": "Applied configuration.", + "item.refinedstorage2.configuration_card.empty_help": "Use on a storage network device while crouching to copy its configuration and upgrades to the card.", + "item.refinedstorage2.configuration_card.configured_help": "Use on the destination storage network device while crouching to transfer the configuration and upgrades. Use while crouching to clear.", "misc.refinedstorage2.stored": "Stored: %s", "misc.refinedstorage2.stored_with_capacity": "Stored: %s / %s (%d%%)", "misc.refinedstorage2.total": "%d total", @@ -225,7 +234,7 @@ "text.autoconfig.refinedstorage2.option.grid": "Grid", "text.autoconfig.refinedstorage2.option.grid.largeFont": "Large font", "text.autoconfig.refinedstorage2.option.grid.maxRowsStretch": "Maximum amount of rows when stretched", - "text.autoconfig.refinedstorage2.option.grid.preventSortingWhileShiftIsDown": "Prevent sorting while shift is down", + "text.autoconfig.refinedstorage2.option.grid.preventSortingWhileShiftIsDown": "Prevent sorting while SHIFT is down", "text.autoconfig.refinedstorage2.option.grid.detailedTooltip": "Detailed tooltip", "text.autoconfig.refinedstorage2.option.grid.rememberSearchQuery": "Remember search query", "text.autoconfig.refinedstorage2.option.grid.energyUsage": "Energy usage", diff --git a/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card.json b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card.json new file mode 100644 index 000000000..d0e58b52d --- /dev/null +++ b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card.json @@ -0,0 +1,17 @@ +{ + "parent": "item/generated", + "overrides": [ + { + "predicate": { + "active": 0 + }, + "model": "refinedstorage2:item/configuration_card/inactive" + }, + { + "predicate": { + "active": 1 + }, + "model": "refinedstorage2:item/configuration_card/active" + } + ] +} diff --git a/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card/active.json b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card/active.json new file mode 100644 index 000000000..d59df8a1f --- /dev/null +++ b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card/active.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "refinedstorage2:item/configuration_card/active" + } +} diff --git a/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card/inactive.json b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card/inactive.json new file mode 100644 index 000000000..211dd1de5 --- /dev/null +++ b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/models/item/configuration_card/inactive.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "refinedstorage2:item/configuration_card/inactive" + } +} diff --git a/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/textures/item/configuration_card/active.png b/refinedstorage2-platform-common/src/main/resources/assets/refinedstorage2/textures/item/configuration_card/active.png new file mode 100644 index 0000000000000000000000000000000000000000..a4d8387d7052183ad39a52f520fc5ac98864d5a0 GIT binary patch literal 997 zcmVEX>4Tx04R}tkv&MmKpe$iQ>9X>4t5Yx%ut;yh>AFB6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfb#YR3krMxx6k5c3aNLh~_a1le0HIc5n$k~y#OK6gCS8#Dk?V@bZ=CZk3p_Jyrjql-VPY}g!b%IXf~gTt5l2)_r+gvp zvC4UivsS9G#y$B9Ls@-gnd>wM5yv8yAVGwJ3W_MfMwC{a6bnh(kG1g+xPFOT3b~44 z`U&8F2Cnp`zgz=mK1r`O zwa5|ByA51iH#KDsxZDBypA6ZQUCB>V$mM|dGy0|s(02<2*Sy{u`#607Qq)!A1~@nb zM)Q=t-sat1t-bwwrqSOIoz`-=tvThp00006VoOIv0RI600RN!9r;`8x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=L#PVCIviogi`eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00F&8L_t(I%cavzOH^SL2k_raqE><{7q)3p?Sd9p1GYbMKrMa|z#qpaTaUp8xaw z&;PvfpH@0^6Z(&#YyV1AG328UYN`%29N4uW44)I=wlGk54-8|$gxs2t7oJH@5QK_D zUmd7Av~J5Qp}zxnOt|ibl0F>D<(d*J`ijrfDvmtRrB_KwT|=(34L(x0qA7&B6?LPg z+@h#O=(lWMrX_?#V%fZDm39hWv?MYuyTbUHoa;vII*<$7npRB~NRhe8aRE2wI zIfU*Bl3+~JqFg4I+O(}^ z$A*S2VZ;xgBt@B1;iuGRzwns0;u&wGmNeyBQZ2c#?@$;K2JBdr$fQCD6I$5DNEt5; zdhNS4t3pf3p0H{MQ%a`v8nW)G4O`}EX>4Tx04R}tkv&MmKpe$iQ>9X>4t5Yx%ut;yh>AFB6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfb#YR3krMxx6k5c3aNLh~_a1le0HIc5n$k~y#OK6gCS8#Dk?V@bZ=CZk3p_Jyrjql-VPY}g!b%IXf~gTt5l2)_r+gvp zvC4UivsS9G#y$B9Ls@-gnd>wM5yv8yAVGwJ3W_MfMwC{a6bnh(kG1g+xPFOT3b~44 z`U&8F2Cnp`zgz=mK1r`O zwa5|ByA51iH#KDsxZDBypA6ZQUCB>V$mM|dGy0|s(02<2*Sy{u`#607Qq)!A1~@nb zM)Q=t-sat1t-bwwrqSOIoz`-=tvThp00006VoOIv0RI600RN!9r;`8x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=L#PVB`?h59!3BF02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00AsXL_t(I%f-`8E5uP02Jjz4h+=C}q6vGHB`Yf>AAyDJ z?3H{COG`^7Vq>A?H6;r#d5MJ$d5tiP%^6Mqj9FMXb-K6vob%js&V4TbZDp~JqaPW3 z;t2DYE=5p*QH-Glm2sZN&JXdO=!*R|b}G;l$z`|;zeyzahBu=<@WXrsgLuLQmN5In z%>x)hH8ycv2xhT`#v*MtVhyjjz(}0c