diff --git a/src/main/java/refinedstorage/api/network/INetworkMaster.java b/src/main/java/refinedstorage/api/network/INetworkMaster.java index 8e7877e88..b5178c2ed 100755 --- a/src/main/java/refinedstorage/api/network/INetworkMaster.java +++ b/src/main/java/refinedstorage/api/network/INetworkMaster.java @@ -4,10 +4,12 @@ import cofh.api.energy.EnergyStorage; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fluids.FluidStack; import refinedstorage.api.autocrafting.ICraftingPattern; import refinedstorage.api.autocrafting.ICraftingTask; import refinedstorage.api.network.grid.IItemGridHandler; import refinedstorage.api.storage.CompareUtils; +import refinedstorage.api.storage.fluid.IGroupedFluidStorage; import refinedstorage.api.storage.item.IGroupedItemStorage; import javax.annotation.Nonnull; @@ -58,6 +60,11 @@ public interface INetworkMaster { */ IGroupedItemStorage getItemStorage(); + /** + * @return The {@link IGroupedFluidStorage} of this network + */ + IGroupedFluidStorage getFluidStorage(); + /** * @return The crafting tasks in this network, do NOT modify this list */ @@ -158,4 +165,26 @@ public interface INetworkMaster { */ @Nullable ItemStack extractItem(@Nonnull ItemStack stack, int size, int flags); + + /** + * Inserts a fluid to this network. + * + * @param stack The stack prototype to insert, do NOT modify + * @param size The amount of that prototype that has to be inserted + * @param simulate If we are simulating + * @return null if the insert was successful, or an {@link FluidStack} with the remainder + */ + @Nullable + FluidStack insertFluid(@Nonnull FluidStack stack, int size, boolean simulate); + + /** + * Extracts a fluid from this network. + * + * @param stack The prototype of the stack to extract, do NOT modify + * @param size The amount of that prototype that has to be extracted + * @param flags The flags to compare on, see {@link CompareUtils} + * @return null if we didn't extract anything, or a {@link FluidStack} with the result + */ + @Nullable + FluidStack extractFluid(@Nonnull FluidStack stack, int size, int flags); } diff --git a/src/main/java/refinedstorage/api/network/grid/GridExtractFlags.java b/src/main/java/refinedstorage/api/network/grid/GridExtractFlags.java deleted file mode 100755 index 43d9466e7..000000000 --- a/src/main/java/refinedstorage/api/network/grid/GridExtractFlags.java +++ /dev/null @@ -1,10 +0,0 @@ -package refinedstorage.api.network.grid; - -/** - * Flags for knowing what extract action the player is performing, these can be combined. - */ -public final class GridExtractFlags { - public static final int EXTRACT_HALF = 1; - public static final int EXTRACT_SINGLE = 2; - public static final int EXTRACT_SHIFT = 4; -} diff --git a/src/main/java/refinedstorage/api/network/grid/IItemGridHandler.java b/src/main/java/refinedstorage/api/network/grid/IItemGridHandler.java index edbaa231b..a2a59327a 100755 --- a/src/main/java/refinedstorage/api/network/grid/IItemGridHandler.java +++ b/src/main/java/refinedstorage/api/network/grid/IItemGridHandler.java @@ -9,11 +9,15 @@ import javax.annotation.Nullable; * Defines the behavior of item grids. */ public interface IItemGridHandler { + int EXTRACT_HALF = 1; + int EXTRACT_SINGLE = 2; + int EXTRACT_SHIFT = 4; + /** * Called when a player tries to extract an item from the grid. * * @param hash The hash of the item we're trying to extract, see {@link refinedstorage.api.network.NetworkUtils#getItemStackHashCode(ItemStack)} - * @param flags How we are extracting, see {@link GridExtractFlags} + * @param flags How we are extracting * @param player The player that is attempting the extraction */ void onExtract(int hash, int flags, EntityPlayerMP player); diff --git a/src/main/java/refinedstorage/api/storage/IStorageProvider.java b/src/main/java/refinedstorage/api/storage/IStorageProvider.java deleted file mode 100755 index 8eeb148b4..000000000 --- a/src/main/java/refinedstorage/api/storage/IStorageProvider.java +++ /dev/null @@ -1,17 +0,0 @@ -package refinedstorage.api.storage; - -import refinedstorage.api.storage.item.IItemStorage; - -import java.util.List; - -/** - * Represents a tile that provides storage to the network. Implement this on a tile that is a {@link refinedstorage.api.network.INetworkNode}. - */ -public interface IStorageProvider { - /** - * Adds the item storages that this storage provider provides. - * - * @param storages The previously added item storages - */ - void addItemStorages(List storages); -} diff --git a/src/main/java/refinedstorage/api/storage/fluid/IFluidStorage.java b/src/main/java/refinedstorage/api/storage/fluid/IFluidStorage.java new file mode 100755 index 000000000..33c3e99a3 --- /dev/null +++ b/src/main/java/refinedstorage/api/storage/fluid/IFluidStorage.java @@ -0,0 +1,54 @@ +package refinedstorage.api.storage.fluid; + +import net.minecraftforge.fluids.FluidStack; +import refinedstorage.api.storage.CompareUtils; +import refinedstorage.api.storage.item.IItemStorageProvider; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +/** + * Represents a fluid storage sink for the storage network. + * Provide this through an {@link IItemStorageProvider}. + */ +public interface IFluidStorage { + /** + * @return Fluids stored in this storage + */ + List getStacks(); + + /** + * Inserts a fluid to this storage. + * + * @param stack The fluid prototype to insert, do NOT modify + * @param size The amount of that prototype that has to be inserted + * @param simulate If we are simulating + * @return null if the insert was successful, or a {@link FluidStack} with the remainder + */ + @Nullable + FluidStack insertFluid(@Nonnull FluidStack stack, int size, boolean simulate); + + /** + * Extracts a fluid from this storage. + *

+ * If the fluid we found in the system is smaller than the requested size, return that fluid anyway. + * + * @param stack A prototype of the fluid to extract, do NOT modify + * @param size The amount of that fluid that has to be extracted + * @param flags On what we are comparing to extract this fluid, see {@link CompareUtils} + * @return null if we didn't extract anything, or an {@link FluidStack} with the result + */ + @Nullable + FluidStack extractFluid(@Nonnull FluidStack stack, int size, int flags); + + /** + * @return The amount of fluids stored in this storage + */ + int getStored(); + + /** + * @return The priority of this storage + */ + int getPriority(); +} diff --git a/src/main/java/refinedstorage/api/storage/fluid/IFluidStorageProvider.java b/src/main/java/refinedstorage/api/storage/fluid/IFluidStorageProvider.java new file mode 100755 index 000000000..a26562f27 --- /dev/null +++ b/src/main/java/refinedstorage/api/storage/fluid/IFluidStorageProvider.java @@ -0,0 +1,15 @@ +package refinedstorage.api.storage.fluid; + +import java.util.List; + +/** + * Represents a tile that provides item storage to the network. Implement this on a tile that is a {@link refinedstorage.api.network.INetworkNode}. + */ +public interface IFluidStorageProvider { + /** + * Adds the fluid storages that this storage provider provides. + * + * @param storages The previously added fluid storages + */ + void addFluidStorages(List storages); +} diff --git a/src/main/java/refinedstorage/api/storage/fluid/IGroupedFluidStorage.java b/src/main/java/refinedstorage/api/storage/fluid/IGroupedFluidStorage.java new file mode 100755 index 000000000..ec12b05f9 --- /dev/null +++ b/src/main/java/refinedstorage/api/storage/fluid/IGroupedFluidStorage.java @@ -0,0 +1,68 @@ +package refinedstorage.api.storage.fluid; + +import net.minecraftforge.fluids.FluidStack; +import refinedstorage.api.network.INetworkMaster; +import refinedstorage.api.storage.CompareUtils; +import refinedstorage.api.storage.item.IItemStorageProvider; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.List; + +/** + * This holds all fluids from all the connected storages from a {@link INetworkMaster}. + *

+ * Refined Storage uses this class mainly for use in Grids and Detectors to avoid querying + * individual {@link IFluidStorage} constantly (performance impact) and to send and detect storage changes + * more efficiently. + */ +public interface IGroupedFluidStorage { + /** + * Rebuilds the global fluid list. Typically called when a {@link IItemStorageProvider} is added or removed from the network. + */ + void rebuild(); + + /** + * Adds an item to the global fluid list. + *

+ * Note that this doesn't modify any of the connected storages, but just modifies the global fluid list. + * Use {@link INetworkMaster#insertFluid(FluidStack, int, boolean)} to add a fluid to an actual storage. + *

+ * Will merge it with another fluid if it already exists. + * + * @param stack The fluid to add, do NOT modify + * @param rebuilding Whether this method is called while the storage is rebuilding + */ + void add(@Nonnull FluidStack stack, boolean rebuilding); + + /** + * Removes a fluid from the global fluid list. + *

+ * Note that this doesn't modify any of the connected storages, but just modifies the global fluid list. + * Use {@link INetworkMaster#extractFluid(FluidStack, int, int)} to remove an fluid from an actual storage. + * + * @param stack The fluid to remove, do NOT modify + */ + void remove(@Nonnull FluidStack stack); + + /** + * Gets a fluid from the network. + * + * @param stack The stack to find + * @param flags The flags to compare on, see {@link CompareUtils} + * @return Null if no fluid is found, or the {@link FluidStack}, do NOT modify + */ + @Nullable + FluidStack get(@Nonnull FluidStack stack, int flags); + + /** + * @return All fluids in this storage network + */ + Collection getStacks(); + + /** + * @return The fluid storages connected to this network + */ + List getStorages(); +} diff --git a/src/main/java/refinedstorage/api/storage/item/IGroupedItemStorage.java b/src/main/java/refinedstorage/api/storage/item/IGroupedItemStorage.java index 310d71092..c4f9291d5 100755 --- a/src/main/java/refinedstorage/api/storage/item/IGroupedItemStorage.java +++ b/src/main/java/refinedstorage/api/storage/item/IGroupedItemStorage.java @@ -3,7 +3,6 @@ package refinedstorage.api.storage.item; import net.minecraft.item.ItemStack; import refinedstorage.api.network.INetworkMaster; import refinedstorage.api.storage.CompareUtils; -import refinedstorage.api.storage.IStorageProvider; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -19,7 +18,7 @@ import java.util.List; */ public interface IGroupedItemStorage { /** - * Rebuilds the global item list. Typically called when a {@link IStorageProvider} is added or removed from the network. + * Rebuilds the global item list. Typically called when a {@link IItemStorageProvider} is added or removed from the network. */ void rebuild(); diff --git a/src/main/java/refinedstorage/api/storage/item/IItemStorage.java b/src/main/java/refinedstorage/api/storage/item/IItemStorage.java index 09e4343ae..a30bb0134 100755 --- a/src/main/java/refinedstorage/api/storage/item/IItemStorage.java +++ b/src/main/java/refinedstorage/api/storage/item/IItemStorage.java @@ -2,7 +2,6 @@ package refinedstorage.api.storage.item; import net.minecraft.item.ItemStack; import refinedstorage.api.storage.CompareUtils; -import refinedstorage.api.storage.IStorageProvider; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -10,7 +9,7 @@ import java.util.List; /** * Represents an item storage sink for the storage network. - * Provide this through an {@link IStorageProvider}. + * Provide this through an {@link IItemStorageProvider}. */ public interface IItemStorage { /** @@ -32,8 +31,7 @@ public interface IItemStorage { /** * Extracts an item from this storage. *

- * If the stack we found in the system is smaller than the requested size, return the stack anyway. - * For example: if this method is called for dirt (64x) while there is only dirt (32x), return the dirt (32x) anyway. + * If the stack we found in the system is smaller than the requested size, return that stack anyway. * * @param stack A prototype of the stack to extract, do NOT modify * @param size The amount of that prototype that has to be extracted diff --git a/src/main/java/refinedstorage/api/storage/item/IItemStorageProvider.java b/src/main/java/refinedstorage/api/storage/item/IItemStorageProvider.java new file mode 100755 index 000000000..e0e365df6 --- /dev/null +++ b/src/main/java/refinedstorage/api/storage/item/IItemStorageProvider.java @@ -0,0 +1,15 @@ +package refinedstorage.api.storage.item; + +import java.util.List; + +/** + * Represents a tile that provides item storage to the network. Implement this on a tile that is a {@link refinedstorage.api.network.INetworkNode}. + */ +public interface IItemStorageProvider { + /** + * Adds the item storages that this storage provider provides. + * + * @param storages The previously added item storages + */ + void addItemStorages(List storages); +} diff --git a/src/main/java/refinedstorage/apiimpl/network/ItemGridHandler.java b/src/main/java/refinedstorage/apiimpl/network/grid/ItemGridHandler.java similarity index 90% rename from src/main/java/refinedstorage/apiimpl/network/ItemGridHandler.java rename to src/main/java/refinedstorage/apiimpl/network/grid/ItemGridHandler.java index 4f9b27336..8a43432ef 100755 --- a/src/main/java/refinedstorage/apiimpl/network/ItemGridHandler.java +++ b/src/main/java/refinedstorage/apiimpl/network/grid/ItemGridHandler.java @@ -1,4 +1,4 @@ -package refinedstorage.apiimpl.network; +package refinedstorage.apiimpl.network.grid; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.InventoryHelper; @@ -7,9 +7,9 @@ import refinedstorage.api.autocrafting.ICraftingPattern; import refinedstorage.api.autocrafting.ICraftingTask; import refinedstorage.api.network.INetworkMaster; import refinedstorage.api.network.NetworkUtils; -import refinedstorage.api.network.grid.GridExtractFlags; import refinedstorage.api.network.grid.IItemGridHandler; import refinedstorage.api.storage.CompareUtils; +import refinedstorage.apiimpl.network.WirelessGridHandler; public class ItemGridHandler implements IItemGridHandler { public static final int MAX_CRAFTING_PER_REQUEST = 500; @@ -30,7 +30,7 @@ public class ItemGridHandler implements IItemGridHandler { int itemSize = item.stackSize; - boolean single = (flags & GridExtractFlags.EXTRACT_SINGLE) == GridExtractFlags.EXTRACT_SINGLE; + boolean single = (flags & EXTRACT_SINGLE) == EXTRACT_SINGLE; ItemStack held = player.inventory.getItemStack(); @@ -44,7 +44,7 @@ public class ItemGridHandler implements IItemGridHandler { int size = 64; - if ((flags & GridExtractFlags.EXTRACT_HALF) == GridExtractFlags.EXTRACT_HALF && itemSize > 1) { + if ((flags & EXTRACT_HALF) == EXTRACT_HALF && itemSize > 1) { size = itemSize / 2; if (size > 32) { @@ -52,7 +52,7 @@ public class ItemGridHandler implements IItemGridHandler { } } else if (single) { size = 1; - } else if ((flags & GridExtractFlags.EXTRACT_SHIFT) == GridExtractFlags.EXTRACT_SHIFT) { + } else if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) { // NO OP, the quantity already set (64) is needed for shift } @@ -61,7 +61,7 @@ public class ItemGridHandler implements IItemGridHandler { ItemStack took = NetworkUtils.extractItem(network, item, size); if (took != null) { - if ((flags & GridExtractFlags.EXTRACT_SHIFT) == GridExtractFlags.EXTRACT_SHIFT) { + if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) { if (!player.inventory.addItemStackToInventory(took.copy())) { InventoryHelper.spawnItemStack(player.worldObj, player.getPosition().getX(), player.getPosition().getY(), player.getPosition().getZ(), took); } diff --git a/src/main/java/refinedstorage/apiimpl/storage/fluid/FluidStorageNBT.java b/src/main/java/refinedstorage/apiimpl/storage/fluid/FluidStorageNBT.java new file mode 100755 index 000000000..ff1b81ac4 --- /dev/null +++ b/src/main/java/refinedstorage/apiimpl/storage/fluid/FluidStorageNBT.java @@ -0,0 +1,212 @@ +package refinedstorage.apiimpl.storage.fluid; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.fluids.FluidStack; +import refinedstorage.api.storage.fluid.IFluidStorage; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +/** + * A implementation of {@link IFluidStorage} that stores storage fluids in NBT. + */ +public abstract class FluidStorageNBT implements IFluidStorage { + /** + * The current save protocol that is used. It's set to every {@link FluidStorageNBT} to allow for + * safe backwards compatibility breaks. + */ + private static final int PROTOCOL = 1; + + private static final String NBT_PROTOCOL = "Protocol"; + + private static final String NBT_FLUIDS = "Fluids"; + private static final String NBT_STORED = "Stored"; + + private NBTTagCompound tag; + private int capacity; + private TileEntity tile; + + private List stacks = new ArrayList<>(); + + /** + * @param tag The NBT tag we are reading from and writing the amount stored to, has to be initialized with {@link FluidStorageNBT#createNBT()} if it doesn't exist yet + * @param capacity The capacity of this storage, -1 for infinite capacity + * @param tile A {@link TileEntity} that the NBT storage is in, will be marked dirty when the storage changes + */ + public FluidStorageNBT(NBTTagCompound tag, int capacity, @Nullable TileEntity tile) { + this.tag = tag; + this.capacity = capacity; + this.tile = tile; + + readFromNBT(); + } + + public void readFromNBT() { + NBTTagList list = (NBTTagList) tag.getTag(NBT_FLUIDS); + + for (int i = 0; i < list.tagCount(); ++i) { + stacks.add(FluidStack.loadFluidStackFromNBT(list.getCompoundTagAt(i))); + } + } + + /** + * Writes the items to the NBT tag. + */ + public void writeToNBT() { + NBTTagList list = new NBTTagList(); + + for (FluidStack stack : stacks) { + list.appendTag(stack.writeToNBT(new NBTTagCompound())); + } + + tag.setTag(NBT_FLUIDS, list); + tag.setInteger(NBT_PROTOCOL, PROTOCOL); + } + + @Override + public List getStacks() { + return stacks; + } + + @Override + public FluidStack insertFluid(FluidStack stack, int size, boolean simulate) { + for (FluidStack otherStack : stacks) { + if (otherStack.isFluidEqual(stack)) { + if (getCapacity() != -1 && getStored() + size > getCapacity()) { + int remainingSpace = getCapacity() - getStored(); + + if (remainingSpace <= 0) { + return FluidUtils.copyStackWithSize(stack, size); + } + + if (!simulate) { + tag.setInteger(NBT_STORED, getStored() + remainingSpace); + + otherStack.amount += remainingSpace; + + onStorageChanged(); + } + + return FluidUtils.copyStackWithSize(otherStack, size - remainingSpace); + } else { + if (!simulate) { + tag.setInteger(NBT_STORED, getStored() + size); + + otherStack.amount += size; + + onStorageChanged(); + } + + return null; + } + } + } + + if (getCapacity() != -1 && getStored() + size > getCapacity()) { + int remainingSpace = getCapacity() - getStored(); + + if (remainingSpace <= 0) { + return FluidUtils.copyStackWithSize(stack, size); + } + + if (!simulate) { + tag.setInteger(NBT_STORED, getStored() + remainingSpace); + + stacks.add(FluidUtils.copyStackWithSize(stack, remainingSpace)); + + onStorageChanged(); + } + + return FluidUtils.copyStackWithSize(stack, size - remainingSpace); + } else { + if (!simulate) { + tag.setInteger(NBT_STORED, getStored() + size); + + stacks.add(FluidUtils.copyStackWithSize(stack, size)); + + onStorageChanged(); + } + + return null; + } + } + + @Override + public FluidStack extractFluid(FluidStack stack, int size, int flags) { + for (FluidStack otherStack : stacks) { + if (otherStack.isFluidEqual(stack)) { + if (size > otherStack.amount) { + size = otherStack.amount; + } + + if (otherStack.amount - size == 0) { + stacks.remove(otherStack); + } else { + otherStack.amount -= size; + } + + tag.setInteger(NBT_STORED, getStored() - size); + + onStorageChanged(); + + return FluidUtils.copyStackWithSize(otherStack, size); + } + } + + return null; + } + + public void onStorageChanged() { + if (tile != null) { + tile.markDirty(); + } + } + + @Override + public int getStored() { + return getStoredFromNBT(tag); + } + + public int getCapacity() { + return capacity; + } + + public NBTTagCompound getTag() { + return tag; + } + + public static int getStoredFromNBT(NBTTagCompound tag) { + return tag.getInteger(NBT_STORED); + } + + /* + * @return A NBT tag initialized with the fields that {@link NBTStorage} uses + */ + public static NBTTagCompound createNBT() { + NBTTagCompound tag = new NBTTagCompound(); + + tag.setTag(NBT_FLUIDS, new NBTTagList()); + tag.setInteger(NBT_STORED, 0); + tag.setInteger(NBT_PROTOCOL, PROTOCOL); + + return tag; + } + + public static boolean isValid(ItemStack stack) { + return stack.hasTagCompound() && stack.getTagCompound().hasKey(NBT_FLUIDS) && stack.getTagCompound().hasKey(NBT_STORED); + } + + /** + * @param stack The {@link ItemStack} to populate with the NBT tags from {@link FluidStorageNBT#createNBT()} + * @return The provided {@link ItemStack} with NBT tags from {@link FluidStorageNBT#createNBT()} + */ + public static ItemStack createStackWithNBT(ItemStack stack) { + stack.setTagCompound(createNBT()); + + return stack; + } +} diff --git a/src/main/java/refinedstorage/apiimpl/storage/fluid/FluidUtils.java b/src/main/java/refinedstorage/apiimpl/storage/fluid/FluidUtils.java new file mode 100755 index 000000000..2a84f3dac --- /dev/null +++ b/src/main/java/refinedstorage/apiimpl/storage/fluid/FluidUtils.java @@ -0,0 +1,11 @@ +package refinedstorage.apiimpl.storage.fluid; + +import net.minecraftforge.fluids.FluidStack; + +public final class FluidUtils { + public static FluidStack copyStackWithSize(FluidStack stack, int size) { + FluidStack copy = stack.copy(); + copy.amount = size; + return copy; + } +} diff --git a/src/main/java/refinedstorage/apiimpl/storage/fluid/GroupedFluidStorage.java b/src/main/java/refinedstorage/apiimpl/storage/fluid/GroupedFluidStorage.java new file mode 100755 index 000000000..eba08be93 --- /dev/null +++ b/src/main/java/refinedstorage/apiimpl/storage/fluid/GroupedFluidStorage.java @@ -0,0 +1,93 @@ +package refinedstorage.apiimpl.storage.fluid; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import refinedstorage.api.network.INetworkMaster; +import refinedstorage.api.storage.fluid.IFluidStorage; +import refinedstorage.api.storage.fluid.IFluidStorageProvider; +import refinedstorage.api.storage.fluid.IGroupedFluidStorage; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class GroupedFluidStorage implements IGroupedFluidStorage { + private INetworkMaster network; + private List storages = new ArrayList<>(); + private Multimap stacks = ArrayListMultimap.create(); + + public GroupedFluidStorage(INetworkMaster network) { + this.network = network; + } + + @Override + public void rebuild() { + storages.clear(); + + network.getNodeGraph().all().stream() + .filter(node -> node.canUpdate() && node instanceof IFluidStorageProvider) + .forEach(node -> ((IFluidStorageProvider) node).addFluidStorages(storages)); + + stacks.clear(); + + for (IFluidStorage storage : storages) { + for (FluidStack stack : storage.getStacks()) { + add(stack, true); + } + } + } + + @Override + public void add(@Nonnull FluidStack stack, boolean rebuilding) { + for (FluidStack otherStack : stacks.get(stack.getFluid())) { + if (otherStack.isFluidEqual(stack)) { + otherStack.amount += stack.amount; + + return; + } + } + + stacks.put(stack.getFluid(), stack.copy()); + } + + @Override + public void remove(@Nonnull FluidStack stack) { + for (FluidStack otherStack : stacks.get(stack.getFluid())) { + if (otherStack.isFluidEqual(stack)) { + otherStack.amount -= stack.amount; + + if (otherStack.amount == 0) { + stacks.remove(otherStack.getFluid(), otherStack); + } + + return; + } + } + } + + @Override + @Nullable + public FluidStack get(@Nonnull FluidStack stack, int flags) { + for (FluidStack otherStack : stacks.get(stack.getFluid())) { + if (otherStack.isFluidEqual(stack)) { + return otherStack; + } + } + + return null; + } + + @Override + public Collection getStacks() { + return stacks.values(); + } + + @Override + public List getStorages() { + return storages; + } +} diff --git a/src/main/java/refinedstorage/apiimpl/storage/item/GroupedItemStorage.java b/src/main/java/refinedstorage/apiimpl/storage/item/GroupedItemStorage.java index 4c751672e..8fc055d89 100755 --- a/src/main/java/refinedstorage/apiimpl/storage/item/GroupedItemStorage.java +++ b/src/main/java/refinedstorage/apiimpl/storage/item/GroupedItemStorage.java @@ -8,9 +8,9 @@ import refinedstorage.api.autocrafting.ICraftingPattern; import refinedstorage.api.network.INetworkMaster; import refinedstorage.api.network.NetworkUtils; import refinedstorage.api.storage.CompareUtils; -import refinedstorage.api.storage.IStorageProvider; import refinedstorage.api.storage.item.IGroupedItemStorage; import refinedstorage.api.storage.item.IItemStorage; +import refinedstorage.api.storage.item.IItemStorageProvider; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -32,8 +32,8 @@ public class GroupedItemStorage implements IGroupedItemStorage { storages.clear(); network.getNodeGraph().all().stream() - .filter(node -> node.canUpdate() && node instanceof IStorageProvider) - .forEach(node -> ((IStorageProvider) node).addItemStorages(storages)); + .filter(node -> node.canUpdate() && node instanceof IItemStorageProvider) + .forEach(node -> ((IItemStorageProvider) node).addItemStorages(storages)); stacks.clear(); diff --git a/src/main/java/refinedstorage/gui/grid/GuiCraftingSettings.java b/src/main/java/refinedstorage/gui/grid/GuiCraftingSettings.java index 09382cf51..279fa8013 100755 --- a/src/main/java/refinedstorage/gui/grid/GuiCraftingSettings.java +++ b/src/main/java/refinedstorage/gui/grid/GuiCraftingSettings.java @@ -7,7 +7,7 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.fml.client.FMLClientHandler; import org.lwjgl.input.Keyboard; import refinedstorage.RefinedStorage; -import refinedstorage.apiimpl.network.ItemGridHandler; +import refinedstorage.apiimpl.network.grid.ItemGridHandler; import refinedstorage.container.ContainerCraftingSettings; import refinedstorage.gui.GuiBase; import refinedstorage.network.MessageGridCraftingStart; diff --git a/src/main/java/refinedstorage/gui/grid/GuiGrid.java b/src/main/java/refinedstorage/gui/grid/GuiGrid.java index e18c55921..8a788be61 100755 --- a/src/main/java/refinedstorage/gui/grid/GuiGrid.java +++ b/src/main/java/refinedstorage/gui/grid/GuiGrid.java @@ -13,7 +13,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraftforge.fml.common.FMLCommonHandler; import refinedstorage.RefinedStorage; -import refinedstorage.api.network.grid.GridExtractFlags; +import refinedstorage.api.network.grid.IItemGridHandler; import refinedstorage.api.storage.CompareUtils; import refinedstorage.block.EnumGridType; import refinedstorage.container.ContainerGrid; @@ -372,15 +372,15 @@ public class GuiGrid extends GuiBase { int flags = 0; if (clickedButton == 1) { - flags |= GridExtractFlags.EXTRACT_HALF; + flags |= IItemGridHandler.EXTRACT_HALF; } if (GuiScreen.isShiftKeyDown()) { - flags |= GridExtractFlags.EXTRACT_SHIFT; + flags |= IItemGridHandler.EXTRACT_SHIFT; } if (clickedButton == 2) { - flags |= GridExtractFlags.EXTRACT_SINGLE; + flags |= IItemGridHandler.EXTRACT_SINGLE; } RefinedStorage.INSTANCE.network.sendToServer(new MessageGridPull(SORTED_ITEMS.get(slotNumber).getId(), flags)); diff --git a/src/main/java/refinedstorage/tile/TileController.java b/src/main/java/refinedstorage/tile/TileController.java index ac15d8034..be2ba1ede 100755 --- a/src/main/java/refinedstorage/tile/TileController.java +++ b/src/main/java/refinedstorage/tile/TileController.java @@ -14,6 +14,7 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.items.ItemHandlerHelper; import refinedstorage.RefinedStorage; import refinedstorage.RefinedStorageBlocks; @@ -23,14 +24,18 @@ import refinedstorage.api.autocrafting.ICraftingTask; import refinedstorage.api.network.*; import refinedstorage.api.network.grid.IItemGridHandler; import refinedstorage.api.storage.CompareUtils; +import refinedstorage.api.storage.fluid.IFluidStorage; +import refinedstorage.api.storage.fluid.IGroupedFluidStorage; import refinedstorage.api.storage.item.IGroupedItemStorage; import refinedstorage.api.storage.item.IItemStorage; import refinedstorage.apiimpl.autocrafting.BasicCraftingTask; import refinedstorage.apiimpl.autocrafting.CraftingPattern; import refinedstorage.apiimpl.autocrafting.ProcessingCraftingTask; -import refinedstorage.apiimpl.network.ItemGridHandler; import refinedstorage.apiimpl.network.NetworkNodeGraph; import refinedstorage.apiimpl.network.WirelessGridHandler; +import refinedstorage.apiimpl.network.grid.ItemGridHandler; +import refinedstorage.apiimpl.storage.fluid.FluidUtils; +import refinedstorage.apiimpl.storage.fluid.GroupedFluidStorage; import refinedstorage.apiimpl.storage.item.GroupedItemStorage; import refinedstorage.block.BlockController; import refinedstorage.block.EnumControllerType; @@ -51,6 +56,8 @@ import refinedstorage.tile.data.RefinedStorageSerializers; import refinedstorage.tile.data.TileDataParameter; import refinedstorage.tile.externalstorage.ItemStorageExternal; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.*; public class TileController extends TileBase implements INetworkMaster, IEnergyReceiver, IRedstoneConfigurable { @@ -137,7 +144,9 @@ public class TileController extends TileBase implements INetworkMaster, IEnergyR private WirelessGridHandler wirelessGridHandler = new WirelessGridHandler(this); private INetworkNodeGraph nodeGraph = new NetworkNodeGraph(this); + private IGroupedItemStorage itemStorage = new GroupedItemStorage(this); + private IGroupedFluidStorage fluidStorage = new GroupedFluidStorage(this); private List patterns = new ArrayList<>(); @@ -324,6 +333,11 @@ public class TileController extends TileBase implements INetworkMaster, IEnergyR return itemStorage; } + @Override + public IGroupedFluidStorage getFluidStorage() { + return fluidStorage; + } + @Override public List getCraftingTasks() { return craftingTasks; @@ -537,6 +551,69 @@ public class TileController extends TileBase implements INetworkMaster, IEnergyR return newStack; } + @Nullable + @Override + public FluidStack insertFluid(@Nonnull FluidStack stack, int size, boolean simulate) { + if (stack == null || fluidStorage.getStorages().isEmpty()) { + return FluidUtils.copyStackWithSize(stack, size); + } + + int orginalSize = size; + + FluidStack remainder = stack; + + for (IFluidStorage storage : this.fluidStorage.getStorages()) { + remainder = storage.insertFluid(remainder, size, simulate); + + if (remainder == null) { + break; + } else { + size = remainder.amount; + } + } + + int inserted = remainder != null ? (orginalSize - remainder.amount) : orginalSize; + + if (!simulate && inserted > 0) { + fluidStorage.add(FluidUtils.copyStackWithSize(stack, inserted), false); + } + + return remainder; + } + + @Nullable + @Override + public FluidStack extractFluid(@Nonnull FluidStack stack, int size, int flags) { + int requested = size; + int received = 0; + + FluidStack newStack = null; + + for (IFluidStorage storage : this.fluidStorage.getStorages()) { + FluidStack took = storage.extractFluid(stack, requested - received, flags); + + if (took != null) { + if (newStack == null) { + newStack = took; + } else { + newStack.amount += took.amount; + } + + received += took.amount; + } + + if (requested == received) { + break; + } + } + + if (newStack != null) { + fluidStorage.remove(newStack); + } + + return newStack; + } + @Override public void readFromNBT(NBTTagCompound tag) { super.readFromNBT(tag); diff --git a/src/main/java/refinedstorage/tile/TileDiskDrive.java b/src/main/java/refinedstorage/tile/TileDiskDrive.java index fabf13437..f6219e41b 100755 --- a/src/main/java/refinedstorage/tile/TileDiskDrive.java +++ b/src/main/java/refinedstorage/tile/TileDiskDrive.java @@ -12,8 +12,8 @@ import net.minecraftforge.items.ItemHandlerHelper; import refinedstorage.RefinedStorage; import refinedstorage.RefinedStorageItems; import refinedstorage.api.network.INetworkMaster; -import refinedstorage.api.storage.IStorageProvider; import refinedstorage.api.storage.item.IItemStorage; +import refinedstorage.api.storage.item.IItemStorageProvider; import refinedstorage.apiimpl.storage.item.ItemStorageNBT; import refinedstorage.block.EnumStorageType; import refinedstorage.inventory.ItemHandlerBasic; @@ -25,7 +25,7 @@ import refinedstorage.tile.data.TileDataParameter; import java.util.List; -public class TileDiskDrive extends TileNode implements IStorageProvider, IStorageGui, IComparable, IFilterable, IPrioritizable { +public class TileDiskDrive extends TileNode implements IItemStorageProvider, IStorageGui, IComparable, IFilterable, IPrioritizable { public static final TileDataParameter PRIORITY = IPrioritizable.createParameter(); public static final TileDataParameter COMPARE = IComparable.createParameter(); public static final TileDataParameter MODE = IFilterable.createParameter(); diff --git a/src/main/java/refinedstorage/tile/TileStorage.java b/src/main/java/refinedstorage/tile/TileStorage.java index b44830cdb..ebdd29aea 100755 --- a/src/main/java/refinedstorage/tile/TileStorage.java +++ b/src/main/java/refinedstorage/tile/TileStorage.java @@ -8,8 +8,8 @@ import net.minecraftforge.items.ItemHandlerHelper; import refinedstorage.RefinedStorage; import refinedstorage.RefinedStorageBlocks; import refinedstorage.api.network.INetworkMaster; -import refinedstorage.api.storage.IStorageProvider; import refinedstorage.api.storage.item.IItemStorage; +import refinedstorage.api.storage.item.IItemStorageProvider; import refinedstorage.apiimpl.storage.item.ItemStorageNBT; import refinedstorage.block.BlockStorage; import refinedstorage.block.EnumStorageType; @@ -22,7 +22,7 @@ import refinedstorage.tile.data.TileDataParameter; import java.util.List; -public class TileStorage extends TileNode implements IStorageProvider, IStorageGui, IComparable, IFilterable, IPrioritizable { +public class TileStorage extends TileNode implements IItemStorageProvider, IStorageGui, IComparable, IFilterable, IPrioritizable { public static final TileDataParameter PRIORITY = IPrioritizable.createParameter(); public static final TileDataParameter COMPARE = IComparable.createParameter(); public static final TileDataParameter MODE = IFilterable.createParameter(); diff --git a/src/main/java/refinedstorage/tile/externalstorage/TileExternalStorage.java b/src/main/java/refinedstorage/tile/externalstorage/TileExternalStorage.java index 2409535d7..b5e079e20 100755 --- a/src/main/java/refinedstorage/tile/externalstorage/TileExternalStorage.java +++ b/src/main/java/refinedstorage/tile/externalstorage/TileExternalStorage.java @@ -10,8 +10,8 @@ import net.minecraftforge.items.IItemHandler; import powercrystals.minefactoryreloaded.api.IDeepStorageUnit; import refinedstorage.RefinedStorage; import refinedstorage.api.network.INetworkMaster; -import refinedstorage.api.storage.IStorageProvider; import refinedstorage.api.storage.item.IItemStorage; +import refinedstorage.api.storage.item.IItemStorageProvider; import refinedstorage.inventory.ItemHandlerBasic; import refinedstorage.tile.IStorageGui; import refinedstorage.tile.TileMultipartNode; @@ -24,7 +24,7 @@ import refinedstorage.tile.data.TileDataParameter; import java.util.ArrayList; import java.util.List; -public class TileExternalStorage extends TileMultipartNode implements IStorageProvider, IStorageGui, IComparable, IFilterable, IPrioritizable { +public class TileExternalStorage extends TileMultipartNode implements IItemStorageProvider, IStorageGui, IComparable, IFilterable, IPrioritizable { public static final TileDataParameter PRIORITY = IPrioritizable.createParameter(); public static final TileDataParameter COMPARE = IComparable.createParameter(); public static final TileDataParameter MODE = IFilterable.createParameter();