Skip to content

Commit

Permalink
feat: ✨ Changed hopper upgrade to filter by contents of the target in…
Browse files Browse the repository at this point in the history
…ventory when pushing into that inventory and set to filter by contents (instead of the current filtering by source inventory)
  • Loading branch information
P3pp3rF1y committed Sep 29, 2024
1 parent b4bb0eb commit 0a86229
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 10 deletions.
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ org.gradle.daemon=false

mod_id=sophisticatedstorage
mod_group_id=sophisticatedstorage
mod_version=0.10.41
mod_version=0.10.42
sonar_project_key=sophisticatedstorage:SophisticatedStorage
github_package_url=https://maven.pkg.github.com/P3pp3rF1y/SophisticatedStorage

Expand All @@ -30,6 +30,6 @@ jade_cf_file_id=4614153
chipped_cf_file_id=5077656
resourcefullib_cf_file_id=5070629
athena_cf_file_id=4764357
sc_version=[1.20.1-0.6.31,1.20.4)
sc_version=[1.20.1-0.6.33,1.20.4)
sb_version=[1.20.1-3.20.5,1.20.4)
parchment_version=1.19.3-2023.03.12-1.20
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.EmptyHandler;
import net.p3pp3rf1y.sophisticatedcore.api.IStorageWrapper;
import net.p3pp3rf1y.sophisticatedcore.inventory.ITrackedContentsItemHandler;
import net.p3pp3rf1y.sophisticatedcore.settings.memory.MemorySettingsCategory;
Expand All @@ -25,13 +26,15 @@
import net.p3pp3rf1y.sophisticatedcore.util.NBTHelper;
import net.p3pp3rf1y.sophisticatedcore.util.WorldHelper;
import net.p3pp3rf1y.sophisticatedstorage.block.StorageBlockBase;
import net.p3pp3rf1y.sophisticatedstorage.block.StorageInputBlockEntity;
import net.p3pp3rf1y.sophisticatedstorage.block.VerticalFacing;
import net.p3pp3rf1y.sophisticatedstorage.common.gui.BlockSide;
import net.p3pp3rf1y.sophisticatedstorage.init.ModItems;
import net.p3pp3rf1y.sophisticatedstorage.upgrades.INeighborChangeListenerUpgrade;

import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

