diff --git a/gradle.properties b/gradle.properties index 03b92141..6e9071c3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ loader_version_range=[4,) mod_id=sophisticatedstorage mod_name=Sophisticated Storage mod_license=GNU General Public License v3.0 -mod_version=0.10.41 +mod_version=0.10.42 mod_group_id=sophisticatedstorage mod_authors=P3pp3rF1y, Ridanisaurus mod_description=Fancy and functional storage containers. @@ -35,7 +35,7 @@ jade_cf_file_id=5109393 chipped_cf_file_id=5506938 resourcefullib_cf_file_id=5483169 athena_cf_file_id=5431579 -sc_version=[1.21-0.6.41,1.22) +sc_version=[1.21-0.6.42,1.22) sb_version=[1.21,1.22) #publish diff --git a/src/main/java/net/p3pp3rf1y/sophisticatedstorage/upgrades/hopper/HopperUpgradeWrapper.java b/src/main/java/net/p3pp3rf1y/sophisticatedstorage/upgrades/hopper/HopperUpgradeWrapper.java index dd0ac2a0..02902101 100644 --- a/src/main/java/net/p3pp3rf1y/sophisticatedstorage/upgrades/hopper/HopperUpgradeWrapper.java +++ b/src/main/java/net/p3pp3rf1y/sophisticatedstorage/upgrades/hopper/HopperUpgradeWrapper.java @@ -21,12 +21,14 @@ import net.p3pp3rf1y.sophisticatedstorage.block.StorageBlockBase; import net.p3pp3rf1y.sophisticatedstorage.block.VerticalFacing; import net.p3pp3rf1y.sophisticatedstorage.common.gui.BlockSide; +import net.p3pp3rf1y.sophisticatedstorage.init.ModBlocks; import net.p3pp3rf1y.sophisticatedstorage.init.ModDataComponents; import net.p3pp3rf1y.sophisticatedstorage.upgrades.INeighborChangeListenerUpgrade; import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Predicate; @@ -35,17 +37,17 @@ public class HopperUpgradeWrapper extends UpgradeWrapperBase pullDirections = new LinkedHashSet<>(); private final Set pushDirections = new LinkedHashSet<>(); - private final Map>> handlerCache = new EnumMap<>(Direction.class); + private final Map handlerCache = new EnumMap<>(Direction.class); private final ContentsFilterLogic inputFilterLogic; - private final ContentsFilterLogic outputFilterLogic; + private final TargetContentsFilterLogic outputFilterLogic; private long coolDownTime = 0; protected HopperUpgradeWrapper(IStorageWrapper storageWrapper, ItemStack upgrade, Consumer upgradeSaveHandler) { super(storageWrapper, upgrade, upgradeSaveHandler); inputFilterLogic = new ContentsFilterLogic(upgrade, upgradeSaveHandler, upgradeItem.getInputFilterSlotCount(), storageWrapper::getInventoryHandler, storageWrapper.getSettingsHandler().getTypeCategory(MemorySettingsCategory.class), ModCoreDataComponents.INPUT_FILTER_ATTRIBUTES); - outputFilterLogic = new ContentsFilterLogic(upgrade, upgradeSaveHandler, upgradeItem.getOutputFilterSlotCount(), storageWrapper::getInventoryHandler, + outputFilterLogic = new TargetContentsFilterLogic(upgrade, upgradeSaveHandler, upgradeItem.getOutputFilterSlotCount(), storageWrapper::getInventoryHandler, storageWrapper.getSettingsHandler().getTypeCategory(MemorySettingsCategory.class), ModDataComponents.OUTPUT_FILTER_ATTRIBUTES); deserialize(); @@ -99,6 +101,7 @@ private boolean pullItems(List fromHandlers) { private boolean pushItems(List toHandlers) { for (IItemHandler toHandler : toHandlers) { + outputFilterLogic.setInventory(toHandler); if (moveItems(storageWrapper.getInventoryForUpgradeProcessing(), toHandler, outputFilterLogic)) { return true; } @@ -132,12 +135,14 @@ && needsCacheUpdate(level, pos, direction)) { } private boolean needsCacheUpdate(Level level, BlockPos pos, Direction direction) { - List> handlers = handlerCache.get(direction); - if (handlers == null || handlers.isEmpty()) { + ItemHandlerHolder holder = handlerCache.get(direction); + if (holder == null || holder.handlers().isEmpty()) { return !level.getBlockState(pos).isAir(); + } else if (holder.refreshOnEveryNeighborChange()) { + return true; } - for (BlockCapabilityCache handler : handlers) { + for (BlockCapabilityCache handler : holder.handlers()) { if (handler.getCapability() == null) { return true; } @@ -159,10 +164,18 @@ public void updateCacheOnSide(Level level, BlockPos pos, Direction direction) { List> caches = new ArrayList<>(); + AtomicBoolean refreshOnEveryNeighborChange = new AtomicBoolean(false); offsetPositions.forEach(offsetPos -> { + offsetPos = level.getBlockEntity(offsetPos, ModBlocks.STORAGE_INPUT_BLOCK_ENTITY_TYPE.get()) + .flatMap(storageInputBlockEntity -> { + refreshOnEveryNeighborChange.set(true); + return storageInputBlockEntity.getControllerPos(); + } + ).orElse(offsetPos); + caches.add(BlockCapabilityCache.create(Capabilities.ItemHandler.BLOCK, serverLevel, offsetPos, direction.getOpposite(), () -> existRef.get() != null, () -> updateCacheOnSide(level, pos, direction))); }); - handlerCache.put(direction, caches); + handlerCache.put(direction, new ItemHandlerHolder(caches, refreshOnEveryNeighborChange.get())); } private boolean runOnItemHandlers(Level level, BlockPos pos, Direction direction, Predicate> run) { @@ -173,7 +186,7 @@ private boolean runOnItemHandlers(Level level, BlockPos pos, Direction direction return false; } - List handler = handlerCache.get(direction).stream().map(BlockCapabilityCache::getCapability).filter(Objects::nonNull).toList(); + List handler = handlerCache.get(direction).handlers().stream().map(BlockCapabilityCache::getCapability).filter(Objects::nonNull).toList(); return run.test(handler); } @@ -239,4 +252,8 @@ public void initDirections(Direction pushDirection, Direction pullDirection) { setPushingTo(pushDirection, true); setPullingFrom(pullDirection, true); } + + private record ItemHandlerHolder(List> handlers, + boolean refreshOnEveryNeighborChange) { + } } diff --git a/src/main/java/net/p3pp3rf1y/sophisticatedstorage/upgrades/hopper/TargetContentsFilterLogic.java b/src/main/java/net/p3pp3rf1y/sophisticatedstorage/upgrades/hopper/TargetContentsFilterLogic.java new file mode 100644 index 00000000..02773e84 --- /dev/null +++ b/src/main/java/net/p3pp3rf1y/sophisticatedstorage/upgrades/hopper/TargetContentsFilterLogic.java @@ -0,0 +1,53 @@ +package net.p3pp3rf1y.sophisticatedstorage.upgrades.hopper; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.p3pp3rf1y.sophisticatedcore.inventory.InventoryHandler; +import net.p3pp3rf1y.sophisticatedcore.inventory.ItemStackKey; +import net.p3pp3rf1y.sophisticatedcore.settings.memory.MemorySettingsCategory; +import net.p3pp3rf1y.sophisticatedcore.upgrades.ContentsFilterLogic; +import net.p3pp3rf1y.sophisticatedcore.upgrades.FilterAttributes; +import net.p3pp3rf1y.sophisticatedcore.util.InventoryHelper; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class TargetContentsFilterLogic extends ContentsFilterLogic { + private Set inventoryFilterStacks = new HashSet<>(); + private final LoadingCache> inventoryCache = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.SECONDS).build(new CacheLoader<>() { + @Override + public Set load(IItemHandler inventory) { + return InventoryHelper.getUniqueStacks(inventory); + } + }); + + public TargetContentsFilterLogic(ItemStack upgrade, Consumer saveHandler, int filterSlotCount, Supplier getInventoryHandler, MemorySettingsCategory memorySettings, DeferredHolder, DataComponentType> filterAttributesComponent) { + super(upgrade, saveHandler, filterSlotCount, getInventoryHandler, memorySettings, filterAttributesComponent); + } + + public void setInventory(IItemHandler inventory) { + inventoryFilterStacks = inventoryCache.getUnchecked(inventory); + } + + @Override + public boolean matchesFilter(ItemStack stack) { + if (!shouldFilterByStorage()) { + return super.matchesFilter(stack); + } + + for (ItemStackKey filterStack : inventoryFilterStacks) { + if (stackMatchesFilter(stack, filterStack.getStack())) { + return true; + } + } + return false; + } +}