diff --git a/src/main/java/appeng/me/cache/NetworkMonitor.java b/src/main/java/appeng/me/cache/NetworkMonitor.java index 89a8bc40fdb..6902e12f335 100644 --- a/src/main/java/appeng/me/cache/NetworkMonitor.java +++ b/src/main/java/appeng/me/cache/NetworkMonitor.java @@ -166,7 +166,7 @@ public boolean validForPass(final int i) { @Nullable @SuppressWarnings("unchecked") - private IMEInventoryHandler getHandler() { + public IMEInventoryHandler getHandler() { switch (this.myChannel) { case ITEMS -> { return (IMEInventoryHandler) this.myGridCache.getItemInventoryHandler(); diff --git a/src/main/java/appeng/me/storage/MEInventoryHandler.java b/src/main/java/appeng/me/storage/MEInventoryHandler.java index c169e733c82..bbb14525150 100644 --- a/src/main/java/appeng/me/storage/MEInventoryHandler.java +++ b/src/main/java/appeng/me/storage/MEInventoryHandler.java @@ -10,6 +10,10 @@ package appeng.me.storage; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Map; import java.util.function.Predicate; import javax.annotation.Nonnull; @@ -24,11 +28,14 @@ import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; +import appeng.me.cache.NetworkMonitor; import appeng.util.prioitylist.DefaultPriorityList; import appeng.util.prioitylist.IPartitionList; public class MEInventoryHandler> implements IMEInventoryHandler { + private static final ThreadLocal, IItemList>>> networkItemsForIteration = new ThreadLocal<>(); + private final IMEInventoryHandler internal; private int myPriority; private IncludeExclude myWhitelist; @@ -124,7 +131,7 @@ public IItemList getAvailableItems(final IItemList out, int iteration) { if (this.isExtractFilterActive() && !this.myExtractPartitionList.isEmpty()) { return this.filterAvailableItems(out, iteration); } else { - return this.internal.getAvailableItems(out, iteration); + return this.getAvailableItems(out, iteration, e -> true); } } @@ -133,17 +140,66 @@ public boolean isVisible() { } protected IItemList filterAvailableItems(IItemList out, int iteration) { - final IItemList allAvailableItems = this.internal - .getAvailableItems((IItemList) this.internal.getChannel().createList(), iteration); Predicate filterCondition = this.getExtractFilterCondition(); - for (T item : allAvailableItems) { - if (filterCondition.test(item)) { - out.add(item); + getAvailableItems(out, iteration, filterCondition); + return out; + } + + private IItemList getAvailableItems(IItemList out, int iteration, Predicate filterCondition) { + final IItemList allAvailableItems = this.getAllAvailableItems(iteration); + Iterator it = allAvailableItems.iterator(); + while (it.hasNext()) { + T items = it.next(); + if (filterCondition.test(items)) { + out.add(items); + // have to remove the item otherwise it could be counted double + it.remove(); } } return out; } + private IItemList getAllAvailableItems(int iteration) { + NetworkInventoryHandler networkInventoryHandler = getNetworkInventoryHandler(); + if (networkInventoryHandler == null) { + return this.internal.getAvailableItems((IItemList) this.internal.getChannel().createList(), iteration); + } + + Map, IItemList>> s = networkItemsForIteration.get(); + if (s != null && !s.containsKey(iteration)) { + s = null; + } + if (s == null) { + s = Collections.singletonMap(iteration, new IdentityHashMap<>()); + networkItemsForIteration.set(s); + } + Map, IItemList> networkInventoryItems = s.get(iteration); + if (!networkInventoryItems.containsKey(networkInventoryHandler)) { + IItemList allAvailableItems = this.internal + .getAvailableItems((IItemList) this.internal.getChannel().createList(), iteration); + networkInventoryItems.put(networkInventoryHandler, allAvailableItems); + } + + return (IItemList) networkInventoryItems.get(networkInventoryHandler); + } + + private NetworkInventoryHandler getNetworkInventoryHandler() { + return (NetworkInventoryHandler) findNetworkInventoryHandler(this.getInternal()); + } + + // should give back the NetworkInventoryHandler for storage buses, everything else can be null + private NetworkInventoryHandler findNetworkInventoryHandler(IMEInventory inventory) { + if (inventory instanceof MEPassThroughpassThrough) { + return findNetworkInventoryHandler(passThrough.getInternal()); + } else if (inventory instanceof NetworkMonitornetworkMonitor) { + return findNetworkInventoryHandler(networkMonitor.getHandler()); + } else if (inventory instanceof NetworkInventoryHandlernetworkInventoryHandler) { + return networkInventoryHandler; + } else { + return null; + } + } + @Override public T getAvailableItem(@Nonnull T request, int iteration) { if (!this.hasReadAccess && !isVisible()) {