From 01fe5c7a8b3f8f0f76450137234b53732a9e0243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Wed, 16 Jun 2021 19:15:55 -0300 Subject: [PATCH 1/3] jei transfer tweaks..again --- .../core/sync/packets/PacketJEIRecipe.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main/java/appeng/core/sync/packets/PacketJEIRecipe.java b/src/main/java/appeng/core/sync/packets/PacketJEIRecipe.java index 0b00cdc53..052cabd7a 100644 --- a/src/main/java/appeng/core/sync/packets/PacketJEIRecipe.java +++ b/src/main/java/appeng/core/sync/packets/PacketJEIRecipe.java @@ -212,23 +212,21 @@ public class PacketJEIRecipe extends AppEngPacket out = Platform.poweredExtraction( energy, storage, request, cct.getActionSource() ); if( out == null ) { - Collection outList = inv.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().findFuzzy( request, FuzzyMode.IGNORE_ALL ); - IAEItemStack mostDamaged = null; - for( IAEItemStack is : outList ) + if( request.getItem().isDamageable() || ( Platform.isModLoaded( "gregtech" ) && request.getItem() instanceof MetaTool ) ) { - if( !is.isCraftable() && (is.getItem().isDamageable() || (Platform.isModLoaded( "gregtech" ) && is.getItem() instanceof MetaTool ) ) ) + Collection outList = inv.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().findFuzzy( request, FuzzyMode.IGNORE_ALL ); + for( IAEItemStack is : outList ) { - if( mostDamaged == null || mostDamaged.getItemDamage() < is.getItemDamage() ) + if( is.getDefinition().getMetadata() == request.getDefinition().getMetadata() ) { - mostDamaged = is; + out = Platform.poweredExtraction( energy, storage, is.copy().setStackSize( 1 ), cct.getActionSource() ); + } + if( out != null ) + { + break; } } } - if( mostDamaged != null ) - { - mostDamaged.setStackSize( 1 ); - out = Platform.poweredExtraction( energy, storage, mostDamaged, cct.getActionSource() ); - } } } else From 0fb393820b37e929df4eafd9a8f4f6afcdd0a198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Wed, 16 Jun 2021 22:21:07 -0300 Subject: [PATCH 2/3] half-undo wip --- .../appeng/parts/misc/ItemHandlerAdapter.java | 153 +++++++++++------- .../parts/misc/ItemRepositoryAdapter.java | 143 +++++++++++----- .../appeng/util/inv/ItemHandlerIterator.java | 2 +- 3 files changed, 194 insertions(+), 104 deletions(-) diff --git a/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java b/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java index ae534e0a5..6e398cb5f 100644 --- a/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java +++ b/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java @@ -19,6 +19,7 @@ package appeng.parts.misc; +import javax.annotation.Nullable; import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.config.Settings; @@ -35,20 +36,17 @@ import appeng.core.AELog; import appeng.me.GridAccessException; import appeng.me.helpers.IGridProxyable; import appeng.me.storage.ITickingMonitor; -import appeng.util.Platform; import appeng.util.inv.ItemHandlerIterator; import appeng.util.inv.ItemSlot; import appeng.util.item.AEItemStack; +import com.google.common.primitives.Ints; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.item.ItemStack; import net.minecraftforge.items.IItemHandler; -import org.apache.commons.lang3.tuple.Pair; +import net.minecraftforge.items.ItemHandlerHelper; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; /** @@ -63,6 +61,8 @@ class ItemHandlerAdapter implements IMEInventory, IBaseMonitor, IBaseMonitor, IBaseMonitor, IBaseMonitor, IBaseMonitor { - private IItemList cachedAeStacks = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + private IAEItemStack[] cachedAeStacks = new IAEItemStack[0]; private final IItemHandler itemHandler; private final StorageFilter mode; @@ -280,7 +286,7 @@ class ItemHandlerAdapter implements IMEInventory, IBaseMonitor getAvailableItems( IItemList out ) { - this.cachedAeStacks.forEach( out::add ); + Arrays.stream( this.cachedAeStacks ).forEach( out::add ); return out; } @@ -292,63 +298,90 @@ class ItemHandlerAdapter implements IMEInventory, IBaseMonitor update() { final List changes = new ArrayList<>(); + final int slots = this.itemHandler.getSlots(); - IItemList storage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + // Make room for new slots + if( slots > this.cachedAeStacks.length ) + { + this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots ); + } for( final ItemSlot is : this ) { - final ItemStack stackInSlot = !is.isExtractable() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY ? ItemStack.EMPTY : is.getItemStack(); - if( !stackInSlot.isEmpty() ) - { - storage.add( AEItemStack.fromItemStack( stackInSlot ) ); - } + // Save the old stuff + final IAEItemStack oldAeIS = this.cachedAeStacks[is.getSlot()]; + final ItemStack newIS = !is.isExtractable() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY ? ItemStack.EMPTY : is.getItemStack(); + + this.handlePossibleSlotChanges( is.getSlot(), oldAeIS, newIS, changes ); } - - IItemList newCachedAeStacks = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); - - Iterator cachedAeStacksIterator = cachedAeStacks.iterator(); - while ( cachedAeStacksIterator.hasNext() ) + // Handle cases where the number of slots actually is lower now than before + if( slots < this.cachedAeStacks.length ) { - IAEItemStack cachedStack = cachedAeStacksIterator.next(); - IAEItemStack storedStack = storage.findPrecise( cachedStack ); - if( storedStack == null ) + for( int slot = slots; slot < this.cachedAeStacks.length; slot++ ) { - changes.add( cachedStack.setStackSize( -cachedStack.getStackSize() ) ); - } - else - { - newCachedAeStacks.add( storedStack ); - if( cachedStack.getStackSize() != storedStack.getStackSize() ) + final IAEItemStack aeStack = this.cachedAeStacks[slot]; + + if( aeStack != null ) { - handleStackSizeChanged( cachedStack, storedStack, changes ); + final IAEItemStack a = aeStack.copy(); + a.setStackSize( -a.getStackSize() ); + changes.add( a ); } } - } - for( IAEItemStack storedStack : storage ) - { - if( cachedAeStacks.findPrecise( storedStack ) == null ) - { - newCachedAeStacks.add( storedStack ); - changes.add( storedStack.copy() ); - } + // Reduce the cache size + this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots ); } - this.cachedAeStacks = newCachedAeStacks; - return changes; } - private void handleStackSizeChanged( IAEItemStack cachedStack, IAEItemStack storedStack, List changes ) + private void handlePossibleSlotChanges( int slot, IAEItemStack oldAeIS, ItemStack newIS, List changes ) + { + if( oldAeIS != null && oldAeIS.isSameType( newIS ) ) + { + this.handleStackSizeChanged( slot, oldAeIS, newIS, changes ); + } + else + { + this.handleItemChanged( slot, oldAeIS, newIS, changes ); + } + } + + private void handleStackSizeChanged( int slot, IAEItemStack oldAeIS, ItemStack newIS, List changes ) { // Still the same item, but amount might have changed - final long diff = storedStack.getStackSize() - cachedStack.getStackSize(); + final long diff = newIS.getCount() - oldAeIS.getStackSize(); if( diff != 0 ) { - final IAEItemStack diffStack = cachedStack.copy(); - diffStack.setStackSize( diff ); - changes.add( diffStack ); + final IAEItemStack stack = oldAeIS.copy(); + stack.setStackSize( newIS.getCount() ); + + this.cachedAeStacks[slot] = stack; + + final IAEItemStack a = stack.copy(); + a.setStackSize( diff ); + changes.add( a ); + } + } + + private void handleItemChanged( int slot, IAEItemStack oldAeIS, ItemStack newIS, List changes ) + { + // Completely different item + this.cachedAeStacks[slot] = AEItemStack.fromItemStack( newIS ); + + // If we had a stack previously in this slot, notify the network about its disappearance + if( oldAeIS != null ) + { + oldAeIS.setStackSize( -oldAeIS.getStackSize() ); + changes.add( oldAeIS ); + } + + // Notify the network about the new stack. Note that this is null if newIS was null + if( this.cachedAeStacks[slot] != null ) + { + changes.add( this.cachedAeStacks[slot] ); } } diff --git a/src/main/java/appeng/parts/misc/ItemRepositoryAdapter.java b/src/main/java/appeng/parts/misc/ItemRepositoryAdapter.java index 684159731..02724c9f0 100644 --- a/src/main/java/appeng/parts/misc/ItemRepositoryAdapter.java +++ b/src/main/java/appeng/parts/misc/ItemRepositoryAdapter.java @@ -1,5 +1,6 @@ package appeng.parts.misc; +import javax.annotation.Nullable; import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.networking.security.IActionSource; @@ -16,15 +17,15 @@ import appeng.me.GridAccessException; import appeng.me.helpers.IGridProxyable; import appeng.me.storage.ITickingMonitor; import appeng.util.item.AEItemStack; +import com.google.common.primitives.Ints; import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.item.ItemStack; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; + /** * Wraps an Item Repository in such a way that it can be used as an IMEInventory for items. @@ -39,6 +40,7 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< private final IGridProxyable proxyable; private final InventoryCache cache; + private ItemStack stackCache; ItemRepositoryAdapter( IItemRepository itemRepository, IGridProxyable proxy ) { @@ -50,12 +52,29 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< @Override public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src ) { - ItemStack orgInput = iox.createItemStack(); - ItemStack remaining = orgInput; + // Try to reuse the cached stack + @Nullable ItemStack currentCached = stackCache; + stackCache = null; - boolean simulate = ( type == Actionable.SIMULATE ); + ItemStack orgInput; + if( currentCached != null && iox.isSameType( currentCached ) ) + { + // Cache is suitable, just update the count + orgInput = currentCached; + currentCached.setCount( Ints.saturatedCast( iox.getStackSize() ) ); + } + else + { + // We need a new stack :-( + orgInput = iox.createItemStack(); + } + ItemStack remaining = this.itemRepository.insertItem( orgInput, type == Actionable.SIMULATE ); - remaining = this.itemRepository.insertItem( remaining, simulate ); + // Store the stack in the cache for next time. + if (!remaining.isEmpty() && remaining != orgInput) + { + stackCache = remaining; + } // At this point, we still have some items left... if( remaining == orgInput ) @@ -83,12 +102,11 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< @Override public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src ) { - ItemStack requestedItemStack = request.getDefinition(); - int remainingSize = (int) Math.min( Integer.MAX_VALUE, request.getStackSize() ); + int remainingSize = Ints.saturatedCast(request.getStackSize()); final boolean simulate = ( mode == Actionable.SIMULATE ); - ItemStack extracted = this.itemRepository.extractItem( requestedItemStack, remainingSize, simulate ); + ItemStack extracted = this.itemRepository.extractItem( request.getDefinition(), remainingSize, simulate ); if( extracted.getCount() > remainingSize ) { @@ -184,7 +202,7 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< private static class InventoryCache { - private IItemList cachedAeStacks = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + private IAEItemStack[] cachedAeStacks = new IAEItemStack[0]; private final IItemRepository iItemRepository; public InventoryCache( IItemRepository iItemRepository ) @@ -194,7 +212,7 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< public IItemList getAvailableItems( IItemList out ) { - this.cachedAeStacks.forEach( out::add ); + Arrays.stream( this.cachedAeStacks ).forEach( out::add ); return out; } @@ -202,54 +220,93 @@ class ItemRepositoryAdapter implements IMEInventory, IBaseMonitor< { final List changes = new ArrayList<>(); - IItemList storage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); - this.iItemRepository.getAllItems().stream().map( s -> AEItemStack.fromItemStack( s.itemPrototype ).setStackSize( s.count ) ).forEach( storage::add ); + List out = this.iItemRepository.getAllItems().stream().map( s -> AEItemStack.fromItemStack( s.itemPrototype ).setStackSize( s.count ) ).collect( Collectors.toList() ); - IItemList newCachedAeStacks = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + final int size = out.size(); - Iterator cachedAeStacksIterator = cachedAeStacks.iterator(); - while ( cachedAeStacksIterator.hasNext() ) + // Make room for new slots + if( size > this.cachedAeStacks.length ) { - IAEItemStack cachedStack = cachedAeStacksIterator.next(); - IAEItemStack storedStack = storage.findPrecise( cachedStack ); - if( storedStack == null ) + this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, size ); + } + + for( int x = 0; x < size; x++ ) + { + // Save the old stuff + final IAEItemStack oldAeIS = this.cachedAeStacks[x]; + final IAEItemStack newIS = out.get( x ); + + this.handlePossibleSlotChanges( x, oldAeIS, newIS, changes ); + } + + // Handle cases where the number of slots actually is lower now than before + if( size < this.cachedAeStacks.length ) + { + for( int x = 0; x < this.cachedAeStacks.length; x++ ) { - changes.add( cachedStack.setStackSize( -cachedStack.getStackSize() ) ); - } - else - { - newCachedAeStacks.add( storedStack ); - if( cachedStack.getStackSize() != storedStack.getStackSize() ) + final IAEItemStack aeStack = this.cachedAeStacks[x]; + + if( aeStack != null ) { - handleStackSizeChanged( cachedStack, storedStack, changes ); + final IAEItemStack a = aeStack.copy(); + a.setStackSize( -a.getStackSize() ); + changes.add( a ); } } - } - for( IAEItemStack storedStack : storage ) - { - if( cachedAeStacks.findPrecise( storedStack ) == null ) - { - newCachedAeStacks.add( storedStack ); - changes.add( storedStack.copy() ); - } + // Reduce the cache size + this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, size ); } - this.cachedAeStacks = newCachedAeStacks; - return changes; } - private void handleStackSizeChanged( IAEItemStack cachedStack, IAEItemStack storedStack, List changes ) + private void handlePossibleSlotChanges( int slot, IAEItemStack oldAeIS, IAEItemStack newIS, List changes ) + { + if( oldAeIS != null && oldAeIS.isSameType( newIS ) ) + { + this.handleStackSizeChanged( slot, oldAeIS, newIS, changes ); + } + else + { + this.handleItemChanged( slot, oldAeIS, newIS, changes ); + } + } + + private void handleStackSizeChanged( int slot, IAEItemStack oldAeIS, IAEItemStack newIS, List changes ) { // Still the same item, but amount might have changed - final long diff = storedStack.getStackSize() - cachedStack.getStackSize(); + final long diff = newIS.getStackSize() - oldAeIS.getStackSize(); if( diff != 0 ) { - final IAEItemStack diffStack = cachedStack.copy(); - diffStack.setStackSize( diff ); - changes.add( diffStack ); + final IAEItemStack stack = oldAeIS.copy(); + stack.setStackSize( newIS.getStackSize() ); + + this.cachedAeStacks[slot] = stack; + + final IAEItemStack a = stack.copy(); + a.setStackSize( diff ); + changes.add( a ); + } + } + + private void handleItemChanged( int slot, IAEItemStack oldAeIS, IAEItemStack newIS, List changes ) + { + // Completely different item + this.cachedAeStacks[slot] = newIS ; + + // If we had a stack previously in this slot, notify the network about its disappearance + if( oldAeIS != null ) + { + oldAeIS.setStackSize( -oldAeIS.getStackSize() ); + changes.add( oldAeIS ); + } + + // Notify the network about the new stack. Note that this is null if newIS was null + if( this.cachedAeStacks[slot] != null ) + { + changes.add( this.cachedAeStacks[slot] ); } } diff --git a/src/main/java/appeng/util/inv/ItemHandlerIterator.java b/src/main/java/appeng/util/inv/ItemHandlerIterator.java index ca36a63aa..bbd78b388 100644 --- a/src/main/java/appeng/util/inv/ItemHandlerIterator.java +++ b/src/main/java/appeng/util/inv/ItemHandlerIterator.java @@ -52,7 +52,7 @@ public class ItemHandlerIterator implements Iterator { throw new NoSuchElementException(); } - this.itemSlot.setExtractable( !this.itemHandler.extractItem( this.slot, 1, true ).isEmpty() ); + this.itemSlot.setExtractable( !this.itemHandler.extractItem( this.slot, Integer.MAX_VALUE, true ).isEmpty() ); this.itemSlot.setItemStack( this.itemHandler.getStackInSlot( this.slot ) ); this.itemSlot.setSlot( this.slot ); this.slot++; From eab695b692b7a40dc3e22715da781400a0de3b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salom=C3=A3o?= Date: Thu, 17 Jun 2021 23:32:16 -0300 Subject: [PATCH 3/3] try to not void fluids in fluid terminal when running out of power --- src/main/java/appeng/container/slot/AppEngSlot.java | 2 +- src/main/java/appeng/core/api/ApiStorage.java | 2 +- .../appeng/fluids/container/ContainerFluidTerminal.java | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/appeng/container/slot/AppEngSlot.java b/src/main/java/appeng/container/slot/AppEngSlot.java index 4992a31d4..8fd494707 100644 --- a/src/main/java/appeng/container/slot/AppEngSlot.java +++ b/src/main/java/appeng/container/slot/AppEngSlot.java @@ -157,7 +157,7 @@ public class AppEngSlot extends Slot { if( this.isSlotEnabled() ) { - return !this.itemHandler.extractItem( this.index, 1, true ).isEmpty(); + return !this.itemHandler.extractItem( this.index, Integer.MAX_VALUE, true ).isEmpty(); } return false; } diff --git a/src/main/java/appeng/core/api/ApiStorage.java b/src/main/java/appeng/core/api/ApiStorage.java index 3fa4b90c8..522926600 100644 --- a/src/main/java/appeng/core/api/ApiStorage.java +++ b/src/main/java/appeng/core/api/ApiStorage.java @@ -175,7 +175,7 @@ public class ApiStorage implements IStorageHelper @Override public int transferFactor() { - return 125; + return 1000; } @Override diff --git a/src/main/java/appeng/fluids/container/ContainerFluidTerminal.java b/src/main/java/appeng/fluids/container/ContainerFluidTerminal.java index cc570f473..139d4365d 100644 --- a/src/main/java/appeng/fluids/container/ContainerFluidTerminal.java +++ b/src/main/java/appeng/fluids/container/ContainerFluidTerminal.java @@ -446,7 +446,11 @@ public class ContainerFluidTerminal extends AEBaseContainer implements IConfigMa if( notInserted != null && notInserted.getStackSize() > 0 ) { - AELog.error( "Fluid item [%s] reported a different possible amount to drain than it actually provided.", held.getDisplayName() ); + IAEFluidStack spill = this.monitor.injectItems( notInserted, Actionable.MODULATE, this.getActionSource() ); + if( spill != null && spill.getStackSize() > 0 ) + { + fh.fill( spill.getFluidStack(), true ); + } } player.inventory.setItemStack( fh.getContainer() );