Added External Storage API (#1460). Fixed bug where External Storage could only handle 1 fluid inventory per block (#1034).

This commit is contained in:
raoulvdberge
2018-06-26 19:02:56 +02:00
parent 7465970667
commit 06a762022c
35 changed files with 777 additions and 473 deletions

View File

@@ -21,6 +21,7 @@ NOTE: Worlds that used Refined Storage 1.5.x are fully compatible with Refined S
- Fixed bug where storage disks in Portable Grids could be moved into themselves (raoulvdberge) - Fixed bug where storage disks in Portable Grids could be moved into themselves (raoulvdberge)
- Fixed the Crafter crashing when opening it while connected to a Primal Tech Grill or Kiln (raoulvdberge) - Fixed the Crafter crashing when opening it while connected to a Primal Tech Grill or Kiln (raoulvdberge)
- Fixed bug where Crafting Upgrade on Interface kept too many items in stock (raoulvdberge) - Fixed bug where Crafting Upgrade on Interface kept too many items in stock (raoulvdberge)
- Fixed bug where External Storage could only handle 1 fluid inventory per block (raoulvdberge)
- Prevent accidental Grid scrollbar click after clicking JEI recipe transfer button (raoulvdberge) - Prevent accidental Grid scrollbar click after clicking JEI recipe transfer button (raoulvdberge)
- Added a missing config option for Crafter Manager energy usage (raoulvdberge) - Added a missing config option for Crafter Manager energy usage (raoulvdberge)
- If an Interface is configured to expose the entire network storage (by configuring no export slots), it will no longer expose the entire RS storage, due to performance issues (raoulvdberge) - If an Interface is configured to expose the entire network storage (by configuring no export slots), it will no longer expose the entire RS storage, due to performance issues (raoulvdberge)

View File

@@ -14,10 +14,12 @@ import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeRegistry;
import com.raoulvdberge.refinedstorage.api.network.readerwriter.IReaderWriterChannel; import com.raoulvdberge.refinedstorage.api.network.readerwriter.IReaderWriterChannel;
import com.raoulvdberge.refinedstorage.api.network.readerwriter.IReaderWriterHandlerRegistry; import com.raoulvdberge.refinedstorage.api.network.readerwriter.IReaderWriterHandlerRegistry;
import com.raoulvdberge.refinedstorage.api.solderer.ISoldererRegistry; import com.raoulvdberge.refinedstorage.api.solderer.ISoldererRegistry;
import com.raoulvdberge.refinedstorage.api.storage.StorageType;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskManager; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskManager;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskRegistry; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskRegistry;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSync; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSync;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;
import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IOneSixMigrationHelper; import com.raoulvdberge.refinedstorage.api.util.IOneSixMigrationHelper;
import com.raoulvdberge.refinedstorage.api.util.IQuantityFormatter; import com.raoulvdberge.refinedstorage.api.util.IQuantityFormatter;
@@ -146,6 +148,20 @@ public interface IRSAPI {
@Nonnull @Nonnull
IStorageDiskSync getStorageDiskSync(); IStorageDiskSync getStorageDiskSync();
/**
* Adds an external storage provider for the given storage type.
*
* @param type the storage type
* @param provider the external storage provider
*/
void addExternalStorageProvider(StorageType type, IExternalStorageProvider provider);
/**
* @param type the type
* @return a list of external storage providers
*/
List<IExternalStorageProvider> getExternalStorageProviders(StorageType type);
/** /**
* @param world the world * @param world the world
* @param capacity the capacity * @param capacity the capacity

View File

@@ -0,0 +1,9 @@
package com.raoulvdberge.refinedstorage.api.storage;
/**
* The storage type.
*/
public enum StorageType {
ITEM,
FLUID
}

View File

@@ -1,5 +1,6 @@
package com.raoulvdberge.refinedstorage.api.storage.disk; package com.raoulvdberge.refinedstorage.api.storage.disk;
import com.raoulvdberge.refinedstorage.api.storage.StorageType;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import java.util.UUID; import java.util.UUID;
@@ -36,5 +37,5 @@ public interface IStorageDiskProvider {
/** /**
* @return the storage type * @return the storage type
*/ */
StorageDiskType getType(); StorageType getType();
} }

View File

@@ -1,9 +0,0 @@
package com.raoulvdberge.refinedstorage.api.storage.disk;
/**
* The storage disk type.
*/
public enum StorageDiskType {
ITEM,
FLUID
}

View File

@@ -0,0 +1,32 @@
package com.raoulvdberge.refinedstorage.api.storage.externalstorage;
import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
/**
* Provides information about an external storage.
*/
public interface IExternalStorageContext {
/**
* @return the priority of the external storage
*/
int getPriority();
/**
* @return the access type of the external storage
*/
AccessType getAccessType();
/**
* @param stack the stack to test
* @return true if the external storage accepts the item, false otherwise
*/
boolean acceptsItem(ItemStack stack);
/**
* @param stack the stack to test
* @return true if the external storage accepts the fluid, false otherwise
*/
boolean acceptsFluid(FluidStack stack);
}

View File

@@ -0,0 +1,30 @@
package com.raoulvdberge.refinedstorage.api.storage.externalstorage;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import javax.annotation.Nonnull;
import java.util.function.Supplier;
/**
* Provides an external storage handler to the external storage block.
*
* @param <T>
*/
public interface IExternalStorageProvider<T> {
/**
* @param tile the tile
* @param direction the direction of the external storage
* @return true if the provider can provide, false otherwise
*/
boolean canProvide(TileEntity tile, EnumFacing direction);
/**
* @param context the context of the external storage
* @param tile the tile supplier
* @param direction the direction of the external storage
* @return the external storage handler
*/
@Nonnull
IStorageExternal<T> provide(IExternalStorageContext context, Supplier<TileEntity> tile, EnumFacing direction);
}

View File

@@ -0,0 +1,27 @@
package com.raoulvdberge.refinedstorage.api.storage.externalstorage;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.storage.IStorage;
/**
* An external storage handler.
*
* @param <T>
*/
public interface IStorageExternal<T> extends IStorage<T> {
/**
* For storage disks and blocks, the network detects changes and updates the {@link com.raoulvdberge.refinedstorage.api.storage.IStorageCache} accordingly.
* However, for blocks connected to an external storage the external storage itself is responsible for bookkeeping the changes
* and submitting them to the {@link com.raoulvdberge.refinedstorage.api.storage.IStorageCache}. That bookkeeping is supposed to happen in this method.
* <p>
* It's called every external storage tick.
*
* @param network the network
*/
void update(INetwork network);
/**
* @return the capacity of the connected storage
*/
int getCapacity();
}

View File

@@ -18,10 +18,12 @@ import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeRegistry;
import com.raoulvdberge.refinedstorage.api.network.readerwriter.IReaderWriterChannel; import com.raoulvdberge.refinedstorage.api.network.readerwriter.IReaderWriterChannel;
import com.raoulvdberge.refinedstorage.api.network.readerwriter.IReaderWriterHandlerRegistry; import com.raoulvdberge.refinedstorage.api.network.readerwriter.IReaderWriterHandlerRegistry;
import com.raoulvdberge.refinedstorage.api.solderer.ISoldererRegistry; import com.raoulvdberge.refinedstorage.api.solderer.ISoldererRegistry;
import com.raoulvdberge.refinedstorage.api.storage.StorageType;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskManager; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskManager;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskRegistry; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskRegistry;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSync; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSync;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;
import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IOneSixMigrationHelper; import com.raoulvdberge.refinedstorage.api.util.IOneSixMigrationHelper;
import com.raoulvdberge.refinedstorage.api.util.IQuantityFormatter; import com.raoulvdberge.refinedstorage.api.util.IQuantityFormatter;
@@ -55,9 +57,7 @@ import net.minecraftforge.fml.common.discovery.ASMDataTable;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.LinkedList; import java.util.*;
import java.util.List;
import java.util.Set;
public class API implements IRSAPI { public class API implements IRSAPI {
private static final IRSAPI INSTANCE = new API(); private static final IRSAPI INSTANCE = new API();
@@ -74,6 +74,7 @@ public class API implements IRSAPI {
private IStorageDiskRegistry storageDiskRegistry = new StorageDiskRegistry(); private IStorageDiskRegistry storageDiskRegistry = new StorageDiskRegistry();
private IStorageDiskSync storageDiskSync = new StorageDiskSync(); private IStorageDiskSync storageDiskSync = new StorageDiskSync();
private IOneSixMigrationHelper oneSixMigrationHelper = new OneSixMigrationHelper(); private IOneSixMigrationHelper oneSixMigrationHelper = new OneSixMigrationHelper();
private Map<StorageType, List<IExternalStorageProvider>> externalStorageProviders = new HashMap<>();
private List<ICraftingPatternRenderHandler> patternRenderHandlers = new LinkedList<>(); private List<ICraftingPatternRenderHandler> patternRenderHandlers = new LinkedList<>();
public static IRSAPI instance() { public static IRSAPI instance() {
@@ -230,6 +231,18 @@ public class API implements IRSAPI {
return storageDiskSync; return storageDiskSync;
} }
@Override
public void addExternalStorageProvider(StorageType type, IExternalStorageProvider provider) {
externalStorageProviders.computeIfAbsent(type, k -> new ArrayList<>()).add(provider);
}
@Override
public List<IExternalStorageProvider> getExternalStorageProviders(StorageType type) {
List<IExternalStorageProvider> providers = externalStorageProviders.get(type);
return providers == null ? Collections.emptyList() : providers;
}
@Override @Override
@Nonnull @Nonnull
public IStorageDisk<ItemStack> createDefaultItemDisk(World world, int capacity) { public IStorageDisk<ItemStack> createDefaultItemDisk(World world, int capacity) {

View File

@@ -92,7 +92,7 @@ public class NetworkNodeDestructor extends NetworkNode implements IComparable, I
if (entity instanceof EntityItem) { if (entity instanceof EntityItem) {
ItemStack droppedItem = ((EntityItem) entity).getItem(); ItemStack droppedItem = ((EntityItem) entity).getItem();
if (IFilterable.canTake(itemFilters, mode, compare, droppedItem) && network.insertItem(droppedItem, droppedItem.getCount(), true) == null) { if (IFilterable.acceptsItem(itemFilters, mode, compare, droppedItem) && network.insertItem(droppedItem, droppedItem.getCount(), true) == null) {
network.insertItemTracked(droppedItem.copy(), droppedItem.getCount()); network.insertItemTracked(droppedItem.copy(), droppedItem.getCount());
world.removeEntity(entity); world.removeEntity(entity);
@@ -114,7 +114,7 @@ public class NetworkNodeDestructor extends NetworkNode implements IComparable, I
); );
if (!frontStack.isEmpty()) { if (!frontStack.isEmpty()) {
if (IFilterable.canTake(itemFilters, mode, compare, frontStack) && frontBlockState.getBlockHardness(world, front) != -1.0) { if (IFilterable.acceptsItem(itemFilters, mode, compare, frontStack) && frontBlockState.getBlockHardness(world, front) != -1.0) {
NonNullList<ItemStack> drops = NonNullList.create(); NonNullList<ItemStack> drops = NonNullList.create();
if (frontBlock instanceof BlockShulkerBox) { if (frontBlock instanceof BlockShulkerBox) {
@@ -171,7 +171,7 @@ public class NetworkNodeDestructor extends NetworkNode implements IComparable, I
if (handler != null) { if (handler != null) {
FluidStack stack = handler.drain(Fluid.BUCKET_VOLUME, false); FluidStack stack = handler.drain(Fluid.BUCKET_VOLUME, false);
if (stack != null && IFilterable.canTakeFluids(fluidFilters, mode, compare, stack) && network.insertFluid(stack, stack.amount, true) == null) { if (stack != null && IFilterable.acceptsFluid(fluidFilters, mode, compare, stack) && network.insertFluid(stack, stack.amount, true) == null) {
FluidStack drained = handler.drain(Fluid.BUCKET_VOLUME, true); FluidStack drained = handler.drain(Fluid.BUCKET_VOLUME, true);
network.insertFluid(drained, drained.amount, false); network.insertFluid(drained, drained.amount, false);

View File

@@ -1,17 +1,19 @@
package com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage; package com.raoulvdberge.refinedstorage.apiimpl.network.node;
import com.raoulvdberge.refinedstorage.RS; import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.storage.AccessType; import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.api.storage.IStorage; import com.raoulvdberge.refinedstorage.api.storage.IStorage;
import com.raoulvdberge.refinedstorage.api.storage.IStorageProvider; import com.raoulvdberge.refinedstorage.api.storage.IStorageProvider;
import com.raoulvdberge.refinedstorage.api.storage.StorageType;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageContext;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IStorageExternal;
import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.IGuiStorage; import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.NetworkNode;
import com.raoulvdberge.refinedstorage.apiimpl.storage.StorageCacheFluid; import com.raoulvdberge.refinedstorage.apiimpl.storage.StorageCacheFluid;
import com.raoulvdberge.refinedstorage.apiimpl.storage.StorageCacheItem; import com.raoulvdberge.refinedstorage.apiimpl.storage.StorageCacheItem;
import com.raoulvdberge.refinedstorage.apiimpl.util.OneSixMigrationHelper; import com.raoulvdberge.refinedstorage.apiimpl.util.OneSixMigrationHelper;
import com.raoulvdberge.refinedstorage.capability.CapabilityNetworkNodeProxy;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerBase; import com.raoulvdberge.refinedstorage.inventory.ItemHandlerBase;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerFluid; import com.raoulvdberge.refinedstorage.inventory.ItemHandlerFluid;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerListenerNetworkNode; import com.raoulvdberge.refinedstorage.inventory.ItemHandlerListenerNetworkNode;
@@ -20,20 +22,18 @@ import com.raoulvdberge.refinedstorage.tile.config.*;
import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter; import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter;
import com.raoulvdberge.refinedstorage.util.AccessTypeUtils; import com.raoulvdberge.refinedstorage.util.AccessTypeUtils;
import com.raoulvdberge.refinedstorage.util.StackUtils; import com.raoulvdberge.refinedstorage.util.StackUtils;
import com.raoulvdberge.refinedstorage.util.WorldUtils;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
public class NetworkNodeExternalStorage extends NetworkNode implements IStorageProvider, IGuiStorage, IComparable, IFilterable, IPrioritizable, IType, IAccessType { public class NetworkNodeExternalStorage extends NetworkNode implements IStorageProvider, IGuiStorage, IComparable, IFilterable, IPrioritizable, IType, IAccessType, IExternalStorageContext {
public static final String ID = "external_storage"; public static final String ID = "external_storage";
private static final String NBT_PRIORITY = "Priority"; private static final String NBT_PRIORITY = "Priority";
@@ -51,8 +51,8 @@ public class NetworkNodeExternalStorage extends NetworkNode implements IStorageP
private AccessType accessType = AccessType.INSERT_EXTRACT; private AccessType accessType = AccessType.INSERT_EXTRACT;
private int networkTicks; private int networkTicks;
private List<StorageItemExternal> itemStorages = new CopyOnWriteArrayList<>(); private List<IStorageExternal<ItemStack>> itemStorages = new CopyOnWriteArrayList<>();
private List<StorageFluidExternal> fluidStorages = new CopyOnWriteArrayList<>(); private List<IStorageExternal<FluidStack>> fluidStorages = new CopyOnWriteArrayList<>();
public NetworkNodeExternalStorage(World world, BlockPos pos) { public NetworkNodeExternalStorage(World world, BlockPos pos) {
super(world, pos); super(world, pos);
@@ -81,20 +81,12 @@ public class NetworkNodeExternalStorage extends NetworkNode implements IStorageP
return; return;
} }
for (StorageItemExternal storage : itemStorages) { for (IStorageExternal<ItemStack> storage : itemStorages) {
storage.detectChanges(network); storage.update(network);
} }
boolean fluidChangeDetected = false; for (IStorageExternal<FluidStack> storage : fluidStorages) {
storage.update(network);
for (StorageFluidExternal storage : fluidStorages) {
if (storage.updateCache()) {
fluidChangeDetected = true;
}
}
if (fluidChangeDetected) {
network.getFluidStorageCache().invalidate();
} }
} }
} }
@@ -145,7 +137,7 @@ public class NetworkNodeExternalStorage extends NetworkNode implements IStorageP
} }
accessType = AccessTypeUtils.readAccessType(tag); accessType = AccessTypeUtils.readAccessType(tag);
OneSixMigrationHelper.migrateEmptyWhitelistToEmptyBlacklist(version, this, itemFilters, fluidFilters); OneSixMigrationHelper.migrateEmptyWhitelistToEmptyBlacklist(version, this, itemFilters, fluidFilters);
} }
@@ -196,19 +188,19 @@ public class NetworkNodeExternalStorage extends NetworkNode implements IStorageP
TileEntity facing = getFacingTile(); TileEntity facing = getFacingTile();
if (type == IType.ITEMS) { if (facing != null) {
if (facing != null && !(facing.hasCapability(CapabilityNetworkNodeProxy.NETWORK_NODE_PROXY_CAPABILITY, getDirection().getOpposite()) && facing.getCapability(CapabilityNetworkNodeProxy.NETWORK_NODE_PROXY_CAPABILITY, getDirection().getOpposite()).getNode() instanceof IStorageProvider)) { if (type == IType.ITEMS) {
IItemHandler itemHandler = WorldUtils.getItemHandler(facing, getDirection().getOpposite()); for (IExternalStorageProvider provider : API.instance().getExternalStorageProviders(StorageType.ITEM)) {
if (provider.canProvide(facing, getDirection())) {
if (itemHandler != null) { itemStorages.add(provider.provide(this, () -> getFacingTile(), getDirection()));
itemStorages.add(new StorageItemItemHandler(this, () -> WorldUtils.getItemHandler(getFacingTile(), getDirection().getOpposite()))); }
}
} else if (type == IType.FLUIDS) {
for (IExternalStorageProvider provider : API.instance().getExternalStorageProviders(StorageType.FLUID)) {
if (provider.canProvide(facing, getDirection())) {
fluidStorages.add(provider.provide(this, () -> getFacingTile(), getDirection()));
}
} }
}
} else if (type == IType.FLUIDS) {
IFluidHandler fluidHandler = WorldUtils.getFluidHandler(facing, getDirection().getOpposite());
if (fluidHandler != null) {
fluidStorages.add(new StorageFluidExternal(this, () -> WorldUtils.getFluidHandler(getFacingTile(), getDirection().getOpposite())));
} }
} }
@@ -271,6 +263,16 @@ public class NetworkNodeExternalStorage extends NetworkNode implements IStorageP
return accessType; return accessType;
} }
@Override
public boolean acceptsItem(ItemStack stack) {
return IFilterable.acceptsItem(itemFilters, mode, compare, stack);
}
@Override
public boolean acceptsFluid(FluidStack stack) {
return IFilterable.acceptsFluid(fluidFilters, mode, compare, stack);
}
@Override @Override
public void setAccessType(AccessType type) { public void setAccessType(AccessType type) {
this.accessType = type; this.accessType = type;
@@ -309,19 +311,11 @@ public class NetworkNodeExternalStorage extends NetworkNode implements IStorageP
return getType() == IType.ITEMS ? itemFilters : fluidFilters; return getType() == IType.ITEMS ? itemFilters : fluidFilters;
} }
public ItemHandlerBase getItemFilters() { public List<IStorageExternal<ItemStack>> getItemStorages() {
return itemFilters;
}
public ItemHandlerFluid getFluidFilters() {
return fluidFilters;
}
public List<StorageItemExternal> getItemStorages() {
return itemStorages; return itemStorages;
} }
public List<StorageFluidExternal> getFluidStorages() { public List<IStorageExternal<FluidStack>> getFluidStorages() {
return fluidStorages; return fluidStorages;
} }
} }

View File

@@ -79,7 +79,7 @@ public class NetworkNodeImporter extends NetworkNode implements IComparable, IFi
ItemStack stack = handler.getStackInSlot(currentSlot); ItemStack stack = handler.getStackInSlot(currentSlot);
if (!IFilterable.canTake(itemFilters, mode, compare, stack)) { if (!IFilterable.acceptsItem(itemFilters, mode, compare, stack)) {
currentSlot++; currentSlot++;
} else if (ticks % upgrades.getSpeed() == 0) { } else if (ticks % upgrades.getSpeed() == 0) {
ItemStack result = handler.extractItem(currentSlot, upgrades.getItemInteractCount(), true); ItemStack result = handler.extractItem(currentSlot, upgrades.getItemInteractCount(), true);
@@ -101,7 +101,7 @@ public class NetworkNodeImporter extends NetworkNode implements IComparable, IFi
if (handler != null) { if (handler != null) {
FluidStack stack = handler.drain(Fluid.BUCKET_VOLUME, false); FluidStack stack = handler.drain(Fluid.BUCKET_VOLUME, false);
if (stack != null && IFilterable.canTakeFluids(fluidFilters, mode, compare, stack) && network.insertFluid(stack, stack.amount, true) == null) { if (stack != null && IFilterable.acceptsFluid(fluidFilters, mode, compare, stack) && network.insertFluid(stack, stack.amount, true) == null) {
FluidStack toDrain = handler.drain(Fluid.BUCKET_VOLUME * upgrades.getItemInteractCount(), false); FluidStack toDrain = handler.drain(Fluid.BUCKET_VOLUME * upgrades.getItemInteractCount(), false);
if (toDrain != null) { if (toDrain != null) {

View File

@@ -4,7 +4,7 @@ import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingRequester; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingRequester;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage.StorageItemItemHandler; import com.raoulvdberge.refinedstorage.apiimpl.storage.externalstorage.StorageExternalItem;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerBase; import com.raoulvdberge.refinedstorage.inventory.ItemHandlerBase;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerListenerNetworkNode; import com.raoulvdberge.refinedstorage.inventory.ItemHandlerListenerNetworkNode;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerProxy; import com.raoulvdberge.refinedstorage.inventory.ItemHandlerProxy;
@@ -93,7 +93,7 @@ public class NetworkNodeInterface extends NetworkNode implements IComparable {
int delta = got.isEmpty() ? wanted.getCount() : (wanted.getCount() - got.getCount()); int delta = got.isEmpty() ? wanted.getCount() : (wanted.getCount() - got.getCount());
if (delta > 0) { if (delta > 0) {
ItemStack result = network.extractItem(wanted, delta, compare, false, s -> !(s instanceof StorageItemItemHandler) || !((StorageItemItemHandler) s).isConnectedToInterface()); ItemStack result = network.extractItem(wanted, delta, compare, false, s -> !(s instanceof StorageExternalItem) || !((StorageExternalItem) s).isConnectedToInterface());
if (result != null) { if (result != null) {
if (exportItems.getStackInSlot(i).isEmpty()) { if (exportItems.getStackInSlot(i).isEmpty()) {

View File

@@ -56,7 +56,7 @@ public class StorageDiskFluidDriveWrapper implements IStorageDisk<FluidStack> {
@Override @Override
@Nullable @Nullable
public FluidStack insert(@Nonnull FluidStack stack, int size, boolean simulate) { public FluidStack insert(@Nonnull FluidStack stack, int size, boolean simulate) {
if (!IFilterable.canTakeFluids(diskDrive.getFluidFilters(), diskDrive.getMode(), diskDrive.getCompare(), stack)) { if (!IFilterable.acceptsFluid(diskDrive.getFluidFilters(), diskDrive.getMode(), diskDrive.getCompare(), stack)) {
return StackUtils.copy(stack, size); return StackUtils.copy(stack, size);
} }

View File

@@ -56,7 +56,7 @@ public class StorageDiskItemDriveWrapper implements IStorageDisk<ItemStack> {
@Override @Override
@Nullable @Nullable
public ItemStack insert(@Nonnull ItemStack stack, int size, boolean simulate) { public ItemStack insert(@Nonnull ItemStack stack, int size, boolean simulate) {
if (!IFilterable.canTake(diskDrive.getItemFilters(), diskDrive.getMode(), diskDrive.getCompare(), stack)) { if (!IFilterable.acceptsItem(diskDrive.getItemFilters(), diskDrive.getMode(), diskDrive.getCompare(), stack)) {
return ItemHandlerHelper.copyStackWithSize(stack, size); return ItemHandlerHelper.copyStackWithSize(stack, size);
} }

View File

@@ -66,7 +66,7 @@ public class StorageDiskFluidManipulatorWrapper implements IStorageDisk<FluidSta
@Override @Override
@Nullable @Nullable
public FluidStack insert(@Nonnull FluidStack stack, int size, boolean simulate) { public FluidStack insert(@Nonnull FluidStack stack, int size, boolean simulate) {
if (!IFilterable.canTakeFluids(diskManipulator.getFluidFilters(), diskManipulator.getMode(), diskManipulator.getCompare(), stack)) { if (!IFilterable.acceptsFluid(diskManipulator.getFluidFilters(), diskManipulator.getMode(), diskManipulator.getCompare(), stack)) {
return StackUtils.copy(stack, size); return StackUtils.copy(stack, size);
} }
@@ -76,7 +76,7 @@ public class StorageDiskFluidManipulatorWrapper implements IStorageDisk<FluidSta
@Override @Override
@Nullable @Nullable
public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, boolean simulate) { public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, boolean simulate) {
if (!IFilterable.canTakeFluids(diskManipulator.getFluidFilters(), diskManipulator.getMode(), diskManipulator.getCompare(), stack)) { if (!IFilterable.acceptsFluid(diskManipulator.getFluidFilters(), diskManipulator.getMode(), diskManipulator.getCompare(), stack)) {
return null; return null;
} }

View File

@@ -61,7 +61,7 @@ public class StorageDiskItemManipulatorWrapper implements IStorageDisk<ItemStack
@Override @Override
@Nullable @Nullable
public ItemStack insert(@Nonnull ItemStack stack, int size, boolean simulate) { public ItemStack insert(@Nonnull ItemStack stack, int size, boolean simulate) {
if (!IFilterable.canTake(diskManipulator.getItemFilters(), diskManipulator.getMode(), diskManipulator.getCompare(), stack)) { if (!IFilterable.acceptsItem(diskManipulator.getItemFilters(), diskManipulator.getMode(), diskManipulator.getCompare(), stack)) {
return ItemHandlerHelper.copyStackWithSize(stack, size); return ItemHandlerHelper.copyStackWithSize(stack, size);
} }
@@ -71,7 +71,7 @@ public class StorageDiskItemManipulatorWrapper implements IStorageDisk<ItemStack
@Override @Override
@Nullable @Nullable
public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, boolean simulate) { public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, boolean simulate) {
if (!IFilterable.canTake(diskManipulator.getItemFilters(), diskManipulator.getMode(), diskManipulator.getCompare(), stack)) { if (!IFilterable.acceptsItem(diskManipulator.getItemFilters(), diskManipulator.getMode(), diskManipulator.getCompare(), stack)) {
return null; return null;
} }

View File

@@ -1,123 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage;
import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.api.storage.IStorage;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.tile.config.IFilterable;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;
public class StorageFluidExternal implements IStorage<FluidStack> {
private FluidStack cache;
private NetworkNodeExternalStorage externalStorage;
private Supplier<IFluidHandler> handlerSupplier;
public StorageFluidExternal(NetworkNodeExternalStorage externalStorage, Supplier<IFluidHandler> handlerSupplier) {
this.externalStorage = externalStorage;
this.handlerSupplier = handlerSupplier;
}
private IFluidTankProperties getProperties() {
IFluidHandler handler = handlerSupplier.get();
return (handler != null && handler.getTankProperties() != null && handler.getTankProperties().length != 0) ? handler.getTankProperties()[0] : null;
}
private FluidStack getContents() {
return getProperties() == null ? null : getProperties().getContents();
}
@Override
public Collection<FluidStack> getStacks() {
return getContents() == null ? Collections.emptyList() : Collections.singletonList(getContents().copy());
}
@Override
@Nullable
public FluidStack insert(@Nonnull FluidStack stack, int size, boolean simulate) {
if (getProperties() != null && IFilterable.canTakeFluids(externalStorage.getFluidFilters(), externalStorage.getMode(), externalStorage.getCompare(), stack) && getProperties().canFillFluidType(stack)) {
int filled = handlerSupplier.get().fill(StackUtils.copy(stack, size), !simulate);
if (filled == size) {
return null;
}
return StackUtils.copy(stack, size - filled);
}
return StackUtils.copy(stack, size);
}
@Override
@Nullable
public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, boolean simulate) {
IFluidHandler handler = handlerSupplier.get();
if (handler == null) {
return null;
}
FluidStack toDrain = StackUtils.copy(stack, size);
if (API.instance().getComparer().isEqual(getContents(), toDrain, flags)) {
return handler.drain(toDrain, !simulate);
}
return null;
}
@Override
public int getStored() {
return getContents() != null ? getContents().amount : 0;
}
public int getCapacity() {
return getProperties() != null ? getProperties().getCapacity() : 0;
}
@Override
public int getPriority() {
return externalStorage.getPriority();
}
public AccessType getAccessType() {
return externalStorage.getAccessType();
}
@Override
public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) {
if (getAccessType() == AccessType.INSERT) {
return 0;
}
return remainder == null ? size : (size - remainder.amount);
}
public boolean updateCache() {
FluidStack stack = getContents();
if (cache == null) {
cache = StackUtils.copy(stack);
} else if (!API.instance().getComparer().isEqual(stack, cache, IComparer.COMPARE_NBT | IComparer.COMPARE_QUANTITY)) {
cache = StackUtils.copy(stack);
return true;
}
return false;
}
public void updateCacheForcefully() {
cache = StackUtils.copy(getContents());
}
}

View File

@@ -1,94 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.api.storage.IStorage;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import net.minecraft.item.ItemStack;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
public abstract class StorageItemExternal implements IStorage<ItemStack> {
private List<ItemStack> cache;
public abstract int getCapacity();
public void detectChanges(INetwork network) {
// If we are insert only, we don't care about sending changes
if (getAccessType() == AccessType.INSERT) {
return;
}
if (cache == null) {
cache = new ArrayList<>(getStacks());
return;
}
List<ItemStack> newStacks = new ArrayList<>(getStacks());
for (int i = 0; i < newStacks.size(); ++i) {
ItemStack actual = newStacks.get(i);
// If we exceed the cache size, than that means this item is added
if (i >= cache.size()) {
if (!actual.isEmpty()) {
network.getItemStorageCache().add(actual, actual.getCount(), false, true);
}
continue;
}
ItemStack cached = cache.get(i);
if (!cached.isEmpty() && actual.isEmpty()) {
// If the cached is not empty but the actual is, we remove this item
network.getItemStorageCache().remove(cached, cached.getCount(), true);
} else if (cached.isEmpty() && !actual.isEmpty()) {
// If the cached is empty and the actual isn't, we added this item
network.getItemStorageCache().add(actual, actual.getCount(), false, true);
network.getCraftingManager().track(actual, actual.getCount());
} else if (cached.isEmpty() && actual.isEmpty()) {
// If they're both empty, nothing happens
} else if (!API.instance().getComparer().isEqualNoQuantity(cached, actual)) {
// If both items mismatch, remove the old and add the new
network.getItemStorageCache().remove(cached, cached.getCount(), true);
network.getItemStorageCache().add(actual, actual.getCount(), false, true);
network.getCraftingManager().track(actual, actual.getCount());
} else if (cached.getCount() != actual.getCount()) {
int delta = actual.getCount() - cached.getCount();
if (delta > 0) {
network.getItemStorageCache().add(actual, delta, false, true);
network.getCraftingManager().track(actual, delta);
} else {
network.getItemStorageCache().remove(actual, Math.abs(delta), true);
}
}
}
// If the cache size is somehow bigger than the actual stacks, that means the inventory shrunk
// In that case, we remove the items that have been removed due to the shrinkage
if (cache.size() > newStacks.size()) {
for (int i = newStacks.size(); i < cache.size(); ++i) {
if (cache.get(i) != ItemStack.EMPTY) {
network.getItemStorageCache().remove(cache.get(i), cache.get(i).getCount(), true);
}
}
}
this.cache = newStacks;
network.getItemStorageCache().flush();
}
@Override
public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) {
return remainder == null ? size : (size - remainder.getCount());
}
}

View File

@@ -1,142 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage;
import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.tile.TileInterface;
import com.raoulvdberge.refinedstorage.tile.config.IFilterable;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
public class StorageItemItemHandler extends StorageItemExternal {
private NetworkNodeExternalStorage externalStorage;
private Supplier<IItemHandler> handlerSupplier;
private boolean connectedToInterface;
public StorageItemItemHandler(NetworkNodeExternalStorage externalStorage, Supplier<IItemHandler> handlerSupplier) {
this.externalStorage = externalStorage;
this.handlerSupplier = handlerSupplier;
this.connectedToInterface = externalStorage.getFacingTile() instanceof TileInterface;
}
public boolean isConnectedToInterface() {
return connectedToInterface;
}
@Override
public int getCapacity() {
IItemHandler handler = handlerSupplier.get();
if (handler == null) {
return 0;
}
int capacity = 0;
for (int i = 0; i < handler.getSlots(); ++i) {
capacity += Math.min(handler.getSlotLimit(i), handler.getStackInSlot(i).getMaxStackSize());
}
return capacity;
}
@Override
public Collection<ItemStack> getStacks() {
IItemHandler handler = handlerSupplier.get();
if (handler == null) {
return Collections.emptyList();
}
List<ItemStack> stacks = new ArrayList<>();
for (int i = 0; i < handler.getSlots(); ++i) {
stacks.add(handler.getStackInSlot(i).copy());
}
return stacks;
}
@Override
public ItemStack insert(@Nonnull ItemStack stack, int size, boolean simulate) {
IItemHandler handler = handlerSupplier.get();
if (handler != null && IFilterable.canTake(externalStorage.getItemFilters(), externalStorage.getMode(), externalStorage.getCompare(), stack)) {
return StackUtils.emptyToNull(ItemHandlerHelper.insertItem(handler, ItemHandlerHelper.copyStackWithSize(stack, size), simulate));
}
return ItemHandlerHelper.copyStackWithSize(stack, size);
}
@Override
public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, boolean simulate) {
int remaining = size;
ItemStack received = null;
IItemHandler handler = handlerSupplier.get();
if (handler == null) {
return null;
}
for (int i = 0; i < handler.getSlots(); ++i) {
ItemStack slot = handler.getStackInSlot(i);
if (!slot.isEmpty() && API.instance().getComparer().isEqual(slot, stack, flags)) {
ItemStack got = handler.extractItem(i, remaining, simulate);
if (!got.isEmpty()) {
if (received == null) {
received = got.copy();
} else {
received.grow(got.getCount());
}
remaining -= got.getCount();
if (remaining == 0) {
break;
}
}
}
}
return received;
}
@Override
public int getStored() {
IItemHandler handler = handlerSupplier.get();
if (handler == null) {
return 0;
}
int size = 0;
for (int i = 0; i < handler.getSlots(); ++i) {
size += handler.getStackInSlot(i).getCount();
}
return size;
}
@Override
public int getPriority() {
return externalStorage.getPriority();
}
@Override
public AccessType getAccessType() {
return externalStorage.getAccessType();
}
}

View File

@@ -41,7 +41,7 @@ public class StorageDiskFluidStorageWrapper implements IStorageDisk<FluidStack>
@Override @Override
@Nullable @Nullable
public FluidStack insert(@Nonnull FluidStack stack, int size, boolean simulate) { public FluidStack insert(@Nonnull FluidStack stack, int size, boolean simulate) {
if (!IFilterable.canTakeFluids(storage.getFilters(), storage.getMode(), storage.getCompare(), stack)) { if (!IFilterable.acceptsFluid(storage.getFilters(), storage.getMode(), storage.getCompare(), stack)) {
return StackUtils.copy(stack, size); return StackUtils.copy(stack, size);
} }

View File

@@ -41,7 +41,7 @@ public class StorageDiskItemStorageWrapper implements IStorageDisk<ItemStack> {
@Override @Override
@Nullable @Nullable
public ItemStack insert(@Nonnull ItemStack stack, int size, boolean simulate) { public ItemStack insert(@Nonnull ItemStack stack, int size, boolean simulate) {
if (!IFilterable.canTake(storage.getFilters(), storage.getMode(), storage.getCompare(), stack)) { if (!IFilterable.acceptsItem(storage.getFilters(), storage.getMode(), storage.getCompare(), stack)) {
return ItemHandlerHelper.copyStackWithSize(stack, size); return ItemHandlerHelper.copyStackWithSize(stack, size);
} }

View File

@@ -5,8 +5,10 @@ import com.raoulvdberge.refinedstorage.api.storage.*;
import com.raoulvdberge.refinedstorage.api.util.IStackList; import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.API;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@@ -19,6 +21,7 @@ public class StorageCacheFluid implements IStorageCache<FluidStack> {
private CopyOnWriteArrayList<IStorage<FluidStack>> storages = new CopyOnWriteArrayList<>(); private CopyOnWriteArrayList<IStorage<FluidStack>> storages = new CopyOnWriteArrayList<>();
private IStackList<FluidStack> list = API.instance().createFluidStackList(); private IStackList<FluidStack> list = API.instance().createFluidStackList();
private List<IStorageCacheListener<FluidStack>> listeners = new LinkedList<>(); private List<IStorageCacheListener<FluidStack>> listeners = new LinkedList<>();
private List<Pair<FluidStack, Integer>> batchedChanges = new ArrayList<>();
public StorageCacheFluid(INetwork network) { public StorageCacheFluid(INetwork network) {
this.network = network; this.network = network;
@@ -54,20 +57,31 @@ public class StorageCacheFluid implements IStorageCache<FluidStack> {
list.add(stack, size); list.add(stack, size);
if (!rebuilding) { if (!rebuilding) {
listeners.forEach(l -> l.onChanged(stack, size)); if (!batched) {
listeners.forEach(l -> l.onChanged(stack, size));
} else {
batchedChanges.add(Pair.of(stack, size));
}
} }
} }
@Override @Override
public synchronized void remove(@Nonnull FluidStack stack, int size, boolean batched) { public synchronized void remove(@Nonnull FluidStack stack, int size, boolean batched) {
if (list.remove(stack, size)) { if (list.remove(stack, size)) {
listeners.forEach(l -> l.onChanged(stack, -size)); if (!batched) {
listeners.forEach(l -> l.onChanged(stack, -size));
} else {
batchedChanges.add(Pair.of(stack, -size));
}
} }
} }
@Override @Override
public void flush() { public void flush() {
throw new UnsupportedOperationException("Cannot flush fluid storage cache"); if (!batchedChanges.isEmpty()) {
batchedChanges.forEach(c -> listeners.forEach(l -> l.onChanged(c.getKey(), c.getValue())));
batchedChanges.clear();
}
} }
@Override @Override

View File

@@ -0,0 +1,25 @@
package com.raoulvdberge.refinedstorage.apiimpl.storage.externalstorage;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageContext;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IStorageExternal;
import com.raoulvdberge.refinedstorage.util.WorldUtils;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nonnull;
import java.util.function.Supplier;
public class ExternalStorageProviderFluid implements IExternalStorageProvider<FluidStack> {
@Override
public boolean canProvide(TileEntity tile, EnumFacing direction) {
return WorldUtils.getFluidHandler(tile, direction.getOpposite()) != null;
}
@Nonnull
@Override
public IStorageExternal<FluidStack> provide(IExternalStorageContext context, Supplier<TileEntity> tile, EnumFacing direction) {
return new StorageExternalFluid(context, () -> WorldUtils.getFluidHandler(tile.get(), direction.getOpposite()));
}
}

View File

@@ -0,0 +1,36 @@
package com.raoulvdberge.refinedstorage.apiimpl.storage.externalstorage;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeProxy;
import com.raoulvdberge.refinedstorage.api.storage.IStorageProvider;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageContext;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IStorageExternal;
import com.raoulvdberge.refinedstorage.capability.CapabilityNetworkNodeProxy;
import com.raoulvdberge.refinedstorage.tile.TileInterface;
import com.raoulvdberge.refinedstorage.util.WorldUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import javax.annotation.Nonnull;
import java.util.function.Supplier;
public class ExternalStorageProviderItem implements IExternalStorageProvider<ItemStack> {
@Override
public boolean canProvide(TileEntity tile, EnumFacing direction) {
boolean isNode = tile.hasCapability(CapabilityNetworkNodeProxy.NETWORK_NODE_PROXY_CAPABILITY, direction.getOpposite());
INetworkNodeProxy nodeProxy = tile.getCapability(CapabilityNetworkNodeProxy.NETWORK_NODE_PROXY_CAPABILITY, direction.getOpposite());
if (!(isNode && nodeProxy.getNode() instanceof IStorageProvider)) {
return WorldUtils.getItemHandler(tile, direction.getOpposite()) != null;
}
return false;
}
@Nonnull
@Override
public IStorageExternal<ItemStack> provide(IExternalStorageContext context, Supplier<TileEntity> tile, EnumFacing direction) {
return new StorageExternalItem(context, () -> WorldUtils.getItemHandler(tile.get(), direction.getOpposite()), tile.get() instanceof TileInterface);
}
}

View File

@@ -0,0 +1,224 @@
package com.raoulvdberge.refinedstorage.apiimpl.storage.externalstorage;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageContext;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IStorageExternal;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
public class StorageExternalFluid implements IStorageExternal<FluidStack> {
private IExternalStorageContext context;
private Supplier<IFluidHandler> handlerSupplier;
private List<FluidStack> cache;
public StorageExternalFluid(IExternalStorageContext context, Supplier<IFluidHandler> handlerSupplier) {
this.context = context;
this.handlerSupplier = handlerSupplier;
}
@Nullable
private IFluidTankProperties[] getProperties() {
IFluidHandler handler = handlerSupplier.get();
return (handler != null && handler.getTankProperties() != null && handler.getTankProperties().length != 0) ? handler.getTankProperties() : null;
}
@Override
public void update(INetwork network) {
// If we are insert only, we don't care about sending changes
if (getAccessType() == AccessType.INSERT) {
return;
}
if (cache == null) {
cache = new ArrayList<>(getStacksWithNulls());
return;
}
List<FluidStack> newStacks = new ArrayList<>(getStacksWithNulls());
for (int i = 0; i < newStacks.size(); ++i) {
FluidStack actual = newStacks.get(i);
// If we exceed the cache size, than that means this item is added
if (i >= cache.size()) {
if (actual != null) {
network.getFluidStorageCache().add(actual, actual.amount, false, true);
}
continue;
}
FluidStack cached = cache.get(i);
if (actual == null && cached == null) {
// NO OP
} else if (actual == null && cached != null) {
network.getFluidStorageCache().remove(cached, cached.amount, true);
} else if (actual != null && cached == null) {
network.getFluidStorageCache().add(actual, actual.amount, false, true);
} else if (!API.instance().getComparer().isEqual(actual, cached, IComparer.COMPARE_NBT)) {
network.getFluidStorageCache().remove(cached, cached.amount, true);
network.getFluidStorageCache().add(actual, actual.amount, false, true);
} else if (actual.amount > cached.amount) {
network.getFluidStorageCache().add(actual, actual.amount - cached.amount, false, true);
} else if (actual.amount < cached.amount) {
network.getFluidStorageCache().remove(actual, cached.amount - actual.amount, true);
}
}
if (cache.size() > newStacks.size()) {
for (int i = newStacks.size(); i < cache.size(); ++i) {
if (cache.get(i) != null) {
network.getFluidStorageCache().remove(cache.get(i), cache.get(i).amount, true);
}
}
}
this.cache = newStacks;
network.getFluidStorageCache().flush();
}
@Override
public int getCapacity() {
IFluidTankProperties[] props = getProperties();
if (props != null) {
int cap = 0;
for (IFluidTankProperties properties : props) {
cap += properties.getCapacity();
}
return cap;
}
return 0;
}
@Override
public Collection<FluidStack> getStacks() {
IFluidTankProperties[] props = getProperties();
if (props != null) {
List<FluidStack> fluids = new ArrayList<>();
for (IFluidTankProperties properties : props) {
FluidStack stack = properties.getContents();
if (stack != null) {
fluids.add(stack.copy());
}
}
return fluids;
}
return Collections.emptyList();
}
private Collection<FluidStack> getStacksWithNulls() {
IFluidTankProperties[] props = getProperties();
if (props != null) {
List<FluidStack> fluids = new ArrayList<>();
for (IFluidTankProperties properties : props) {
FluidStack stack = properties.getContents();
if (stack != null) {
fluids.add(stack.copy());
} else {
fluids.add(null);
}
}
return fluids;
}
return Collections.emptyList();
}
@Nullable
@Override
public FluidStack insert(@Nonnull FluidStack stack, int size, boolean simulate) {
if (context.acceptsFluid(stack)) {
int filled = handlerSupplier.get().fill(StackUtils.copy(stack, size), !simulate);
if (filled == size) {
return null;
}
return StackUtils.copy(stack, size - filled);
}
return StackUtils.copy(stack, size);
}
@Nullable
@Override
public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, boolean simulate) {
IFluidHandler handler = handlerSupplier.get();
if (handler == null) {
return null;
}
return handler.drain(StackUtils.copy(stack, size), !simulate);
}
@Override
public int getStored() {
IFluidTankProperties[] props = getProperties();
if (props != null) {
int stored = 0;
for (IFluidTankProperties properties : props) {
FluidStack contents = properties.getContents();
if (contents != null) {
stored += contents.amount;
}
}
return stored;
}
return 0;
}
@Override
public int getPriority() {
return context.getPriority();
}
@Override
public AccessType getAccessType() {
return context.getAccessType();
}
@Override
public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) {
if (getAccessType() == AccessType.INSERT) {
return 0;
}
return remainder == null ? size : (size - remainder.amount);
}
}

View File

@@ -0,0 +1,229 @@
package com.raoulvdberge.refinedstorage.apiimpl.storage.externalstorage;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageContext;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IStorageExternal;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
public class StorageExternalItem implements IStorageExternal<ItemStack> {
private IExternalStorageContext context;
private Supplier<IItemHandler> handlerSupplier;
private List<ItemStack> cache;
private boolean connectedToInterface;
public StorageExternalItem(IExternalStorageContext context, Supplier<IItemHandler> handlerSupplier, boolean connectedToInterface) {
this.context = context;
this.handlerSupplier = handlerSupplier;
this.connectedToInterface = connectedToInterface;
}
public boolean isConnectedToInterface() {
return connectedToInterface;
}
@Override
public void update(INetwork network) {
// If we are insert only, we don't care about sending changes
if (getAccessType() == AccessType.INSERT) {
return;
}
if (cache == null) {
cache = new ArrayList<>(getStacks());
return;
}
List<ItemStack> newStacks = new ArrayList<>(getStacks());
for (int i = 0; i < newStacks.size(); ++i) {
ItemStack actual = newStacks.get(i);
// If we exceed the cache size, than that means this item is added
if (i >= cache.size()) {
if (!actual.isEmpty()) {
network.getItemStorageCache().add(actual, actual.getCount(), false, true);
}
continue;
}
ItemStack cached = cache.get(i);
if (!cached.isEmpty() && actual.isEmpty()) {
// If the cached is not empty but the actual is, we remove this item
network.getItemStorageCache().remove(cached, cached.getCount(), true);
} else if (cached.isEmpty() && !actual.isEmpty()) {
// If the cached is empty and the actual isn't, we added this item
network.getItemStorageCache().add(actual, actual.getCount(), false, true);
network.getCraftingManager().track(actual, actual.getCount());
} else if (cached.isEmpty() && actual.isEmpty()) {
// If they're both empty, nothing happens
} else if (!API.instance().getComparer().isEqualNoQuantity(cached, actual)) {
// If both items mismatch, remove the old and add the new
network.getItemStorageCache().remove(cached, cached.getCount(), true);
network.getItemStorageCache().add(actual, actual.getCount(), false, true);
network.getCraftingManager().track(actual, actual.getCount());
} else if (cached.getCount() != actual.getCount()) {
int delta = actual.getCount() - cached.getCount();
if (delta > 0) {
network.getItemStorageCache().add(actual, delta, false, true);
network.getCraftingManager().track(actual, delta);
} else {
network.getItemStorageCache().remove(actual, Math.abs(delta), true);
}
}
}
// If the cache size is somehow bigger than the actual stacks, that means the inventory shrunk
// In that case, we remove the items that have been removed due to the shrinkage
if (cache.size() > newStacks.size()) {
for (int i = newStacks.size(); i < cache.size(); ++i) {
if (cache.get(i) != ItemStack.EMPTY) {
network.getItemStorageCache().remove(cache.get(i), cache.get(i).getCount(), true);
}
}
}
this.cache = newStacks;
network.getItemStorageCache().flush();
}
@Override
public int getCapacity() {
IItemHandler handler = handlerSupplier.get();
if (handler == null) {
return 0;
}
int capacity = 0;
for (int i = 0; i < handler.getSlots(); ++i) {
capacity += Math.min(handler.getSlotLimit(i), handler.getStackInSlot(i).getMaxStackSize());
}
return capacity;
}
@Override
public Collection<ItemStack> getStacks() {
IItemHandler handler = handlerSupplier.get();
if (handler == null) {
return Collections.emptyList();
}
List<ItemStack> stacks = new ArrayList<>();
for (int i = 0; i < handler.getSlots(); ++i) {
stacks.add(handler.getStackInSlot(i).copy());
}
return stacks;
}
@Nullable
@Override
public ItemStack insert(@Nonnull ItemStack stack, int size, boolean simulate) {
IItemHandler handler = handlerSupplier.get();
if (handler != null && context.acceptsItem(stack)) {
return StackUtils.emptyToNull(ItemHandlerHelper.insertItem(handler, ItemHandlerHelper.copyStackWithSize(stack, size), simulate));
}
return ItemHandlerHelper.copyStackWithSize(stack, size);
}
@Nullable
@Override
public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, boolean simulate) {
int remaining = size;
ItemStack received = null;
IItemHandler handler = handlerSupplier.get();
if (handler == null) {
return null;
}
for (int i = 0; i < handler.getSlots(); ++i) {
ItemStack slot = handler.getStackInSlot(i);
if (!slot.isEmpty() && API.instance().getComparer().isEqual(slot, stack, flags)) {
ItemStack got = handler.extractItem(i, remaining, simulate);
if (!got.isEmpty()) {
if (received == null) {
received = got.copy();
} else {
received.grow(got.getCount());
}
remaining -= got.getCount();
if (remaining == 0) {
break;
}
}
}
}
return received;
}
@Override
public int getStored() {
IItemHandler handler = handlerSupplier.get();
if (handler == null) {
return 0;
}
int size = 0;
for (int i = 0; i < handler.getSlots(); ++i) {
size += handler.getStackInSlot(i).getCount();
}
return size;
}
@Override
public int getPriority() {
return context.getPriority();
}
@Override
public AccessType getAccessType() {
return context.getAccessType();
}
@Override
public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) {
if (getAccessType() == AccessType.INSERT) {
return 0;
}
return remainder == null ? size : (size - remainder.getCount());
}
}

View File

@@ -1,7 +1,7 @@
package com.raoulvdberge.refinedstorage.block; package com.raoulvdberge.refinedstorage.block;
import com.raoulvdberge.refinedstorage.RSGui; import com.raoulvdberge.refinedstorage.RSGui;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage.NetworkNodeExternalStorage; import com.raoulvdberge.refinedstorage.apiimpl.network.node.NetworkNodeExternalStorage;
import com.raoulvdberge.refinedstorage.tile.TileExternalStorage; import com.raoulvdberge.refinedstorage.tile.TileExternalStorage;
import com.raoulvdberge.refinedstorage.util.RenderUtils; import com.raoulvdberge.refinedstorage.util.RenderUtils;
import net.minecraft.block.Block; import net.minecraft.block.Block;

View File

@@ -1,10 +1,10 @@
package com.raoulvdberge.refinedstorage.item; package com.raoulvdberge.refinedstorage.item;
import com.raoulvdberge.refinedstorage.RSItems; import com.raoulvdberge.refinedstorage.RSItems;
import com.raoulvdberge.refinedstorage.api.storage.StorageType;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskProvider;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSyncData; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSyncData;
import com.raoulvdberge.refinedstorage.api.storage.disk.StorageDiskType;
import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.block.FluidStorageType; import com.raoulvdberge.refinedstorage.block.FluidStorageType;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
@@ -148,7 +148,7 @@ public class ItemFluidStorageDisk extends ItemBase implements IStorageDiskProvid
} }
@Override @Override
public StorageDiskType getType() { public StorageType getType() {
return StorageDiskType.FLUID; return StorageType.FLUID;
} }
} }

View File

@@ -1,10 +1,10 @@
package com.raoulvdberge.refinedstorage.item; package com.raoulvdberge.refinedstorage.item;
import com.raoulvdberge.refinedstorage.RSItems; import com.raoulvdberge.refinedstorage.RSItems;
import com.raoulvdberge.refinedstorage.api.storage.StorageType;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskProvider;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSyncData; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSyncData;
import com.raoulvdberge.refinedstorage.api.storage.disk.StorageDiskType;
import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.block.ItemStorageType; import com.raoulvdberge.refinedstorage.block.ItemStorageType;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
@@ -148,7 +148,7 @@ public class ItemStorageDisk extends ItemBase implements IStorageDiskProvider {
} }
@Override @Override
public StorageDiskType getType() { public StorageType getType() {
return StorageDiskType.ITEM; return StorageType.ITEM;
} }
} }

View File

@@ -5,6 +5,7 @@ import com.google.gson.JsonSyntaxException;
import com.raoulvdberge.refinedstorage.RS; import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.RSBlocks; import com.raoulvdberge.refinedstorage.RSBlocks;
import com.raoulvdberge.refinedstorage.RSItems; import com.raoulvdberge.refinedstorage.RSItems;
import com.raoulvdberge.refinedstorage.api.storage.StorageType;
import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementColor; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementColor;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementFluidRender; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementFluidRender;
@@ -25,6 +26,8 @@ import com.raoulvdberge.refinedstorage.apiimpl.network.readerwriter.ReaderWriter
import com.raoulvdberge.refinedstorage.apiimpl.solderer.SoldererRecipeLoader; import com.raoulvdberge.refinedstorage.apiimpl.solderer.SoldererRecipeLoader;
import com.raoulvdberge.refinedstorage.apiimpl.storage.disk.StorageDiskFactoryFluid; import com.raoulvdberge.refinedstorage.apiimpl.storage.disk.StorageDiskFactoryFluid;
import com.raoulvdberge.refinedstorage.apiimpl.storage.disk.StorageDiskFactoryItem; import com.raoulvdberge.refinedstorage.apiimpl.storage.disk.StorageDiskFactoryItem;
import com.raoulvdberge.refinedstorage.apiimpl.storage.externalstorage.ExternalStorageProviderFluid;
import com.raoulvdberge.refinedstorage.apiimpl.storage.externalstorage.ExternalStorageProviderItem;
import com.raoulvdberge.refinedstorage.apiimpl.util.OneSixMigrationHelper; import com.raoulvdberge.refinedstorage.apiimpl.util.OneSixMigrationHelper;
import com.raoulvdberge.refinedstorage.block.BlockBase; import com.raoulvdberge.refinedstorage.block.BlockBase;
import com.raoulvdberge.refinedstorage.capability.CapabilityNetworkNodeProxy; import com.raoulvdberge.refinedstorage.capability.CapabilityNetworkNodeProxy;
@@ -147,6 +150,9 @@ public class ProxyCommon {
API.instance().getStorageDiskRegistry().add(StorageDiskFactoryItem.ID, new StorageDiskFactoryItem()); API.instance().getStorageDiskRegistry().add(StorageDiskFactoryItem.ID, new StorageDiskFactoryItem());
API.instance().getStorageDiskRegistry().add(StorageDiskFactoryFluid.ID, new StorageDiskFactoryFluid()); API.instance().getStorageDiskRegistry().add(StorageDiskFactoryFluid.ID, new StorageDiskFactoryFluid());
API.instance().addExternalStorageProvider(StorageType.ITEM, new ExternalStorageProviderItem());
API.instance().addExternalStorageProvider(StorageType.FLUID, new ExternalStorageProviderFluid());
int id = 0; int id = 0;
RS.INSTANCE.network.registerMessage(MessageTileDataParameter.class, MessageTileDataParameter.class, id++, Side.CLIENT); RS.INSTANCE.network.registerMessage(MessageTileDataParameter.class, MessageTileDataParameter.class, id++, Side.CLIENT);

View File

@@ -20,14 +20,13 @@ import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.api.storage.IStorage; import com.raoulvdberge.refinedstorage.api.storage.IStorage;
import com.raoulvdberge.refinedstorage.api.storage.IStorageCache; import com.raoulvdberge.refinedstorage.api.storage.IStorageCache;
import com.raoulvdberge.refinedstorage.api.storage.IStorageTracker; import com.raoulvdberge.refinedstorage.api.storage.IStorageTracker;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IStorageExternal;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingManager; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingManager;
import com.raoulvdberge.refinedstorage.apiimpl.energy.Energy; import com.raoulvdberge.refinedstorage.apiimpl.energy.Energy;
import com.raoulvdberge.refinedstorage.apiimpl.network.NetworkNodeGraph; import com.raoulvdberge.refinedstorage.apiimpl.network.NetworkNodeGraph;
import com.raoulvdberge.refinedstorage.apiimpl.network.grid.handler.FluidGridHandler; import com.raoulvdberge.refinedstorage.apiimpl.network.grid.handler.FluidGridHandler;
import com.raoulvdberge.refinedstorage.apiimpl.network.grid.handler.ItemGridHandler; import com.raoulvdberge.refinedstorage.apiimpl.network.grid.handler.ItemGridHandler;
import com.raoulvdberge.refinedstorage.apiimpl.network.item.NetworkItemHandler; import com.raoulvdberge.refinedstorage.apiimpl.network.item.NetworkItemHandler;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage.StorageFluidExternal;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage.StorageItemExternal;
import com.raoulvdberge.refinedstorage.apiimpl.network.readerwriter.ReaderWriterManager; import com.raoulvdberge.refinedstorage.apiimpl.network.readerwriter.ReaderWriterManager;
import com.raoulvdberge.refinedstorage.apiimpl.network.security.SecurityManager; import com.raoulvdberge.refinedstorage.apiimpl.network.security.SecurityManager;
import com.raoulvdberge.refinedstorage.apiimpl.storage.StorageCacheFluid; import com.raoulvdberge.refinedstorage.apiimpl.storage.StorageCacheFluid;
@@ -319,8 +318,8 @@ public class TileController extends TileBase implements ITickable, INetwork, IRe
if (remainder == null) { if (remainder == null) {
// The external storage is responsible for sending changes, we don't need to anymore // The external storage is responsible for sending changes, we don't need to anymore
if (storage instanceof StorageItemExternal && !simulate) { if (storage instanceof IStorageExternal && !simulate) {
((StorageItemExternal) storage).detectChanges(this); ((IStorageExternal) storage).update(this);
insertedExternally += size; insertedExternally += size;
} }
@@ -328,8 +327,8 @@ public class TileController extends TileBase implements ITickable, INetwork, IRe
break; break;
} else { } else {
// The external storage is responsible for sending changes, we don't need to anymore // The external storage is responsible for sending changes, we don't need to anymore
if (size != remainder.getCount() && storage instanceof StorageItemExternal && !simulate) { if (size != remainder.getCount() && storage instanceof IStorageExternal && !simulate) {
((StorageItemExternal) storage).detectChanges(this); ((IStorageExternal) storage).update(this);
insertedExternally += size - remainder.getCount(); insertedExternally += size - remainder.getCount();
} }
@@ -363,8 +362,8 @@ public class TileController extends TileBase implements ITickable, INetwork, IRe
if (took != null) { if (took != null) {
// The external storage is responsible for sending changes, we don't need to anymore // The external storage is responsible for sending changes, we don't need to anymore
if (storage instanceof StorageItemExternal && !simulate) { if (storage instanceof IStorageExternal && !simulate) {
((StorageItemExternal) storage).detectChanges(this); ((IStorageExternal) storage).update(this);
extractedExternally += took.getCount(); extractedExternally += took.getCount();
} }
@@ -390,16 +389,17 @@ public class TileController extends TileBase implements ITickable, INetwork, IRe
return newStack; return newStack;
} }
@Nullable
@Override @Override
public FluidStack insertFluid(@Nonnull FluidStack stack, int size, boolean simulate) { public FluidStack insertFluid(@Nonnull FluidStack stack, int size, boolean simulate) {
if (fluidStorage.getStorages().isEmpty()) { if (stack == null || fluidStorage.getStorages().isEmpty()) {
return StackUtils.copy(stack, size); return StackUtils.copy(stack, size);
} }
FluidStack remainder = stack; FluidStack remainder = stack;
int inserted = 0; int inserted = 0;
int insertedExternally = 0;
for (IStorage<FluidStack> storage : this.fluidStorage.getStorages()) { for (IStorage<FluidStack> storage : this.fluidStorage.getStorages()) {
if (storage.getAccessType() == AccessType.EXTRACT) { if (storage.getAccessType() == AccessType.EXTRACT) {
@@ -414,30 +414,41 @@ public class TileController extends TileBase implements ITickable, INetwork, IRe
inserted += storage.getCacheDelta(storedPre, size, remainder); inserted += storage.getCacheDelta(storedPre, size, remainder);
} }
if (storage instanceof StorageFluidExternal && !simulate) {
((StorageFluidExternal) storage).updateCacheForcefully();
}
if (remainder == null) { if (remainder == null) {
// The external storage is responsible for sending changes, we don't need to anymore
if (storage instanceof IStorageExternal && !simulate) {
((IStorageExternal) storage).update(this);
insertedExternally += size;
}
break; break;
} else { } else {
// The external storage is responsible for sending changes, we don't need to anymore
if (size != remainder.amount && storage instanceof IStorageExternal && !simulate) {
((IStorageExternal) storage).update(this);
insertedExternally += size - remainder.amount;
}
size = remainder.amount; size = remainder.amount;
} }
} }
if (inserted > 0) { if (!simulate && inserted - insertedExternally > 0) {
fluidStorage.add(stack, inserted, false, false); fluidStorage.add(stack, inserted - insertedExternally, false, false);
} }
return remainder; return remainder;
} }
@Nullable
@Override @Override
public FluidStack extractFluid(@Nonnull FluidStack stack, int size, int flags, boolean simulate) { public FluidStack extractFluid(@Nonnull FluidStack stack, int size, int flags, boolean simulate) {
int requested = size; int requested = size;
int received = 0; int received = 0;
int extractedExternally = 0;
FluidStack newStack = null; FluidStack newStack = null;
for (IStorage<FluidStack> storage : this.fluidStorage.getStorages()) { for (IStorage<FluidStack> storage : this.fluidStorage.getStorages()) {
@@ -448,8 +459,11 @@ public class TileController extends TileBase implements ITickable, INetwork, IRe
} }
if (took != null) { if (took != null) {
if (storage instanceof StorageFluidExternal && !simulate) { // The external storage is responsible for sending changes, we don't need to anymore
((StorageFluidExternal) storage).updateCacheForcefully(); if (storage instanceof IStorageExternal && !simulate) {
((IStorageExternal) storage).update(this);
extractedExternally += took.amount;
} }
if (newStack == null) { if (newStack == null) {
@@ -466,8 +480,8 @@ public class TileController extends TileBase implements ITickable, INetwork, IRe
} }
} }
if (newStack != null && !simulate) { if (newStack != null && newStack.amount - extractedExternally > 0 && !simulate) {
fluidStorage.remove(newStack, newStack.amount, false); fluidStorage.remove(newStack, newStack.amount - extractedExternally, false);
} }
return newStack; return newStack;

View File

@@ -1,14 +1,15 @@
package com.raoulvdberge.refinedstorage.tile; package com.raoulvdberge.refinedstorage.tile;
import com.raoulvdberge.refinedstorage.api.storage.AccessType; import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage.NetworkNodeExternalStorage; import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IStorageExternal;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage.StorageFluidExternal; import com.raoulvdberge.refinedstorage.apiimpl.network.node.NetworkNodeExternalStorage;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.externalstorage.StorageItemExternal;
import com.raoulvdberge.refinedstorage.tile.config.*; import com.raoulvdberge.refinedstorage.tile.config.*;
import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter; import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter;
import net.minecraft.item.ItemStack;
import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -21,11 +22,11 @@ public class TileExternalStorage extends TileNode<NetworkNodeExternalStorage> {
public static final TileDataParameter<Integer, TileExternalStorage> STORED = new TileDataParameter<>(DataSerializers.VARINT, 0, t -> { public static final TileDataParameter<Integer, TileExternalStorage> STORED = new TileDataParameter<>(DataSerializers.VARINT, 0, t -> {
int stored = 0; int stored = 0;
for (StorageItemExternal storage : t.getNode().getItemStorages()) { for (IStorageExternal<ItemStack> storage : t.getNode().getItemStorages()) {
stored += storage.getStored(); stored += storage.getStored();
} }
for (StorageFluidExternal storage : t.getNode().getFluidStorages()) { for (IStorageExternal<FluidStack> storage : t.getNode().getFluidStorages()) {
stored += storage.getStored(); stored += storage.getStored();
} }
@@ -34,11 +35,11 @@ public class TileExternalStorage extends TileNode<NetworkNodeExternalStorage> {
public static final TileDataParameter<Integer, TileExternalStorage> CAPACITY = new TileDataParameter<>(DataSerializers.VARINT, 0, t -> { public static final TileDataParameter<Integer, TileExternalStorage> CAPACITY = new TileDataParameter<>(DataSerializers.VARINT, 0, t -> {
int capacity = 0; int capacity = 0;
for (StorageItemExternal storage : t.getNode().getItemStorages()) { for (IStorageExternal<ItemStack> storage : t.getNode().getItemStorages()) {
capacity += storage.getCapacity(); capacity += storage.getCapacity();
} }
for (StorageFluidExternal storage : t.getNode().getFluidStorages()) { for (IStorageExternal<FluidStack> storage : t.getNode().getFluidStorages()) {
capacity += storage.getCapacity(); capacity += storage.getCapacity();
} }

View File

@@ -24,7 +24,7 @@ public interface IFilterable {
}); });
} }
static boolean canTake(IItemHandler filters, int mode, int compare, ItemStack stack) { static boolean acceptsItem(IItemHandler filters, int mode, int compare, ItemStack stack) {
if (mode == WHITELIST) { if (mode == WHITELIST) {
for (int i = 0; i < filters.getSlots(); ++i) { for (int i = 0; i < filters.getSlots(); ++i) {
ItemStack slot = filters.getStackInSlot(i); ItemStack slot = filters.getStackInSlot(i);
@@ -50,7 +50,7 @@ public interface IFilterable {
return false; return false;
} }
static boolean canTakeFluids(ItemHandlerFluid filters, int mode, int compare, FluidStack stack) { static boolean acceptsFluid(ItemHandlerFluid filters, int mode, int compare, FluidStack stack) {
if (mode == WHITELIST) { if (mode == WHITELIST) {
for (int i = 0; i < filters.getSlots(); ++i) { for (int i = 0; i < filters.getSlots(); ++i) {
FluidStack slot = filters.getFluidStackInSlot(i); FluidStack slot = filters.getFluidStackInSlot(i);

View File

@@ -10,10 +10,10 @@ import com.raoulvdberge.refinedstorage.api.network.grid.handler.IItemGridHandler
import com.raoulvdberge.refinedstorage.api.storage.AccessType; import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.api.storage.IStorageCache; import com.raoulvdberge.refinedstorage.api.storage.IStorageCache;
import com.raoulvdberge.refinedstorage.api.storage.IStorageCacheListener; import com.raoulvdberge.refinedstorage.api.storage.IStorageCacheListener;
import com.raoulvdberge.refinedstorage.api.storage.StorageType;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDisk;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskContainerContext;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskProvider;
import com.raoulvdberge.refinedstorage.api.storage.disk.StorageDiskType;
import com.raoulvdberge.refinedstorage.api.util.IFilter; import com.raoulvdberge.refinedstorage.api.util.IFilter;
import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.network.grid.handler.ItemGridHandlerPortable; import com.raoulvdberge.refinedstorage.apiimpl.network.grid.handler.ItemGridHandlerPortable;
@@ -123,7 +123,7 @@ public class TilePortableGrid extends TileBase implements IGrid, IPortableGrid,
private List<IFilter> filters = new ArrayList<>(); private List<IFilter> filters = new ArrayList<>();
private List<IGridTab> tabs = new ArrayList<>(); private List<IGridTab> tabs = new ArrayList<>();
private ItemHandlerFilter filter = new ItemHandlerFilter(filters, tabs, new ItemHandlerListenerTile(this)); private ItemHandlerFilter filter = new ItemHandlerFilter(filters, tabs, new ItemHandlerListenerTile(this));
private ItemHandlerBase disk = new ItemHandlerBase(1, new ItemHandlerListenerTile(this), s -> NetworkNodeDiskDrive.VALIDATOR_STORAGE_DISK.test(s) && ((IStorageDiskProvider) s.getItem()).getType() == StorageDiskType.ITEM) { private ItemHandlerBase disk = new ItemHandlerBase(1, new ItemHandlerListenerTile(this), s -> NetworkNodeDiskDrive.VALIDATOR_STORAGE_DISK.test(s) && ((IStorageDiskProvider) s.getItem()).getType() == StorageType.ITEM) {
@Override @Override
protected void onContentsChanged(int slot) { protected void onContentsChanged(int slot) {
super.onContentsChanged(slot); super.onContentsChanged(slot);