public class HopperUpgradeWrapper extends UpgradeWrapperBase<HopperUpgradeWrapper, HopperUpgradeItem>
Expand All @@ -40,17 +43,17 @@ public class HopperUpgradeWrapper extends UpgradeWrapperBase<HopperUpgradeWrappe
private Set<Direction> pullDirections = new LinkedHashSet<>();
private Set<Direction> pushDirections = new LinkedHashSet<>();
private boolean directionsInitialized = false;
private final Map<Direction, List<LazyOptional<IItemHandler>>> handlerCache = new EnumMap<>(Direction.class);
private final Map<Direction, ItemHandlerHolder> 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<ItemStack> upgradeSaveHandler) {
super(storageWrapper, upgrade, upgradeSaveHandler);
inputFilterLogic = new ContentsFilterLogic(upgrade, upgradeSaveHandler, upgradeItem.getInputFilterSlotCount(), storageWrapper::getInventoryHandler,
storageWrapper.getSettingsHandler().getTypeCategory(MemorySettingsCategory.class), "inputFilter");
outputFilterLogic = new ContentsFilterLogic(upgrade, upgradeSaveHandler, upgradeItem.getOutputFilterSlotCount(), storageWrapper::getInventoryHandler,
outputFilterLogic = new TargetContentsFilterLogic(upgrade, upgradeSaveHandler, upgradeItem.getOutputFilterSlotCount(), storageWrapper::getInventoryHandler,
storageWrapper.getSettingsHandler().getTypeCategory(MemorySettingsCategory.class), "outputFilter");

deserialize();
Expand Down Expand Up @@ -105,6 +108,7 @@ public void tick(@Nullable LivingEntity entity, Level level, BlockPos pos) {
private boolean pushItemsToContainer(WorldlyContainer worldlyContainer, Direction face) {
ITrackedContentsItemHandler fromHandler = storageWrapper.getInventoryForUpgradeProcessing();

outputFilterLogic.setInventory(EmptyHandler.INSTANCE);
for (int slot = 0; slot < fromHandler.getSlots(); slot++) {
ItemStack slotStack = fromHandler.getStackInSlot(slot);
if (!slotStack.isEmpty() && outputFilterLogic.matchesFilter(slotStack)) {
Expand Down Expand Up @@ -192,6 +196,7 @@ private boolean pullItems(IItemHandler fromHandler) {
}

private boolean pushItems(IItemHandler toHandler) {
outputFilterLogic.setInventory(toHandler);
return moveItems(storageWrapper.getInventoryForUpgradeProcessing(), toHandler, outputFilterLogic);
}

Expand Down Expand Up @@ -221,12 +226,14 @@ && needsCacheUpdate(level, pos, direction)) {
}

private boolean needsCacheUpdate(Level level, BlockPos pos, Direction direction) {
List<LazyOptional<IItemHandler>> 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 (LazyOptional<IItemHandler> handler : handlers) {
for (LazyOptional<IItemHandler> handler : holder.handlers()) {
if (!handler.isPresent()) {
return true;
}
Expand All @@ -244,22 +251,28 @@ public void updateCacheOnSide(Level level, BlockPos pos, Direction direction) {
BlockState storageState = level.getBlockState(pos);
List<BlockPos> offsetPositions = storageState.getBlock() instanceof StorageBlockBase storageBlock ? storageBlock.getNeighborPos(storageState, pos, direction) : List.of(pos.relative(direction));
List<LazyOptional<IItemHandler>> caches = new ArrayList<>();
AtomicBoolean refreshOnEveryNeighborChange = new AtomicBoolean(false);
offsetPositions.forEach(offsetPos ->
WorldHelper.getLoadedBlockEntity(level, offsetPos).ifPresent(blockEntity -> {
if (blockEntity instanceof StorageInputBlockEntity input) {
refreshOnEveryNeighborChange.set(true);
blockEntity = input.getControllerPos().map(level::getBlockEntity).orElse(blockEntity);
}

LazyOptional<IItemHandler> lazyOptional = blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER, direction.getOpposite());
if (lazyOptional.isPresent()) {
lazyOptional.addListener(l -> updateCacheOnSide(level, pos, direction));
caches.add(lazyOptional);
}
}));
handlerCache.put(direction, caches);
handlerCache.put(direction, new ItemHandlerHolder(caches, refreshOnEveryNeighborChange.get()));
}

private List<LazyOptional<IItemHandler>> getItemHandlers(Level level, BlockPos pos, Direction direction) {
if (!handlerCache.containsKey(direction)) {
updateCacheOnSide(level, pos, direction);
}
return handlerCache.getOrDefault(direction, Collections.emptyList());
return handlerCache.containsKey(direction) ? handlerCache.get(direction).handlers() : Collections.emptyList();
}

public ContentsFilterLogic getInputFilterLogic() {
Expand Down Expand Up @@ -319,4 +332,7 @@ public void initDirections(Direction pushDirection, Direction pullDirection) {
setPushingTo(pushDirection, true);
setPullingFrom(pullDirection, true);
}

private record ItemHandlerHolder(List<LazyOptional<IItemHandler>> handlers, boolean refreshOnEveryNeighborChange) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
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.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<ItemStackKey> inventoryFilterStacks = new HashSet<>();
private final LoadingCache<IItemHandler, Set<ItemStackKey>> inventoryCache = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.SECONDS).build(new CacheLoader<>() {
@Override
public Set<ItemStackKey> load(IItemHandler inventory) {
return InventoryHelper.getUniqueStacks(inventory);
}
});

public TargetContentsFilterLogic(ItemStack upgrade, Consumer<ItemStack> saveHandler, int filterSlotCount, Supplier<InventoryHandler> getInventoryHandler, MemorySettingsCategory memorySettings, String parentTagKey) {
super(upgrade, saveHandler, filterSlotCount, getInventoryHandler, memorySettings, parentTagKey);
}

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;
}
}

0 comments on commit 0a86229

Please sign in to comment.