diff --git a/CHANGELOG.md b/CHANGELOG.md index df388d7d2..b727dc80f 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Refined Storage Changelog +### 1.6.1 +- Added fluid autocrafting (raoulvdberge) + ### 1.6 NOTE: Worlds that used Refined Storage 1.5.x are fully compatible with Refined Storage 1.6.x and are getting converted upon loading the world. It is however not possible to revert back to Refined Storage 1.5.x when a world has already been converted to Refined Storage 1.6.x. diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/IRSAPI.java b/src/main/java/com/raoulvdberge/refinedstorage/api/IRSAPI.java index 569c6838b..01c84e1a4 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/IRSAPI.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/IRSAPI.java @@ -5,6 +5,8 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftin import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry; import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry; import com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskRegistry; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.api.network.grid.wireless.IWirelessGridFactory; import com.raoulvdberge.refinedstorage.api.network.grid.wireless.IWirelessGridRegistry; @@ -25,6 +27,7 @@ import com.raoulvdberge.refinedstorage.api.util.IQuantityFormatter; import com.raoulvdberge.refinedstorage.api.util.IStackList; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -171,6 +174,30 @@ public interface IRSAPI { @Nonnull IStorageDisk createDefaultFluidDisk(World world, int capacity); + /** + * Creates crafting request info for an item. + * + * @param stack the stack + * @return the request info + */ + ICraftingRequestInfo createCraftingRequestInfo(ItemStack stack); + + /** + * Creates crafting request info for a fluid. + * + * @param stack the stack + * @return the request info + */ + ICraftingRequestInfo createCraftingRequestInfo(FluidStack stack); + + /** + * Creates crafting request info from NBT. + * + * @param tag the nbt tag + * @return the request info + */ + ICraftingRequestInfo createCraftingRequestInfo(NBTTagCompound tag) throws CraftingTaskReadException; + /** * Returns a helper for the 1.6.x migration. * Will be removed in 1.7.x! diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingManager.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingManager.java index 872193715..312c34585 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingManager.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingManager.java @@ -4,6 +4,7 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftin import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.items.IItemHandlerModifiable; import javax.annotation.Nonnull; @@ -60,6 +61,16 @@ public interface ICraftingManager { @Nullable ICraftingTask create(ItemStack stack, int quantity); + /** + * Creates a crafting task for a given stack, but doesn't add it to the list. + * + * @param stack the stack to craft + * @param quantity the quantity to craft + * @return the crafting task, or null if no pattern was found for the given stack + */ + @Nullable + ICraftingTask create(FluidStack stack, int quantity); + /** * @return a new pattern chain list */ @@ -82,6 +93,13 @@ public interface ICraftingManager { */ void track(ItemStack stack, int size); + /** + * Tracks an incoming stack. + * + * @param stack the stack + */ + void track(FluidStack stack, int size); + /** * @return a list of crafting patterns in this network, do NOT modify this list */ @@ -101,6 +119,15 @@ public interface ICraftingManager { @Nullable ICraftingPattern getPattern(ItemStack pattern); + /** + * Return a crafting pattern from a fluid stack. + * + * @param pattern the stack to get a pattern for + * @return the crafting pattern, or null if none is found + */ + @Nullable + ICraftingPattern getPattern(FluidStack pattern); + /** * Updates the tasks in this manager. */ diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPattern.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPattern.java index 7f121ea01..366b661cc 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPattern.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPattern.java @@ -2,6 +2,7 @@ package com.raoulvdberge.refinedstorage.api.autocrafting; import net.minecraft.item.ItemStack; import net.minecraft.util.NonNullList; +import net.minecraftforge.fluids.FluidStack; import java.util.List; @@ -61,6 +62,10 @@ public interface ICraftingPattern { */ NonNullList getByproducts(NonNullList took); + NonNullList getFluidInputs(); + + NonNullList getFluidOutputs(); + /** * @return the id of the factory that creates a crafting task for this pattern, as defined in the {@link com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskRegistry} */ diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPatternContainer.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPatternContainer.java index 50635b604..bc8ff374a 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPatternContainer.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingPatternContainer.java @@ -3,6 +3,7 @@ package com.raoulvdberge.refinedstorage.api.autocrafting; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; @@ -25,6 +26,9 @@ public interface ICraftingPatternContainer { @Nullable IItemHandler getConnectedInventory(); + @Nullable + IFluidHandler getConnectedFluidInventory(); + /** * @return the tile that this container is connected to, or null if no tile is present */ diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/registry/ICraftingTaskFactory.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/registry/ICraftingTaskFactory.java index fef2fd601..fcce417cb 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/registry/ICraftingTaskFactory.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/registry/ICraftingTaskFactory.java @@ -2,9 +2,9 @@ package com.raoulvdberge.refinedstorage.api.autocrafting.registry; import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern; import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; import com.raoulvdberge.refinedstorage.api.network.INetwork; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import javax.annotation.Nonnull; @@ -17,14 +17,14 @@ public interface ICraftingTaskFactory { /** * Returns a crafting task for a given pattern. * - * @param network the network - * @param stack the stack to create a task for - * @param pattern the pattern - * @param quantity the quantity + * @param network the network + * @param requested the request info + * @param pattern the pattern + * @param quantity the quantity * @return the crafting task */ @Nonnull - ICraftingTask create(INetwork network, ItemStack stack, int quantity, ICraftingPattern pattern); + ICraftingTask create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern); /** * Returns a crafting task for a given NBT tag. diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingRequestInfo.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingRequestInfo.java new file mode 100644 index 000000000..ad3706744 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingRequestInfo.java @@ -0,0 +1,29 @@ +package com.raoulvdberge.refinedstorage.api.autocrafting.task; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; + +import javax.annotation.Nullable; + +/** + * Contains information about a crafting request. + */ +public interface ICraftingRequestInfo { + /** + * @return the item requested, or null if no item was requested + */ + @Nullable + ItemStack getItem(); + + /** + * @return the fluid requested, or null if no fluid was requested + */ + @Nullable + FluidStack getFluid(); + + /** + * @return the written tag + */ + NBTTagCompound writeToNbt(); +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingTask.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingTask.java index bd9f03703..4e59cc110 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingTask.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/task/ICraftingTask.java @@ -6,6 +6,7 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreview import com.raoulvdberge.refinedstorage.api.util.IStackList; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; import javax.annotation.Nullable; import java.util.List; @@ -44,7 +45,7 @@ public interface ICraftingTask { /** * @return the stack requested */ - ItemStack getRequested(); + ICraftingRequestInfo getRequested(); /** * Called when a stack is inserted into the system through {@link com.raoulvdberge.refinedstorage.api.network.INetwork#insertItemTracked(ItemStack, int)}. @@ -52,7 +53,15 @@ public interface ICraftingTask { * @param stack the stack * @return the size remaining, decremented by the crafting task when it was relevant to it */ - int onTrackedItemInserted(ItemStack stack, int size); + int onTrackedInsert(ItemStack stack, int size); + + /** + * Called when a stack is inserted into the system through {@link com.raoulvdberge.refinedstorage.api.network.INetwork#insertFluidTracked(FluidStack, int)}. + * + * @param stack the stack + * @return the size remaining, decremented by the crafting task when it was relevant to it + */ + int onTrackedInsert(FluidStack stack, int size); /** * Writes this task to NBT. diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetwork.java b/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetwork.java index 0001566c9..c57ccd468 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetwork.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetwork.java @@ -167,6 +167,16 @@ public interface INetwork { @Nullable FluidStack insertFluid(@Nonnull FluidStack stack, int size, Action action); + default FluidStack insertFluidTracked(@Nonnull FluidStack stack, int size) { + FluidStack remainder = insertFluid(stack, size, Action.PERFORM); + + int inserted = remainder == null ? size : (size - remainder.amount); + + getCraftingManager().track(stack, inserted); + + return remainder; + } + /** * Extracts a fluid from this network. * diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/IGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/IGrid.java index 6b371ee5b..bbf4e0803 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/IGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/IGrid.java @@ -47,7 +47,7 @@ public interface IGrid { /** * @return the grid type */ - GridType getType(); + GridType getGridType(); /** * @param player the player to create a listener for diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/IGridTab.java b/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/IGridTab.java index 0bf52c373..fa5455e12 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/IGridTab.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/IGridTab.java @@ -1,8 +1,10 @@ package com.raoulvdberge.refinedstorage.api.network.grid; +import com.raoulvdberge.refinedstorage.api.render.IElementDrawer; import com.raoulvdberge.refinedstorage.api.util.IFilter; import net.minecraft.client.gui.FontRenderer; import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; import java.util.List; @@ -30,7 +32,10 @@ public interface IGridTab { void drawTooltip(int x, int y, int screenWidth, int screenHeight, FontRenderer fontRenderer); /** - * @return the icon + * Draws the icon. + * + * @param x the x position + * @param y the y position */ - ItemStack getIcon(); + void drawIcon(int x, int y, IElementDrawer itemDrawer, IElementDrawer fluidDrawer); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/handler/IFluidGridHandler.java b/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/handler/IFluidGridHandler.java index ea33d6416..5197a9ae7 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/handler/IFluidGridHandler.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/network/grid/handler/IFluidGridHandler.java @@ -45,4 +45,24 @@ public interface IFluidGridHandler { * @return the remainder container */ ItemStack onShiftClick(EntityPlayerMP player, ItemStack container); + + + /** + * Called when a player requests the crafting preview window to be opened. + * + * @param player the player + * @param hash the item stack hash + * @param quantity the amount of that item that we need a preview for + * @param noPreview true if the crafting preview window shouldn't be shown, false otherwise + */ + void onCraftingPreviewRequested(EntityPlayerMP player, int hash, int quantity, boolean noPreview); + + /** + * Called when a player requested crafting for an item. + * + * @param player the player that is requesting the crafting + * @param hash the hash of the item to request a craft for + * @param quantity the amount of the item that has to be crafted + */ + void onCraftingRequested(EntityPlayerMP player, int hash, int quantity); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/util/IQuantityFormatter.java b/src/main/java/com/raoulvdberge/refinedstorage/api/util/IQuantityFormatter.java index 9e8d37d2b..ca91e4804 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/util/IQuantityFormatter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/util/IQuantityFormatter.java @@ -24,4 +24,20 @@ public interface IQuantityFormatter { * @return the formatted quantity */ String format(int qty); + + /** + * Divides quantity by 1000 and appends "B". + * + * @param qty the quantity + * @return the formatted quantity + */ + String formatInBucketForm(int qty); + + /** + * Used in Fluid Grid. + * + * @param qty the quantity + * @return the formatted quantity + */ + String formatInBucketFormWithOnlyTrailingDigitsIfZero(int qty); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/API.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/API.java index cbc1293af..70de218a8 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/API.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/API.java @@ -9,6 +9,8 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftin import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry; import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry; import com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskRegistry; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.api.network.grid.wireless.IWirelessGridRegistry; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; @@ -27,6 +29,7 @@ import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.api.util.IOneSixMigrationHelper; import com.raoulvdberge.refinedstorage.api.util.IQuantityFormatter; import com.raoulvdberge.refinedstorage.api.util.IStackList; +import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingRequestInfo; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementRegistry; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementRegistry; @@ -246,6 +249,21 @@ public class API implements IRSAPI { return new StorageDiskFluid(world, capacity); } + @Override + public ICraftingRequestInfo createCraftingRequestInfo(ItemStack stack) { + return new CraftingRequestInfo(stack); + } + + @Override + public ICraftingRequestInfo createCraftingRequestInfo(FluidStack stack) { + return new CraftingRequestInfo(stack); + } + + @Override + public ICraftingRequestInfo createCraftingRequestInfo(NBTTagCompound tag) throws CraftingTaskReadException { + return new CraftingRequestInfo(tag); + } + @Override @Nonnull public IOneSixMigrationHelper getOneSixMigrationHelper() { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingManager.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingManager.java index a816c3ee3..91787e2d7 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingManager.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingManager.java @@ -10,12 +10,14 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadExc import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; +import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.tile.TileController; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.items.IItemHandlerModifiable; import javax.annotation.Nonnull; @@ -91,7 +93,23 @@ public class CraftingManager implements ICraftingManager { return null; } - return factory.create(network, stack, quantity, pattern); + return factory.create(network, API.instance().createCraftingRequestInfo(stack), quantity, pattern); + } + + @Nullable + @Override + public ICraftingTask create(FluidStack stack, int quantity) { + ICraftingPattern pattern = getPattern(stack); + if (pattern == null) { + return null; + } + + ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(pattern.getId()); + if (factory == null) { + return null; + } + + return factory.create(network, API.instance().createCraftingRequestInfo(stack), quantity, pattern); } @Override @@ -200,12 +218,15 @@ public class CraftingManager implements ICraftingManager { listeners.forEach(ICraftingMonitorListener::onChanged); } + //TODO: Make fluid version @Override @Nullable public ICraftingTask request(ItemStack stack, int amount) { for (ICraftingTask task : getTasks()) { - if (API.instance().getComparer().isEqualNoQuantity(task.getRequested(), stack)) { - amount -= task.getQuantity(); + if (task.getRequested().getItem() != null) { + if (API.instance().getComparer().isEqualNoQuantity(task.getRequested().getItem(), stack)) { + amount -= task.getQuantity(); + } } } @@ -231,7 +252,24 @@ public class CraftingManager implements ICraftingManager { int initialSize = size; for (ICraftingTask task : tasks.values()) { - size = task.onTrackedItemInserted(stack, size); + size = task.onTrackedInsert(stack, size); + + if (size == 0) { + break; + } + } + + if (size != initialSize) { + this.onTaskChanged(); + } + } + + @Override + public void track(FluidStack stack, int size) { + int initialSize = size; + + for (ICraftingTask task : tasks.values()) { + size = task.onTrackedInsert(stack, size); if (size == 0) { break; @@ -286,4 +324,18 @@ public class CraftingManager implements ICraftingManager { return null; } + + @Nullable + @Override + public ICraftingPattern getPattern(FluidStack pattern) { + for (ICraftingPattern patternInList : patterns) { + for (FluidStack output : patternInList.getFluidOutputs()) { + if (API.instance().getComparer().isEqual(output, pattern, IComparer.COMPARE_NBT)) { + return patternInList; + } + } + } + + return null; + } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingPattern.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingPattern.java index e2f1e16f8..8a302cc63 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingPattern.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingPattern.java @@ -2,6 +2,7 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting; import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern; import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer; +import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.registry.CraftingTaskFactory; import com.raoulvdberge.refinedstorage.apiimpl.util.OneSixMigrationHelper; @@ -15,6 +16,7 @@ import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.IRecipe; import net.minecraft.util.NonNullList; import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.oredict.OreDictionary; import java.util.ArrayList; @@ -30,6 +32,8 @@ public class CraftingPattern implements ICraftingPattern { private List> inputs = new ArrayList<>(); private NonNullList outputs = NonNullList.create(); private NonNullList byproducts = NonNullList.create(); + private NonNullList fluidInputs = NonNullList.create(); + private NonNullList fluidOutputs = NonNullList.create(); public CraftingPattern(World world, ICraftingPatternContainer container, ItemStack stack) { if (!OneSixMigrationHelper.isValidOneSixPattern(stack)) { @@ -77,6 +81,20 @@ public class CraftingPattern implements ICraftingPattern { outputs.add(output); } + + FluidStack fluidInput = ItemPattern.getFluidInputSlot(stack, i); + if (fluidInput != null) { + this.valid = true; + + fluidInputs.add(fluidInput); + } + + FluidStack fluidOutput = ItemPattern.getFluidOutputSlot(stack, i); + if (fluidOutput != null) { + this.valid = true; + + fluidOutputs.add(fluidOutput); + } } } else { InventoryCrafting inv = new InventoryCraftingDummy(); @@ -218,6 +236,16 @@ public class CraftingPattern implements ICraftingPattern { return sanitized; } + @Override + public NonNullList getFluidInputs() { + return fluidInputs; + } + + @Override + public NonNullList getFluidOutputs() { + return fluidOutputs; + } + @Override public String getId() { return CraftingTaskFactory.ID; @@ -229,7 +257,10 @@ public class CraftingPattern implements ICraftingPattern { return false; } - if ((other.getInputs().size() != inputs.size()) || (other.getOutputs().size() != outputs.size())) { + if ((other.getInputs().size() != inputs.size()) || + (other.getFluidInputs().size() != fluidInputs.size()) || + (other.getOutputs().size() != outputs.size()) || + (other.getFluidOutputs().size() != fluidOutputs.size())) { return false; } @@ -252,12 +283,24 @@ public class CraftingPattern implements ICraftingPattern { } } + for (int i = 0; i < fluidInputs.size(); ++i) { + if (!API.instance().getComparer().isEqual(fluidInputs.get(i), other.getFluidInputs().get(i), IComparer.COMPARE_NBT | IComparer.COMPARE_QUANTITY)) { + return false; + } + } + for (int i = 0; i < outputs.size(); ++i) { if (!API.instance().getComparer().isEqual(outputs.get(i), other.getOutputs().get(i))) { return false; } } + for (int i = 0; i < fluidOutputs.size(); ++i) { + if (!API.instance().getComparer().isEqual(fluidOutputs.get(i), other.getFluidOutputs().get(i), IComparer.COMPARE_NBT | IComparer.COMPARE_QUANTITY)) { + return false; + } + } + if (!processing) { for (int i = 0; i < byproducts.size(); ++i) { if (!API.instance().getComparer().isEqual(byproducts.get(i), other.getByproducts().get(i))) { @@ -282,10 +325,18 @@ public class CraftingPattern implements ICraftingPattern { } } + for (FluidStack input : this.fluidInputs) { + result = 31 * result + API.instance().getFluidStackHashCode(input); + } + for (ItemStack output : this.outputs) { result = 31 * result + API.instance().getItemStackHashCode(output); } + for (FluidStack output : this.fluidOutputs) { + result = 31 * result + API.instance().getFluidStackHashCode(output); + } + for (ItemStack byproduct : this.byproducts) { result = 31 * result + API.instance().getItemStackHashCode(byproduct); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingRequestInfo.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingRequestInfo.java new file mode 100644 index 000000000..9548cd168 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingRequestInfo.java @@ -0,0 +1,69 @@ +package com.raoulvdberge.refinedstorage.apiimpl.autocrafting; + +import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; +import com.raoulvdberge.refinedstorage.util.StackUtils; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; + +import javax.annotation.Nullable; + +public class CraftingRequestInfo implements ICraftingRequestInfo { + private static final String NBT_FLUID = "Fluid"; + private static final String NBT_STACK = "Stack"; + + private ItemStack item; + private FluidStack fluid; + + public CraftingRequestInfo(NBTTagCompound tag) throws CraftingTaskReadException { + if (!tag.getBoolean(NBT_FLUID)) { + item = StackUtils.deserializeStackFromNbt(tag.getCompoundTag(NBT_STACK)); + + if (item.isEmpty()) { + throw new CraftingTaskReadException("Extractor stack is empty"); + } + } else { + fluid = FluidStack.loadFluidStackFromNBT(tag.getCompoundTag(NBT_STACK)); + + if (fluid == null) { + throw new CraftingTaskReadException("Extractor fluid stack is emty"); + } + } + } + + public CraftingRequestInfo(ItemStack item) { + this.item = item; + } + + public CraftingRequestInfo(FluidStack fluid) { + this.fluid = fluid; + } + + @Nullable + @Override + public ItemStack getItem() { + return item; + } + + @Nullable + @Override + public FluidStack getFluid() { + return fluid; + } + + @Override + public NBTTagCompound writeToNbt() { + NBTTagCompound tag = new NBTTagCompound(); + + tag.setBoolean(NBT_FLUID, fluid != null); + + if (fluid != null) { + tag.setTag(NBT_STACK, fluid.writeToNBT(new NBTTagCompound())); + } else { + tag.setTag(NBT_STACK, StackUtils.serializeStackToNbt(item)); + } + + return tag; + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/craftingmonitor/CraftingMonitorElementFluidRender.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/craftingmonitor/CraftingMonitorElementFluidRender.java index dead8e498..62609e727 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/craftingmonitor/CraftingMonitorElementFluidRender.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/craftingmonitor/CraftingMonitorElementFluidRender.java @@ -15,10 +15,12 @@ public class CraftingMonitorElementFluidRender implements ICraftingMonitorElemen public static final String ID = "fluid_render"; private FluidStack stack; + private int quantity; private int offset; - public CraftingMonitorElementFluidRender(FluidStack stack, int offset) { + public CraftingMonitorElementFluidRender(FluidStack stack, int quantity, int offset) { this.stack = stack; + this.quantity = quantity; this.offset = offset; } @@ -36,7 +38,7 @@ public class CraftingMonitorElementFluidRender implements ICraftingMonitorElemen GlStateManager.pushMatrix(); GlStateManager.scale(scale, scale, 1); - drawers.getStringDrawer().draw(RenderUtils.getOffsetOnScale(x + 21 + offset, scale), RenderUtils.getOffsetOnScale(y + 7, scale), API.instance().getQuantityFormatter().format(stack.amount) + " mB " + stack.getLocalizedName()); + drawers.getStringDrawer().draw(RenderUtils.getOffsetOnScale(x + 21 + offset, scale), RenderUtils.getOffsetOnScale(y + 7, scale), API.instance().getQuantityFormatter().formatInBucketForm(quantity) + " " + stack.getLocalizedName()); GlStateManager.popMatrix(); } @@ -49,13 +51,14 @@ public class CraftingMonitorElementFluidRender implements ICraftingMonitorElemen @Override public void write(ByteBuf buf) { StackUtils.writeFluidStack(buf, stack); + buf.writeInt(quantity); buf.writeInt(offset); } @Override public boolean merge(ICraftingMonitorElement element) { if (element.getId().equals(getId()) && elementHashCode() == element.elementHashCode()) { - this.stack.amount += ((CraftingMonitorElementFluidRender) element).stack.amount; + this.quantity += ((CraftingMonitorElementFluidRender) element).quantity; return true; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/preview/CraftingPreviewElementFluidStack.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/preview/CraftingPreviewElementFluidStack.java index 238f2d54c..e25ad1497 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/preview/CraftingPreviewElementFluidStack.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/preview/CraftingPreviewElementFluidStack.java @@ -2,6 +2,7 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview; import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.raoulvdberge.refinedstorage.api.render.IElementDrawers; +import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.gui.GuiBase; import com.raoulvdberge.refinedstorage.util.RenderUtils; import io.netty.buffer.ByteBuf; @@ -25,7 +26,6 @@ public class CraftingPreviewElementFluidStack implements ICraftingPreviewElement public CraftingPreviewElementFluidStack(FluidStack stack) { this.stack = stack.copy(); - this.available = stack.amount; } public CraftingPreviewElementFluidStack(FluidStack stack, int available, boolean missing, int toCraft) { @@ -73,11 +73,21 @@ public class CraftingPreviewElementFluidStack implements ICraftingPreviewElement float scale = drawers.getFontRenderer().getUnicodeFlag() ? 1F : 0.5F; + y += 2; + GlStateManager.pushMatrix(); GlStateManager.scale(scale, scale, 1); - drawers.getStringDrawer().draw(RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y + 3, scale), GuiBase.t("gui.refinedstorage:crafting_preview.available", "")); - drawers.getStringDrawer().draw(RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y + 9, scale), getAvailable() + " mB"); + if (getToCraft() > 0) { + String format = hasMissing() ? "gui.refinedstorage:crafting_preview.missing" : "gui.refinedstorage:crafting_preview.to_craft"; + drawers.getStringDrawer().draw(RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y, scale), GuiBase.t(format, API.instance().getQuantityFormatter().formatInBucketForm(getToCraft()))); + + y += 7; + } + + if (getAvailable() > 0) { + drawers.getStringDrawer().draw(RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y, scale), GuiBase.t("gui.refinedstorage:crafting_preview.available", API.instance().getQuantityFormatter().formatInBucketForm(getAvailable()))); + } GlStateManager.popMatrix(); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/registry/CraftingTaskFactory.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/registry/CraftingTaskFactory.java index d72a6037c..7b87a9b54 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/registry/CraftingTaskFactory.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/registry/CraftingTaskFactory.java @@ -3,10 +3,10 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.registry; import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern; import com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskFactory; import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.CraftingTask; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import javax.annotation.Nonnull; @@ -16,8 +16,8 @@ public class CraftingTaskFactory implements ICraftingTaskFactory { @Nonnull @Override - public ICraftingTask create(INetwork network, ItemStack stack, int quantity, ICraftingPattern pattern) { - return new CraftingTask(network, stack, quantity, pattern); + public ICraftingTask create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) { + return new CraftingTask(network, requested, quantity, pattern); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java index 55fde94ad..0b9ffc666 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java @@ -4,21 +4,21 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.*; import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList; import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; -import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskErrorType; -import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; -import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; -import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.*; import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.api.util.IStackList; import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementColor; +import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementFluidRender; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementItemRender; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementText; +import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementFluidStack; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementItemStack; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractor; -import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractorItemStatus; +import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractorStack; +import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractorStatus; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter.CraftingInserter; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter.CraftingInserterItem; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter.CraftingInserterItemStatus; @@ -33,6 +33,7 @@ import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.items.ItemHandlerHelper; import org.apache.commons.lang3.tuple.Pair; @@ -56,7 +57,7 @@ public class CraftingTask implements ICraftingTask { private static final String NBT_PATTERN_CONTAINER_POS = "ContainerPos"; private INetwork network; - private ItemStack requested; + private ICraftingRequestInfo requested; private int quantity; private ICraftingPattern pattern; private List steps = new LinkedList<>(); @@ -68,10 +69,15 @@ public class CraftingTask implements ICraftingTask { private UUID id = UUID.randomUUID(); private IStackList toTake = API.instance().createItemStackList(); - private IStackList missing = API.instance().createItemStackList(); - private IStackList toCraft = API.instance().createItemStackList(); + private IStackList toTakeFluids = API.instance().createFluidStackList(); - public CraftingTask(INetwork network, ItemStack requested, int quantity, ICraftingPattern pattern) { + private IStackList missing = API.instance().createItemStackList(); + private IStackList missingFluids = API.instance().createFluidStackList(); + + private IStackList toCraft = API.instance().createItemStackList(); + private IStackList toCraftFluids = API.instance().createFluidStackList(); + + public CraftingTask(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) { this.network = network; this.inserter = new CraftingInserter(network); this.requested = requested; @@ -82,11 +88,7 @@ public class CraftingTask implements ICraftingTask { public CraftingTask(INetwork network, NBTTagCompound tag) throws CraftingTaskReadException { this.network = network; - this.requested = new ItemStack(tag.getCompoundTag(NBT_REQUESTED)); - if (requested.isEmpty()) { - throw new CraftingTaskReadException("Requested item doesn't exist anymore"); - } - + this.requested = API.instance().createCraftingRequestInfo(tag.getCompoundTag(NBT_REQUESTED)); this.quantity = tag.getInteger(NBT_QUANTITY); this.pattern = readPatternFromNbt(tag.getCompoundTag(NBT_PATTERN), network.world()); this.inserter = new CraftingInserter(network, tag.getTagList(NBT_INSERTER, Constants.NBT.TAG_COMPOUND)); @@ -134,7 +136,10 @@ public class CraftingTask implements ICraftingTask { int crafted = 0; IStackList results = API.instance().createItemStackList(); + IStackList fluidResults = API.instance().createFluidStackList(); + IStackList storage = network.getItemStorageCache().getList().copy(); + IStackList fluidStorage = network.getFluidStorageCache().getList().copy(); // Items that are being handled in other tasks aren't available to us. for (ICraftingTask task : network.getCraftingManager().getTasks()) { @@ -149,8 +154,20 @@ public class CraftingTask implements ICraftingTask { } if (extractor != null) { - for (ItemStack inUse : extractor.getItems()) { - storage.remove(inUse); + for (CraftingExtractorStack inUse : extractor.getStacks()) { + ItemStack inUseItem = inUse.getItem(); + + if (inUseItem != null) { + storage.remove(inUseItem); + } else { + FluidStack inUseFluid = inUse.getFluid(); + + if (inUseFluid != null) { + fluidStorage.remove(inUseFluid); + } else { + throw new IllegalStateException("Extractor stack is neither a fluid or an item!"); + } + } } } } @@ -162,7 +179,7 @@ public class CraftingTask implements ICraftingTask { ICraftingPatternChain patternChain = patternChainList.getChain(pattern); while (qty > 0) { - Pair result = calculateInternal(storage, results, patternChainList, patternChain.current()); + Pair result = calculateInternal(storage, fluidStorage, results, fluidResults, patternChainList, patternChain.current()); if (result.getRight() != null) { return result.getRight(); @@ -177,12 +194,23 @@ public class CraftingTask implements ICraftingTask { patternChain.cycle(); } - this.toCraft.add(requested, crafted); + if (requested.getItem() != null) { + this.toCraft.add(requested.getItem(), crafted); + } else { + this.toCraftFluids.add(requested.getFluid(), crafted); + } return null; } - private Pair calculateInternal(IStackList mutatedStorage, IStackList results, ICraftingPatternChainList patternChainList, ICraftingPattern pattern) { + private Pair calculateInternal( + IStackList mutatedStorage, + IStackList mutatedFluidStorage, + IStackList results, + IStackList fluidResults, + ICraftingPatternChainList patternChainList, + ICraftingPattern pattern) { + if (System.currentTimeMillis() - calculationStarted > CALCULATION_TIMEOUT_MS) { return Pair.of(null, new CraftingTaskError(CraftingTaskErrorType.TOO_COMPLEX)); } @@ -192,6 +220,7 @@ public class CraftingTask implements ICraftingTask { } IStackList itemsToExtract = API.instance().createItemStackList(); + IStackList fluidsToExtract = API.instance().createFluidStackList(); NonNullList took = NonNullList.create(); @@ -270,7 +299,7 @@ public class CraftingTask implements ICraftingTask { ICraftingPatternChain subPatternChain = patternChainList.getChain(subPattern); while ((fromSelf == null ? 0 : fromSelf.getCount()) < remaining) { - Pair result = calculateInternal(mutatedStorage, results, patternChainList, subPatternChain.current()); + Pair result = calculateInternal(mutatedStorage, mutatedFluidStorage, results, fluidResults, patternChainList, subPatternChain.current()); if (result.getRight() != null) { return Pair.of(null, result.getRight()); @@ -301,6 +330,73 @@ public class CraftingTask implements ICraftingTask { } } + for (FluidStack input : pattern.getFluidInputs()) { + FluidStack fromSelf = fluidResults.get(input, IComparer.COMPARE_NBT); + FluidStack fromNetwork = mutatedFluidStorage.get(input, IComparer.COMPARE_NBT); + + int remaining = input.amount; + + while (remaining > 0) { + if (fromSelf != null) { + int toTake = Math.min(remaining, fromSelf.amount); + + fluidsToExtract.add(input, toTake); + + fluidResults.remove(input, toTake); + + remaining -= toTake; + + fromSelf = fluidResults.get(input, IComparer.COMPARE_NBT); + } else if (fromNetwork != null) { + int toTake = Math.min(remaining, fromNetwork.amount); + + this.toTakeFluids.add(input, toTake); + + fluidsToExtract.add(input, toTake); + + mutatedFluidStorage.remove(fromNetwork, toTake); + + remaining -= toTake; + + fromNetwork = mutatedFluidStorage.get(input, IComparer.COMPARE_NBT); + } else { + ICraftingPattern subPattern = network.getCraftingManager().getPattern(input); + + if (subPattern != null) { + ICraftingPatternChain subPatternChain = patternChainList.getChain(subPattern); + + while ((fromSelf == null ? 0 : fromSelf.amount) < remaining) { + Pair result = calculateInternal(mutatedStorage, mutatedFluidStorage, results, fluidResults, patternChainList, subPatternChain.current()); + + if (result.getRight() != null) { + return Pair.of(null, result.getRight()); + } + + this.steps.add(result.getLeft()); + + fromSelf = fluidResults.get(input, IComparer.COMPARE_NBT); + if (fromSelf == null) { + throw new IllegalStateException("Recursive fluid calculation didn't yield anything"); + } + + fromNetwork = mutatedFluidStorage.get(input, IComparer.COMPARE_NBT); + + subPatternChain.cycle(); + } + + // fromSelf contains the amount crafted after the loop. + this.toCraftFluids.add(input, fromSelf.amount); + } else { + this.missingFluids.add(input, remaining); + + fluidsToExtract.add(input, remaining); + + remaining = 0; + } + } + } + } + patternsUsed.remove(pattern); if (pattern.isProcessing()) { @@ -308,8 +404,16 @@ public class CraftingTask implements ICraftingTask { results.add(output); } - return Pair.of(new CraftingStepProcess(pattern, network, new ArrayList<>(itemsToExtract.getStacks())), null); + for (FluidStack output : pattern.getFluidOutputs()) { + fluidResults.add(output); + } + + return Pair.of(new CraftingStepProcess(pattern, network, new ArrayList<>(itemsToExtract.getStacks()), new ArrayList<>(fluidsToExtract.getStacks())), null); } else { + if (!fluidsToExtract.isEmpty()) { + throw new IllegalStateException("Cannot extract fluids in normal pattern!"); + } + results.add(pattern.getOutput(took)); for (ItemStack byproduct : pattern.getByproducts(took)) { @@ -320,15 +424,23 @@ public class CraftingTask implements ICraftingTask { } } - private int getQuantityPerCraft(ICraftingPattern pattern, ItemStack requested) { + private int getQuantityPerCraft(ICraftingPattern pattern, ICraftingRequestInfo requested) { int qty = 0; - for (ItemStack output : pattern.getOutputs()) { - if (API.instance().getComparer().isEqualNoQuantity(output, requested)) { - qty += output.getCount(); + if (requested.getItem() != null) { + for (ItemStack output : pattern.getOutputs()) { + if (API.instance().getComparer().isEqualNoQuantity(output, requested.getItem())) { + qty += output.getCount(); - if (!pattern.isProcessing()) { - break; + if (!pattern.isProcessing()) { + break; + } + } + } + } else { + for (FluidStack output : pattern.getFluidOutputs()) { + if (API.instance().getComparer().isEqual(output, requested.getFluid(), IComparer.COMPARE_NBT)) { + qty += output.amount; } } } @@ -376,12 +488,12 @@ public class CraftingTask implements ICraftingTask { } @Override - public ItemStack getRequested() { + public ICraftingRequestInfo getRequested() { return requested; } @Override - public int onTrackedItemInserted(ItemStack stack, int size) { + public int onTrackedInsert(ItemStack stack, int size) { for (CraftingStep step : steps) { if (step instanceof CraftingStepProcess) { size = ((CraftingStepProcess) step).onTrackedItemInserted(stack, size); @@ -395,13 +507,31 @@ public class CraftingTask implements ICraftingTask { return size; } + @Override + public int onTrackedInsert(FluidStack stack, int size) { + for (CraftingStep step : steps) { + if (step instanceof CraftingStepProcess) { + size = ((CraftingStepProcess) step).onTrackedFluidInserted(stack, size); + + if (size == 0) { + break; + } + } + } + + return size; + } + + // TODO: Fix lang keys. @Override public List getCraftingMonitorElements() { ICraftingMonitorElementList elements = API.instance().createCraftingMonitorElementList(); - if (!missing.isEmpty()) { + if (!missing.isEmpty() || !missingFluids.isEmpty()) { elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_missing", 5)); + } + if (!missing.isEmpty()) { for (ItemStack missing : this.missing.getStacks()) { elements.add(new CraftingMonitorElementColor(new CraftingMonitorElementItemRender(missing, missing.getCount(), 0), "", CraftingMonitorElementColor.COLOR_ERROR)); } @@ -409,6 +539,14 @@ public class CraftingTask implements ICraftingTask { elements.commit(); } + if (!missingFluids.isEmpty()) { + for (FluidStack missing : this.missingFluids.getStacks()) { + elements.add(new CraftingMonitorElementColor(new CraftingMonitorElementFluidRender(missing, missing.amount, 0), "", CraftingMonitorElementColor.COLOR_ERROR)); + } + + elements.commit(); + } + if (!inserter.getItems().isEmpty()) { elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_inserting", 5)); @@ -425,20 +563,20 @@ public class CraftingTask implements ICraftingTask { elements.commit(); } - if (steps.stream().anyMatch(s -> s instanceof CraftingStepCraft && !s.isCompleted() && !((CraftingStepCraft) s).getExtractor().getItems().isEmpty())) { + if (steps.stream().anyMatch(s -> s instanceof CraftingStepCraft && !s.isCompleted() && !((CraftingStepCraft) s).getExtractor().getStacks().isEmpty())) { elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_crafting", 5)); for (CraftingStep step : steps) { if (step instanceof CraftingStepCraft && !step.isCompleted()) { CraftingExtractor extractor = ((CraftingStepCraft) step).getExtractor(); - for (int i = 0; i < extractor.getItems().size(); ++i) { - ItemStack item = extractor.getItems().get(i); - CraftingExtractorItemStatus status = extractor.getStatus().get(i); + for (int i = 0; i < extractor.getStacks().size(); ++i) { + // Assume we have an item here. + CraftingExtractorStack stack = extractor.getStacks().get(i); - ICraftingMonitorElement element = new CraftingMonitorElementItemRender(item, item.getCount(), 0); + ICraftingMonitorElement element = new CraftingMonitorElementItemRender(stack.getItem(), stack.getItem().getCount(), 0); - if (status == CraftingExtractorItemStatus.MISSING) { + if (stack.getStatus() == CraftingExtractorStatus.MISSING) { element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.waiting_for_items", CraftingMonitorElementColor.COLOR_INFO); } @@ -450,6 +588,7 @@ public class CraftingTask implements ICraftingTask { elements.commit(); } + // TODO: Make better? if (steps.stream().anyMatch(s -> s instanceof CraftingStepProcess && !s.isCompleted())) { elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_processing", 5)); @@ -457,19 +596,54 @@ public class CraftingTask implements ICraftingTask { if (step instanceof CraftingStepProcess && !step.isCompleted()) { CraftingExtractor extractor = ((CraftingStepProcess) step).getExtractor(); - for (int i = 0; i < extractor.getItems().size(); ++i) { - ItemStack item = extractor.getItems().get(i); - CraftingExtractorItemStatus status = extractor.getStatus().get(i); + for (int i = 0; i < extractor.getStacks().size(); ++i) { + CraftingExtractorStack stack = extractor.getStacks().get(i); - ICraftingMonitorElement element = new CraftingMonitorElementItemRender(item, item.getCount(), 0); + if (stack.getItem() == null) { + continue; + } - if (status == CraftingExtractorItemStatus.MISSING) { + ICraftingMonitorElement element = new CraftingMonitorElementItemRender(stack.getItem(), stack.getItem().getCount(), 0); + + if (stack.getStatus() == CraftingExtractorStatus.MISSING) { element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.waiting_for_items", CraftingMonitorElementColor.COLOR_INFO); - } else if (status == CraftingExtractorItemStatus.MACHINE_DOES_NOT_ACCEPT) { + } else if (stack.getStatus() == CraftingExtractorStatus.MACHINE_DOES_NOT_ACCEPT) { element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.machine_does_not_accept", CraftingMonitorElementColor.COLOR_ERROR); - } else if (status == CraftingExtractorItemStatus.MACHINE_NONE) { + } else if (stack.getStatus() == CraftingExtractorStatus.MACHINE_NONE) { element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.machine_none", CraftingMonitorElementColor.COLOR_ERROR); - } else if (status == CraftingExtractorItemStatus.EXTRACTED) { + } else if (stack.getStatus() == CraftingExtractorStatus.EXTRACTED) { + element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.item_inserted_into_machine", CraftingMonitorElementColor.COLOR_SUCCESS); + } + + elements.add(element); + } + } + } + + elements.commit(); + + for (CraftingStep step : steps) { + if (step instanceof CraftingStepProcess && !step.isCompleted()) { + CraftingExtractor extractor = ((CraftingStepProcess) step).getExtractor(); + + for (int i = 0; i < extractor.getStacks().size(); ++i) { + CraftingExtractorStack stack = extractor.getStacks().get(i); + + ICraftingMonitorElement element; + + if (stack.getItem() != null) { + continue; + } + + element = new CraftingMonitorElementFluidRender(stack.getFluid(), stack.getFluid().amount, 0); + + if (stack.getStatus() == CraftingExtractorStatus.MISSING) { + element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.waiting_for_items", CraftingMonitorElementColor.COLOR_INFO); + } else if (stack.getStatus() == CraftingExtractorStatus.MACHINE_DOES_NOT_ACCEPT) { + element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.machine_does_not_accept", CraftingMonitorElementColor.COLOR_ERROR); + } else if (stack.getStatus() == CraftingExtractorStatus.MACHINE_NONE) { + element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.machine_none", CraftingMonitorElementColor.COLOR_ERROR); + } else if (stack.getStatus() == CraftingExtractorStatus.EXTRACTED) { element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.item_inserted_into_machine", CraftingMonitorElementColor.COLOR_SUCCESS); } @@ -487,6 +661,7 @@ public class CraftingTask implements ICraftingTask { @Override public List getPreviewStacks() { Map map = new LinkedHashMap<>(); + Map mapFluids = new LinkedHashMap<>(); for (ItemStack stack : toCraft.getStacks()) { int hash = API.instance().getItemStackHashCode(stack); @@ -502,6 +677,20 @@ public class CraftingTask implements ICraftingTask { map.put(hash, previewStack); } + for (FluidStack stack : toCraftFluids.getStacks()) { + int hash = API.instance().getFluidStackHashCode(stack); + + CraftingPreviewElementFluidStack previewStack = mapFluids.get(hash); + + if (previewStack == null) { + previewStack = new CraftingPreviewElementFluidStack(stack); + } + + previewStack.addToCraft(stack.amount); + + mapFluids.put(hash, previewStack); + } + for (ItemStack stack : missing.getStacks()) { int hash = API.instance().getItemStackHashCode(stack); @@ -517,6 +706,21 @@ public class CraftingTask implements ICraftingTask { map.put(hash, previewStack); } + for (FluidStack stack : missingFluids.getStacks()) { + int hash = API.instance().getFluidStackHashCode(stack); + + CraftingPreviewElementFluidStack previewStack = mapFluids.get(hash); + + if (previewStack == null) { + previewStack = new CraftingPreviewElementFluidStack(stack); + } + + previewStack.setMissing(true); + previewStack.addToCraft(stack.amount); + + mapFluids.put(hash, previewStack); + } + for (ItemStack stack : toTake.getStacks()) { int hash = API.instance().getItemStackHashCode(stack); @@ -531,7 +735,26 @@ public class CraftingTask implements ICraftingTask { map.put(hash, previewStack); } - return new ArrayList<>(map.values()); + for (FluidStack stack : toTakeFluids.getStacks()) { + int hash = API.instance().getFluidStackHashCode(stack); + + CraftingPreviewElementFluidStack previewStack = mapFluids.get(hash); + + if (previewStack == null) { + previewStack = new CraftingPreviewElementFluidStack(stack); + } + + previewStack.addAvailable(stack.amount); + + mapFluids.put(hash, previewStack); + } + + List elements = new ArrayList<>(); + + elements.addAll(map.values()); + elements.addAll(mapFluids.values()); + + return elements; } @Override @@ -561,7 +784,7 @@ public class CraftingTask implements ICraftingTask { @Override public NBTTagCompound writeToNbt(NBTTagCompound tag) { - tag.setTag(NBT_REQUESTED, requested.serializeNBT()); + tag.setTag(NBT_REQUESTED, requested.writeToNbt()); tag.setInteger(NBT_QUANTITY, quantity); tag.setTag(NBT_PATTERN, writePatternToNbt(pattern)); tag.setTag(NBT_INSERTER, inserter.writeToNbt()); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractor.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractor.java index 09421d9e7..0423aa205 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractor.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractor.java @@ -3,11 +3,12 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor; import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.api.util.Action; +import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.CraftingTask; -import com.raoulvdberge.refinedstorage.util.StackUtils; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; @@ -16,80 +17,75 @@ import java.util.ArrayList; import java.util.List; public class CraftingExtractor { - private static final String NBT_ITEM = "Item"; - private static final String NBT_STATUS = "Status"; - private INetwork network; - private List items; - private List status = new ArrayList<>(); + private List stacks; private boolean processing; - public CraftingExtractor(INetwork network, List items, boolean processing) { + public CraftingExtractor(INetwork network, List stacks, boolean processing) { this.network = network; - this.items = items; + this.stacks = stacks; this.processing = processing; - - for (int i = 0; i < items.size(); ++i) { - status.add(CraftingExtractorItemStatus.MISSING); - } } public CraftingExtractor(INetwork network, NBTTagList tag, boolean processing) throws CraftingTaskReadException { this.network = network; this.processing = processing; - this.items = new ArrayList<>(); + this.stacks = new ArrayList<>(); for (int i = 0; i < tag.tagCount(); ++i) { - NBTTagCompound itemTag = tag.getCompoundTagAt(i); - - ItemStack stack = StackUtils.deserializeStackFromNbt(itemTag.getCompoundTag(NBT_ITEM)); - - if (stack.isEmpty()) { - throw new CraftingTaskReadException("Extractor stack is empty"); - } - - CraftingExtractorItemStatus status = CraftingExtractorItemStatus.values()[itemTag.getInteger(NBT_STATUS)]; - - this.items.add(stack); - this.status.add(status); + this.stacks.add(new CraftingExtractorStack(tag.getCompoundTagAt(i))); } } - public List getItems() { - return items; + public List getStacks() { + return stacks; } - public List getStatus() { - return status; - } - - public void updateStatus(@Nullable IItemHandler processingInventory) { + public void updateStatus(@Nullable IItemHandler processingInventory, @Nullable IFluidHandler processingFluidInventory) { boolean updated = false; - for (int i = 0; i < items.size(); ++i) { - if (status.get(i) != CraftingExtractorItemStatus.EXTRACTED) { - ItemStack stack = items.get(i); + for (CraftingExtractorStack stack : stacks) { + if (stack.getStatus() != CraftingExtractorStatus.EXTRACTED) { + CraftingExtractorStatus previousStatus = stack.getStatus(); - ItemStack inNetwork = network.extractItem(stack, stack.getCount(), CraftingTask.getFlags(stack), Action.SIMULATE); + if (stack.getItem() != null) { + ItemStack item = stack.getItem(); - CraftingExtractorItemStatus previousStatus = status.get(i); + ItemStack inNetwork = network.extractItem(item, item.getCount(), CraftingTask.getFlags(item), Action.SIMULATE); - if (inNetwork == null || inNetwork.getCount() < stack.getCount()) { - status.set(i, CraftingExtractorItemStatus.MISSING); + if (inNetwork == null || inNetwork.getCount() < item.getCount()) { + stack.setStatus(CraftingExtractorStatus.MISSING); + } else { + stack.setStatus(CraftingExtractorStatus.AVAILABLE); + + if (processing) { + if (processingInventory == null) { + stack.setStatus(CraftingExtractorStatus.MACHINE_NONE); + } else if (!ItemHandlerHelper.insertItem(processingInventory, item, true).isEmpty()) { + stack.setStatus(CraftingExtractorStatus.MACHINE_DOES_NOT_ACCEPT); + } + } + } } else { - status.set(i, CraftingExtractorItemStatus.AVAILABLE); + FluidStack fluid = stack.getFluid(); - if (processing) { - if (processingInventory == null) { - status.set(i, CraftingExtractorItemStatus.MACHINE_NONE); - } else if (!ItemHandlerHelper.insertItem(processingInventory, stack, true).isEmpty()) { - status.set(i, CraftingExtractorItemStatus.MACHINE_DOES_NOT_ACCEPT); + FluidStack inNetwork = network.extractFluid(fluid, fluid.amount, IComparer.COMPARE_NBT, Action.SIMULATE); + + if (inNetwork == null || inNetwork.amount < fluid.amount) { + stack.setStatus(CraftingExtractorStatus.MISSING); + } else { + stack.setStatus(CraftingExtractorStatus.AVAILABLE); + + if (processingFluidInventory == null) { + stack.setStatus(CraftingExtractorStatus.MACHINE_NONE); + } else if (processingFluidInventory.fill(fluid, false) != fluid.amount) { + stack.setStatus(CraftingExtractorStatus.MACHINE_DOES_NOT_ACCEPT); } } } - if (previousStatus != status.get(i)) { + if (previousStatus != stack.getStatus()) { updated = true; } } @@ -101,43 +97,67 @@ public class CraftingExtractor { } public boolean isAllAvailable() { - return !items.isEmpty() && status.stream().allMatch(s -> s == CraftingExtractorItemStatus.AVAILABLE || s == CraftingExtractorItemStatus.EXTRACTED); + return !stacks.isEmpty() && stacks.stream().allMatch(s -> s.getStatus() == CraftingExtractorStatus.AVAILABLE || s.getStatus() == CraftingExtractorStatus.EXTRACTED); } public boolean isAllExtracted() { - return !items.isEmpty() && status.stream().allMatch(s -> s == CraftingExtractorItemStatus.EXTRACTED); + return !stacks.isEmpty() && stacks.stream().allMatch(s -> s.getStatus() == CraftingExtractorStatus.EXTRACTED); } - public void extractOne(@Nullable IItemHandler processingInventory) { + public void extractOne(@Nullable IItemHandler processingInventory, @Nullable IFluidHandler processingFluidInventory) { boolean changed = false; - for (int i = 0; i < items.size(); ++i) { - if (status.get(i) == CraftingExtractorItemStatus.AVAILABLE) { - ItemStack extracted = network.extractItem(items.get(i), items.get(i).getCount(), CraftingTask.getFlags(items.get(i)), Action.PERFORM); - if (extracted == null) { - throw new IllegalStateException("Did not extract anything while available"); - } + for (CraftingExtractorStack stack : stacks) { + if (stack.getStatus() == CraftingExtractorStatus.AVAILABLE) { + if (stack.getItem() != null) { + ItemStack item = stack.getItem(); - if (processing) { - if (processingInventory == null) { - throw new IllegalStateException("Processing inventory is null"); + ItemStack extracted = network.extractItem(item, item.getCount(), CraftingTask.getFlags(item), Action.PERFORM); + if (extracted == null) { + throw new IllegalStateException("Did not extract anything while available"); } - ItemStack remainder = ItemHandlerHelper.insertItem(processingInventory, extracted, false); - if (!remainder.isEmpty()) { - throw new IllegalStateException("The processing inventory gave back a remainder while it previously stated it could handle all"); + if (processing) { + if (processingInventory == null) { + throw new IllegalStateException("Processing inventory is null"); + } + + ItemStack remainder = ItemHandlerHelper.insertItem(processingInventory, extracted, false); + if (!remainder.isEmpty()) { + throw new IllegalStateException("The processing inventory gave back a remainder while it previously stated it could handle all"); + } } + + stack.setStatus(CraftingExtractorStatus.EXTRACTED); + + changed = true; + } else { + FluidStack fluid = stack.getFluid(); + + FluidStack extracted = network.extractFluid(fluid, fluid.amount, IComparer.COMPARE_NBT, Action.PERFORM); + if (extracted == null) { + throw new IllegalStateException("Did not extract any fluids while available"); + } + + if (processingFluidInventory == null) { + throw new IllegalStateException("Processing fluid inventory is null"); + } + + int filled = processingFluidInventory.fill(fluid, true); + if (filled != fluid.amount) { + throw new IllegalStateException("The processing fluid inventory gave back a remainder while it previously stated it could handle all"); + } + + stack.setStatus(CraftingExtractorStatus.EXTRACTED); + + changed = true; } - status.set(i, CraftingExtractorItemStatus.EXTRACTED); - - changed = true; - // For processing patterns we want to insert all items at once to avoid conflicts with other crafting steps. if (!processing) { return; } else { - updateStatus(processingInventory); + updateStatus(processingInventory, processingFluidInventory); } } } @@ -150,13 +170,8 @@ public class CraftingExtractor { public NBTTagList writeToNbt() { NBTTagList list = new NBTTagList(); - for (int i = 0; i < items.size(); ++i) { - NBTTagCompound tag = new NBTTagCompound(); - - tag.setTag(NBT_ITEM, StackUtils.serializeStackToNbt(items.get(i))); - tag.setInteger(NBT_STATUS, status.get(i).ordinal()); - - list.appendTag(tag); + for (CraftingExtractorStack stack : stacks) { + list.appendTag(stack.writeToNbt()); } return list; diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractorStack.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractorStack.java new file mode 100644 index 000000000..75b7d0140 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractorStack.java @@ -0,0 +1,79 @@ +package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor; + +import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; +import com.raoulvdberge.refinedstorage.util.StackUtils; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; + +import javax.annotation.Nullable; + +public class CraftingExtractorStack { + private static final String NBT_FLUID = "Fluid"; + private static final String NBT_STACK = "Stack"; + private static final String NBT_STATUS = "Status"; + + private ItemStack item; + private FluidStack fluid; + private CraftingExtractorStatus status = CraftingExtractorStatus.MISSING; + + public CraftingExtractorStack(ItemStack item) { + this.item = item; + } + + public CraftingExtractorStack(FluidStack fluid) { + this.fluid = fluid; + } + + public CraftingExtractorStack(NBTTagCompound tag) throws CraftingTaskReadException { + if (!tag.getBoolean(NBT_FLUID)) { + item = StackUtils.deserializeStackFromNbt(tag.getCompoundTag(NBT_STACK)); + + if (item.isEmpty()) { + throw new CraftingTaskReadException("Extractor stack is empty"); + } + } else { + fluid = FluidStack.loadFluidStackFromNBT(tag.getCompoundTag(NBT_STACK)); + + if (fluid == null) { + throw new CraftingTaskReadException("Extractor fluid stack is empty"); + } + } + + status = CraftingExtractorStatus.values()[tag.getInteger(NBT_STATUS)]; + } + + @Nullable + public ItemStack getItem() { + return item; + } + + @Nullable + public FluidStack getFluid() { + return fluid; + } + + public NBTTagCompound writeToNbt() { + NBTTagCompound tag = new NBTTagCompound(); + + tag.setBoolean(NBT_FLUID, fluid != null); + + if (fluid != null) { + tag.setTag(NBT_STACK, fluid.writeToNBT(new NBTTagCompound())); + } else { + tag.setTag(NBT_STACK, StackUtils.serializeStackToNbt(item)); + } + + tag.setInteger(NBT_STATUS, status.ordinal()); + + return tag; + } + + public CraftingExtractorStatus getStatus() { + return status; + } + + public void setStatus(CraftingExtractorStatus status) { + this.status = status; + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractorItemStatus.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractorStatus.java similarity index 80% rename from src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractorItemStatus.java rename to src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractorStatus.java index 6b9a26ad0..7843d7963 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractorItemStatus.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/extractor/CraftingExtractorStatus.java @@ -1,6 +1,6 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor; -public enum CraftingExtractorItemStatus { +public enum CraftingExtractorStatus { AVAILABLE, MISSING, EXTRACTED, diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/step/CraftingStepCraft.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/step/CraftingStepCraft.java index 9b7665242..e58d8104a 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/step/CraftingStepCraft.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/step/CraftingStepCraft.java @@ -4,6 +4,7 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern; import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractor; +import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractorStack; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter.CraftingInserter; import com.raoulvdberge.refinedstorage.util.StackUtils; import net.minecraft.item.ItemStack; @@ -13,6 +14,7 @@ import net.minecraft.util.NonNullList; import net.minecraftforge.common.util.Constants; import java.util.List; +import java.util.stream.Collectors; public class CraftingStepCraft extends CraftingStep { public static final String TYPE = "craft"; @@ -33,7 +35,7 @@ public class CraftingStepCraft extends CraftingStep { } this.inserter = inserter; - this.extractor = new CraftingExtractor(network, toExtract, false); + this.extractor = new CraftingExtractor(network, toExtract.stream().map(CraftingExtractorStack::new).collect(Collectors.toList()), false); this.took = took; } @@ -57,14 +59,14 @@ public class CraftingStepCraft extends CraftingStep { @Override public boolean canExecute() { - extractor.updateStatus(null); + extractor.updateStatus(null, null); return extractor.isAllAvailable(); } @Override public boolean execute() { - extractor.extractOne(null); + extractor.extractOne(null, null); boolean allExtracted = extractor.isAllExtracted(); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/step/CraftingStepProcess.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/step/CraftingStepProcess.java index 916abdb85..afbe3e09b 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/step/CraftingStepProcess.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/step/CraftingStepProcess.java @@ -6,12 +6,15 @@ import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.api.util.IStackList; import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractor; +import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractorStack; import com.raoulvdberge.refinedstorage.util.StackUtils; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fluids.FluidStack; +import java.util.ArrayList; import java.util.List; public class CraftingStepProcess extends CraftingStep { @@ -19,22 +22,39 @@ public class CraftingStepProcess extends CraftingStep { private static final String NBT_EXTRACTOR = "Extractor"; private static final String NBT_TO_RECEIVE = "ToReceive"; + private static final String NBT_TO_RECEIVE_FLUIDS = "ToReceiveFluids"; private CraftingExtractor extractor; - private IStackList itemsToReceive = API.instance().createItemStackList(); - public CraftingStepProcess(ICraftingPattern pattern, INetwork network, List toExtract) { + private IStackList itemsToReceive = API.instance().createItemStackList(); + private IStackList fluidsToReceive = API.instance().createFluidStackList(); + + public CraftingStepProcess(ICraftingPattern pattern, INetwork network, List toExtract, List fluidsToExtract) { super(pattern); if (!pattern.isProcessing()) { throw new IllegalArgumentException("Cannot pass non-processing pattern to processing handler"); } - this.extractor = new CraftingExtractor(network, toExtract, true); + List stacks = new ArrayList<>(); + + for (ItemStack item : toExtract) { + stacks.add(new CraftingExtractorStack(item)); + } + + for (FluidStack fluid : fluidsToExtract) { + stacks.add(new CraftingExtractorStack(fluid)); + } + + this.extractor = new CraftingExtractor(network, stacks, true); for (ItemStack output : pattern.getOutputs()) { this.itemsToReceive.add(output); } + + for (FluidStack output : pattern.getFluidOutputs()) { + this.fluidsToReceive.add(output); + } } public CraftingStepProcess(ICraftingPattern pattern, INetwork network, NBTTagCompound tag) throws CraftingTaskReadException { @@ -56,11 +76,22 @@ public class CraftingStepProcess extends CraftingStep { this.itemsToReceive.add(toReceive); } + + NBTTagList toReceiveFluidsList = tag.getTagList(NBT_TO_RECEIVE_FLUIDS, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < toReceiveFluidsList.tagCount(); ++i) { + FluidStack toReceive = FluidStack.loadFluidStackFromNBT(toReceiveFluidsList.getCompoundTagAt(i)); + + if (toReceive == null) { + throw new CraftingTaskReadException("Fluid to receive is null"); + } + + this.fluidsToReceive.add(toReceive); + } } @Override public boolean canExecute() { - extractor.updateStatus(pattern.getContainer().getConnectedInventory()); + extractor.updateStatus(pattern.getContainer().getConnectedInventory(), pattern.getContainer().getConnectedFluidInventory()); return extractor.isAllAvailable(); } @@ -82,13 +113,30 @@ public class CraftingStepProcess extends CraftingStep { return size - toExtract; } + public int onTrackedFluidInserted(FluidStack stack, int size) { + if (!extractor.isAllExtracted()) { + return size; + } + + FluidStack inList = fluidsToReceive.get(stack); + if (inList == null) { + return size; + } + + int toExtract = Math.min(size, inList.amount); + + fluidsToReceive.remove(stack, toExtract); + + return size - toExtract; + } + @Override public boolean execute() { if (!extractor.isAllExtracted()) { - extractor.extractOne(pattern.getContainer().getConnectedInventory()); + extractor.extractOne(pattern.getContainer().getConnectedInventory(), pattern.getContainer().getConnectedFluidInventory()); } - return extractor.isAllExtracted() && itemsToReceive.isEmpty(); + return extractor.isAllExtracted() && itemsToReceive.isEmpty() && fluidsToReceive.isEmpty(); } @Override @@ -110,6 +158,14 @@ public class CraftingStepProcess extends CraftingStep { tag.setTag(NBT_TO_RECEIVE, toReceive); + NBTTagList toReceiveFluids = new NBTTagList(); + + for (FluidStack toReceiveStack : fluidsToReceive.getStacks()) { + toReceiveFluids.appendTag(toReceiveStack.writeToNBT(new NBTTagCompound())); + } + + tag.setTag(NBT_TO_RECEIVE_FLUIDS, toReceiveFluids); + return tag; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/GridTab.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/GridTab.java index f6495ee59..7b2446f36 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/GridTab.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/GridTab.java @@ -1,9 +1,12 @@ package com.raoulvdberge.refinedstorage.apiimpl.network.grid; import com.raoulvdberge.refinedstorage.api.network.grid.IGridTab; +import com.raoulvdberge.refinedstorage.api.render.IElementDrawer; import com.raoulvdberge.refinedstorage.api.util.IFilter; import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.RenderHelper; import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.client.config.GuiUtils; import java.util.Collections; @@ -33,7 +36,9 @@ public class GridTab implements IGridTab { } @Override - public ItemStack getIcon() { - return icon; + public void drawIcon(int x, int y, IElementDrawer itemDrawer, IElementDrawer fluidDrawer) { + RenderHelper.enableGUIStandardItemLighting(); + + itemDrawer.draw(x, y, icon); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/handler/FluidGridHandler.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/handler/FluidGridHandler.java index 8b3bd0e40..06f153e88 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/handler/FluidGridHandler.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/handler/FluidGridHandler.java @@ -1,12 +1,20 @@ package com.raoulvdberge.refinedstorage.apiimpl.network.grid.handler; +import com.raoulvdberge.refinedstorage.RS; +import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError; import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.raoulvdberge.refinedstorage.api.network.item.INetworkItem; import com.raoulvdberge.refinedstorage.api.network.item.NetworkItemAction; import com.raoulvdberge.refinedstorage.api.network.security.Permission; import com.raoulvdberge.refinedstorage.api.util.Action; +import com.raoulvdberge.refinedstorage.api.util.IStackList; import com.raoulvdberge.refinedstorage.apiimpl.API; +import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementError; +import com.raoulvdberge.refinedstorage.network.MessageGridCraftingPreviewResponse; +import com.raoulvdberge.refinedstorage.network.MessageGridCraftingStartResponse; import com.raoulvdberge.refinedstorage.util.StackUtils; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.InventoryHelper; @@ -18,6 +26,7 @@ import net.minecraftforge.fluids.capability.IFluidHandlerItem; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; +import java.util.Collections; public class FluidGridHandler implements IFluidGridHandler { private INetwork network; @@ -116,4 +125,79 @@ public class FluidGridHandler implements IFluidGridHandler { public ItemStack onShiftClick(EntityPlayerMP player, ItemStack container) { return StackUtils.nullToEmpty(onInsert(player, container)); } + + @Override + public void onCraftingPreviewRequested(EntityPlayerMP player, int hash, int quantity, boolean noPreview) { + if (!network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) { + return; + } + + IStackList cache = API.instance().createFluidStackList(); + + for (ICraftingPattern pattern : network.getCraftingManager().getPatterns()) { + for (FluidStack output : pattern.getFluidOutputs()) { + cache.add(output); + } + } + + FluidStack stack = cache.get(hash); + + if (stack != null) { + Thread calculationThread = new Thread(() -> { + ICraftingTask task = network.getCraftingManager().create(stack, quantity); + if (task == null) { + return; + } + + ICraftingTaskError error = task.calculate(); + + if (error != null) { + RS.INSTANCE.network.sendTo(new MessageGridCraftingPreviewResponse(Collections.singletonList(new CraftingPreviewElementError(error.getType(), error.getRecursedPattern() == null ? ItemStack.EMPTY : error.getRecursedPattern().getStack())), hash, quantity, true), player); + } else if (noPreview && task.getMissing().isEmpty()) { + network.getCraftingManager().add(task); + + RS.INSTANCE.network.sendTo(new MessageGridCraftingStartResponse(), player); + } else { + RS.INSTANCE.network.sendTo(new MessageGridCraftingPreviewResponse(task.getPreviewStacks(), hash, quantity, true), player); + } + }, "RS crafting preview calculation"); + + calculationThread.start(); + } + } + + @Override + public void onCraftingRequested(EntityPlayerMP player, int hash, int quantity) { + if (quantity <= 0 || !network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) { + return; + } + + FluidStack stack = null; + + for (ICraftingPattern pattern : network.getCraftingManager().getPatterns()) { + for (FluidStack output : pattern.getFluidOutputs()) { + if (API.instance().getFluidStackHashCode(output) == hash) { + stack = output; + + break; + } + } + + if (stack != null) { + break; + } + } + + if (stack != null) { + ICraftingTask task = network.getCraftingManager().create(stack, quantity); + if (task == null) { + return; + } + + ICraftingTaskError error = task.calculate(); + if (error == null) { + network.getCraftingManager().add(task); + } + } + } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/handler/ItemGridHandler.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/handler/ItemGridHandler.java index b651cb550..85ee2545e 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/handler/ItemGridHandler.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/handler/ItemGridHandler.java @@ -196,13 +196,13 @@ public class ItemGridHandler implements IItemGridHandler { ICraftingTaskError error = task.calculate(); if (error != null) { - RS.INSTANCE.network.sendTo(new MessageGridCraftingPreviewResponse(Collections.singletonList(new CraftingPreviewElementError(error.getType(), error.getRecursedPattern() == null ? ItemStack.EMPTY : error.getRecursedPattern().getStack())), hash, quantity), player); + RS.INSTANCE.network.sendTo(new MessageGridCraftingPreviewResponse(Collections.singletonList(new CraftingPreviewElementError(error.getType(), error.getRecursedPattern() == null ? ItemStack.EMPTY : error.getRecursedPattern().getStack())), hash, quantity, false), player); } else if (noPreview && task.getMissing().isEmpty()) { network.getCraftingManager().add(task); RS.INSTANCE.network.sendTo(new MessageGridCraftingStartResponse(), player); } else { - RS.INSTANCE.network.sendTo(new MessageGridCraftingPreviewResponse(task.getPreviewStacks(), hash, quantity), player); + RS.INSTANCE.network.sendTo(new MessageGridCraftingPreviewResponse(task.getPreviewStacks(), hash, quantity, false), player); } }, "RS crafting preview calculation"); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java index e5d06bef6..9e68bf0a1 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java @@ -48,6 +48,7 @@ import net.minecraftforge.items.wrapper.CombinedInvWrapper; import javax.annotation.Nullable; +// TODO: Crafting upgrade for fluids. public class NetworkNodeConstructor extends NetworkNode implements IComparable, IType, ICoverable { public static final String ID = "constructor"; diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java index e7536ec52..bcbcbbe76 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java @@ -19,6 +19,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorldNameable; import net.minecraft.world.World; +import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.wrapper.CombinedInvWrapper; @@ -187,6 +188,17 @@ public class NetworkNodeCrafter extends NetworkNode implements ICraftingPatternC return WorldUtils.getItemHandler(proxy.getFacingTile(), proxy.getDirection().getOpposite()); } + @Nullable + @Override + public IFluidHandler getConnectedFluidInventory() { + ICraftingPatternContainer proxy = getRootContainer(); + if (proxy == null) { + return null; + } + + return WorldUtils.getFluidHandler(proxy.getFacingTile(), proxy.getDirection().getOpposite()); + } + @Override @Nullable public TileEntity getConnectedTile() { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java index 884545702..784187cc6 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java @@ -183,7 +183,7 @@ public class NetworkNodeDestructor extends NetworkNode implements IComparable, I if (stack != null && IFilterable.acceptsFluid(fluidFilters, mode, compare, stack) && network.insertFluid(stack, stack.amount, Action.SIMULATE) == null) { FluidStack drained = handler.drain(Fluid.BUCKET_VOLUME, true); - network.insertFluid(drained, drained.amount, Action.PERFORM); + network.insertFluidTracked(drained, drained.amount); } } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java index e3439d727..3b65ff2b7 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java @@ -29,6 +29,7 @@ import net.minecraftforge.items.wrapper.CombinedInvWrapper; import javax.annotation.Nullable; +// TODO: Crafting upgrade for fluids public class NetworkNodeExporter extends NetworkNode implements IComparable, IType, ICoverable { public static final String ID = "exporter"; diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeFluidInterface.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeFluidInterface.java index e3ce819d8..9d128f791 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeFluidInterface.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeFluidInterface.java @@ -19,6 +19,7 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.wrapper.CombinedInvWrapper; import org.apache.commons.lang3.tuple.Pair; +// TODO: Crafting upgrade public class NetworkNodeFluidInterface extends NetworkNode implements IComparable { public static final String ID = "fluid_interface"; @@ -96,7 +97,7 @@ public class NetworkNodeFluidInterface extends NetworkNode implements IComparabl // Drain in tank if (drained != null) { - FluidStack remainder = network.insertFluid(drained, drained.amount, Action.PERFORM); + FluidStack remainder = network.insertFluidTracked(drained, drained.amount); if (remainder != null) { tankIn.fillInternal(remainder, true); @@ -112,7 +113,7 @@ public class NetworkNodeFluidInterface extends NetworkNode implements IComparabl FluidStack remainder = tankOut.drainInternal(Fluid.BUCKET_VOLUME * upgrades.getItemInteractCount(), true); if (remainder != null) { - network.insertFluid(remainder, remainder.amount, Action.PERFORM); + network.insertFluidTracked(remainder, remainder.amount); } } else if (stack != null) { // Fill the out fluid diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeGrid.java index 5aa6ff78b..552f321a3 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeGrid.java @@ -22,11 +22,9 @@ import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.storage.StorageCacheListenerGridFluid; import com.raoulvdberge.refinedstorage.apiimpl.storage.StorageCacheListenerGridItem; import com.raoulvdberge.refinedstorage.block.BlockGrid; -import com.raoulvdberge.refinedstorage.inventory.ItemHandlerBase; -import com.raoulvdberge.refinedstorage.inventory.ItemHandlerFilter; -import com.raoulvdberge.refinedstorage.inventory.ItemHandlerListenerNetworkNode; -import com.raoulvdberge.refinedstorage.inventory.ItemValidatorBasic; +import com.raoulvdberge.refinedstorage.inventory.*; import com.raoulvdberge.refinedstorage.item.ItemPattern; +import com.raoulvdberge.refinedstorage.tile.config.IType; import com.raoulvdberge.refinedstorage.tile.data.TileDataManager; import com.raoulvdberge.refinedstorage.tile.grid.TileGrid; import com.raoulvdberge.refinedstorage.util.StackUtils; @@ -41,6 +39,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; @@ -53,7 +52,7 @@ import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; -public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { +public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware, IType { public static final String ID = "grid"; public static final String NBT_VIEW_TYPE = "ViewType"; @@ -65,6 +64,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { public static final String NBT_TAB_PAGE = "TabPage"; public static final String NBT_SIZE = "Size"; public static final String NBT_PROCESSING_PATTERN = "ProcessingPattern"; + public static final String NBT_PROCESSING_TYPE = "ProcessingType"; private Container craftingContainer = new Container() { @Override @@ -81,6 +81,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { private InventoryCrafting matrix = new InventoryCrafting(craftingContainer, 3, 3); private InventoryCraftResult result = new InventoryCraftResult(); private ItemHandlerBase matrixProcessing = new ItemHandlerBase(9 * 2, new ItemHandlerListenerNetworkNode(this)); + private ItemHandlerFluid matrixProcessingFluids = new ItemHandlerFluid(9 * 2, new ItemHandlerListenerNetworkNode(this)); private ItemHandlerBase patterns = new ItemHandlerBase(2, new ItemHandlerListenerNetworkNode(this), new ItemValidatorBasic(RSItems.PATTERN)) { @Override @@ -144,6 +145,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { private boolean oredictPattern = false; private boolean processingPattern = false; + private int processingType = IType.ITEMS; public NetworkNodeGrid(World world, BlockPos pos) { super(world, pos); @@ -151,7 +153,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { @Override public int getEnergyUsage() { - switch (getType()) { + switch (getGridType()) { case NORMAL: return RS.INSTANCE.config.gridUsage; case CRAFTING: @@ -209,7 +211,8 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { this.processingPattern = processingPattern; } - public GridType getType() { + @Override + public GridType getGridType() { if (type == null) { IBlockState state = world.getBlockState(pos); if (state.getBlock() == RSBlocks.GRID) { @@ -222,13 +225,13 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { @Override public IStorageCacheListener createListener(EntityPlayerMP player) { - return getType() == GridType.FLUID ? new StorageCacheListenerGridFluid(player, network) : new StorageCacheListenerGridItem(player, network); + return getGridType() == GridType.FLUID ? new StorageCacheListenerGridFluid(player, network) : new StorageCacheListenerGridItem(player, network); } @Nullable @Override public IStorageCache getStorageCache() { - return network != null ? (getType() == GridType.FLUID ? network.getFluidStorageCache() : network.getItemStorageCache()) : null; + return network != null ? (getGridType() == GridType.FLUID ? network.getFluidStorageCache() : network.getItemStorageCache()) : null; } @Nullable @@ -245,7 +248,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { @Override public String getGuiTitle() { - GridType type = getType(); + GridType type = getGridType(); switch (type) { case CRAFTING: @@ -292,6 +295,10 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { return matrixProcessing; } + public ItemHandlerFluid getMatrixProcessingFluids() { + return matrixProcessingFluids; + } + @Override public void onCraftingMatrixChanged() { if (currentRecipe == null || !currentRecipe.matches(matrix, world)) { @@ -315,7 +322,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { public static void onRecipeTransfer(IGridNetworkAware grid, EntityPlayer player, ItemStack[][] recipe) { INetwork network = grid.getNetwork(); - if (network != null && grid.getType() == GridType.CRAFTING && !network.getSecurityManager().hasPermission(Permission.EXTRACT, player)) { + if (network != null && grid.getGridType() == GridType.CRAFTING && !network.getSecurityManager().hasPermission(Permission.EXTRACT, player)) { return; } @@ -325,7 +332,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { if (!slot.isEmpty()) { // Only if we are a crafting grid. Pattern grids can just be emptied. - if (grid.getType() == GridType.CRAFTING) { + if (grid.getGridType() == GridType.CRAFTING) { // If we are connected, try to insert into network. If it fails, stop. if (network != null) { if (network.insertItem(slot, slot.getCount(), Action.SIMULATE) != null) { @@ -351,7 +358,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { ItemStack[] possibilities = recipe[i]; // If we are a crafting grid - if (grid.getType() == GridType.CRAFTING) { + if (grid.getGridType() == GridType.CRAFTING) { boolean found = false; // If we are connected, first try to get the possibilities from the network @@ -389,7 +396,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { } } } - } else if (grid.getType() == GridType.PATTERN) { + } else if (grid.getGridType() == GridType.PATTERN) { // If we are a pattern grid we can just set the slot grid.getCraftingMatrix().setInventorySlotContents(i, possibilities.length == 0 ? ItemStack.EMPTY : possibilities[0]); } @@ -402,6 +409,10 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { matrixProcessing.setStackInSlot(i, ItemStack.EMPTY); } + for (int i = 0; i < matrixProcessingFluids.getSlots(); ++i) { + matrixProcessingFluids.setStackInSlot(i, ItemStack.EMPTY); + } + for (int i = 0; i < matrix.getSizeInventory(); ++i) { matrix.setInventorySlotContents(i, ItemStack.EMPTY); } @@ -520,6 +531,20 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { ItemPattern.setInputSlot(pattern, i, matrixProcessing.getStackInSlot(i)); } } + + if (!matrixProcessingFluids.getStackInSlot(i).isEmpty()) { + if (i >= 9) { + FluidStack fluid = StackUtils.getFluid(ItemHandlerHelper.copyStackWithSize(matrixProcessingFluids.getStackInSlot(i), 1), true).getValue(); + if (fluid != null) { + ItemPattern.setFluidOutputSlot(pattern, i - 9, StackUtils.copy(fluid, matrixProcessingFluids.getStackInSlot(i).getCount())); + } + } else { + FluidStack fluid = StackUtils.getFluid(ItemHandlerHelper.copyStackWithSize(matrixProcessingFluids.getStackInSlot(i), 1), true).getValue(); + if (fluid != null) { + ItemPattern.setFluidInputSlot(pattern, i, StackUtils.copy(fluid, matrixProcessingFluids.getStackInSlot(i).getCount())); + } + } + } } } else { for (int i = 0; i < 9; ++i) { @@ -552,12 +577,20 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { if (!matrixProcessing.getStackInSlot(i).isEmpty()) { inputsFilled++; } + + if (!matrixProcessingFluids.getStackInSlot(i).isEmpty()) { + inputsFilled++; + } } for (int i = 9; i < 18; ++i) { if (!matrixProcessing.getStackInSlot(i).isEmpty()) { outputsFilled++; } + + if (!matrixProcessingFluids.getStackInSlot(i).isEmpty()) { + outputsFilled++; + } } return inputsFilled > 0 && outputsFilled > 0; @@ -643,6 +676,23 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { } } + @Override + public int getType() { + return world.isRemote ? TileGrid.PROCESSING_TYPE.getValue() : processingType; + } + + @Override + public void setType(int type) { + this.processingType = type; + + this.markDirty(); + } + + @Override + public IItemHandler getFilterInventory() { + return getType() == IType.FLUIDS ? matrixProcessingFluids : matrixProcessing; + } + @Override public boolean hasConnectivityState() { return true; @@ -656,6 +706,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { StackUtils.readItems(patterns, 1, tag); StackUtils.readItems(filter, 2, tag); StackUtils.readItems(matrixProcessing, 3, tag); + StackUtils.readItems(matrixProcessingFluids, 4, tag, StackUtils::deserializeStackFromNbt); if (tag.hasKey(NBT_TAB_SELECTED)) { tabSelected = tag.getInteger(NBT_TAB_SELECTED); @@ -679,6 +730,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { StackUtils.writeItems(patterns, 1, tag); StackUtils.writeItems(filter, 2, tag); StackUtils.writeItems(matrixProcessing, 3, tag); + StackUtils.writeItems(matrixProcessingFluids, 4, tag, StackUtils::serializeStackToNbt); tag.setInteger(NBT_TAB_SELECTED, tabSelected); tag.setInteger(NBT_TAB_PAGE, tabPage); @@ -698,6 +750,7 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { tag.setBoolean(NBT_OREDICT_PATTERN, oredictPattern); tag.setBoolean(NBT_PROCESSING_PATTERN, processingPattern); + tag.setInteger(NBT_PROCESSING_TYPE, processingType); return tag; } @@ -733,11 +786,15 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware { if (tag.hasKey(NBT_PROCESSING_PATTERN)) { processingPattern = tag.getBoolean(NBT_PROCESSING_PATTERN); } + + if (tag.hasKey(NBT_PROCESSING_TYPE)) { + processingType = tag.getInteger(NBT_PROCESSING_TYPE); + } } @Override public IItemHandler getDrops() { - switch (getType()) { + switch (getGridType()) { case CRAFTING: return new CombinedInvWrapper(filter, new InvWrapper(matrix)); case PATTERN: diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java index c0e6b0acb..ce216f773 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java @@ -115,7 +115,7 @@ public class NetworkNodeImporter extends NetworkNode implements IComparable, IFi FluidStack toDrain = handler.drain(Fluid.BUCKET_VOLUME * upgrades.getItemInteractCount(), false); if (toDrain != null) { - FluidStack remainder = network.insertFluid(toDrain, toDrain.amount, Action.PERFORM); + FluidStack remainder = network.insertFluidTracked(toDrain, toDrain.amount); if (remainder != null) { toDrain.amount -= remainder.amount; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/QuantityFormatter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/QuantityFormatter.java index ff9e20963..4e8f838f5 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/QuantityFormatter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/QuantityFormatter.java @@ -1,6 +1,8 @@ package com.raoulvdberge.refinedstorage.apiimpl.util; import com.raoulvdberge.refinedstorage.api.util.IQuantityFormatter; +import com.raoulvdberge.refinedstorage.apiimpl.API; +import net.minecraftforge.fluids.Fluid; import java.math.RoundingMode; import java.text.DecimalFormat; @@ -10,6 +12,7 @@ import java.util.Locale; public class QuantityFormatter implements IQuantityFormatter { private DecimalFormat formatterWithUnits = new DecimalFormat("####0.#", DecimalFormatSymbols.getInstance(Locale.US)); private DecimalFormat formatter = new DecimalFormat("#,###", DecimalFormatSymbols.getInstance(Locale.US)); + private DecimalFormat bucketFormatter = new DecimalFormat("####0.###", DecimalFormatSymbols.getInstance(Locale.US)); public QuantityFormatter() { formatterWithUnits.setRoundingMode(RoundingMode.DOWN); @@ -42,4 +45,21 @@ public class QuantityFormatter implements IQuantityFormatter { public String format(int qty) { return formatter.format(qty); } + + @Override + public String formatInBucketForm(int qty) { + return bucketFormatter.format((float) qty / (float) Fluid.BUCKET_VOLUME) + " B"; + } + + @Override + public String formatInBucketFormWithOnlyTrailingDigitsIfZero(int qty) { + float amountRaw = ((float) qty / (float) Fluid.BUCKET_VOLUME); + int amount = (int) amountRaw; + + if (amount >= 1) { + return API.instance().getQuantityFormatter().formatWithUnits(amount); + } else { + return String.format("%.1f", amountRaw); + } + } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerBase.java b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerBase.java index 1ed313c5e..cacc6b860 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerBase.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerBase.java @@ -2,15 +2,22 @@ package com.raoulvdberge.refinedstorage.container; import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.container.slot.*; +import com.raoulvdberge.refinedstorage.gui.GuiBase; +import com.raoulvdberge.refinedstorage.gui.GuiFluidAmount; import com.raoulvdberge.refinedstorage.tile.TileBase; +import com.raoulvdberge.refinedstorage.tile.config.IType; import com.raoulvdberge.refinedstorage.tile.data.TileDataWatcher; import invtweaks.api.container.InventoryContainer; +import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.ClickType; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.client.FMLClientHandler; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; @@ -77,21 +84,21 @@ public abstract class ContainerBase extends Container { } if (slot instanceof SlotFilter) { - if (((SlotFilter) slot).allowsSize()) { + if (((SlotFilter) slot).isSizeAllowed()) { if (clickType == ClickType.QUICK_MOVE) { slot.putStack(ItemStack.EMPTY); } else if (!player.inventory.getItemStack().isEmpty()) { - slot.putStack(player.inventory.getItemStack().copy()); + slot.putStack(ItemHandlerHelper.copyStackWithSize(player.inventory.getItemStack(), ((SlotFilter) slot).getInitialAmount(player.inventory.getItemStack()))); } else if (slot.getHasStack()) { - int amount = slot.getStack().getCount(); + if (slot instanceof SlotFilterType && ((SlotFilterType) slot).getType().getType() == IType.FLUIDS) { + if (FMLCommonHandler.instance().getSide() == Side.CLIENT) { + FMLClientHandler.instance().showGuiScreen(new GuiFluidAmount((GuiBase) Minecraft.getMinecraft().currentScreen, player, slot.getSlotIndex(), ((SlotFilterType) slot).getActualStack())); + } + } else { + slot.getStack().setCount(((SlotFilter) slot).getAmountModified(dragType)); - if (dragType == 0) { - amount = Math.max(1, amount - 1); - } else if (dragType == 1) { - amount = Math.min(slot.getStack().getMaxStackSize(), amount + 1); + detectAndSendChanges(); } - - slot.getStack().setCount(amount); } } else if (player.inventory.getItemStack().isEmpty()) { slot.putStack(ItemStack.EMPTY); @@ -149,7 +156,7 @@ public abstract class ContainerBase extends Container { if (slot instanceof SlotFilterFluid) { stackInSlot = ((SlotFilterFluid) slot).getRealStack(); } else if (slot instanceof SlotFilterType) { - stackInSlot = ((SlotFilterType) slot).getRealStack(); + stackInSlot = ((SlotFilterType) slot).getActualStack(); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerCraftingSettings.java b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerCraftingSettings.java index 549e3795b..20db698fb 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerCraftingSettings.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerCraftingSettings.java @@ -1,112 +1,45 @@ package com.raoulvdberge.refinedstorage.container; -import com.raoulvdberge.refinedstorage.container.slot.SlotDisabled; +import com.raoulvdberge.refinedstorage.gui.grid.stack.GridStackFluid; +import com.raoulvdberge.refinedstorage.gui.grid.stack.GridStackItem; +import com.raoulvdberge.refinedstorage.gui.grid.stack.IGridStack; +import com.raoulvdberge.refinedstorage.inventory.ItemHandlerFluid; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; -import net.minecraft.util.text.ITextComponent; +import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; -import javax.annotation.Nullable; +import javax.annotation.Nonnull; public class ContainerCraftingSettings extends ContainerBase { - public ContainerCraftingSettings(EntityPlayer player, final ItemStack stack) { + public ContainerCraftingSettings(EntityPlayer player, IGridStack stack) { super(null, player); - final ItemStack slot = ItemHandlerHelper.copyStackWithSize(stack, 1); + IItemHandler handler = null; - addSlotToContainer(new SlotDisabled(new IInventory() { - @Override - public int getSizeInventory() { - return 1; - } + if (stack instanceof GridStackFluid) { + handler = new ItemHandlerFluid(1, null); - @Override - public boolean isEmpty() { - return true; - } + ((ItemHandlerFluid) handler).setFluidStack(0, ((GridStackFluid) stack).getStack()); + } else if (stack instanceof GridStackItem) { + handler = new ItemStackHandler(1); - @Nullable - @Override - public ItemStack getStackInSlot(int index) { - return slot; - } + ((ItemStackHandler) handler).setStackInSlot(0, ItemHandlerHelper.copyStackWithSize(((GridStackItem) stack).getStack(), 1)); + } - @Nullable + addSlotToContainer(new SlotItemHandler(handler, 0, 89, 48) { @Override - public ItemStack decrStackSize(int index, int count) { - return null; - } - - @Nullable - @Override - public ItemStack removeStackFromSlot(int index) { - return null; - } - - @Override - public void setInventorySlotContents(int index, @Nullable ItemStack stack) { - } - - @Override - public int getInventoryStackLimit() { - return 0; - } - - @Override - public void markDirty() { - } - - @Override - public boolean isUsableByPlayer(EntityPlayer player) { + public boolean isItemValid(@Nonnull ItemStack stack) { return false; } + @Nonnull @Override - public void openInventory(EntityPlayer player) { + public ItemStack getStack() { + return stack instanceof GridStackFluid ? ItemStack.EMPTY : super.getStack(); } - - @Override - public void closeInventory(EntityPlayer player) { - } - - @Override - public boolean isItemValidForSlot(int index, ItemStack stack) { - return false; - } - - @Override - public int getField(int id) { - return 0; - } - - @Override - public void setField(int id, int value) { - } - - @Override - public int getFieldCount() { - return 0; - } - - @Override - public void clear() { - } - - @Override - public String getName() { - return null; - } - - @Override - public boolean hasCustomName() { - return false; - } - - @Override - public ITextComponent getDisplayName() { - return null; - } - }, 0, 89, 48)); + }); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerFluidAmount.java b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerFluidAmount.java new file mode 100644 index 000000000..6d27273fb --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerFluidAmount.java @@ -0,0 +1,32 @@ +package com.raoulvdberge.refinedstorage.container; + +import com.raoulvdberge.refinedstorage.inventory.ItemHandlerFluid; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.SlotItemHandler; + +import javax.annotation.Nonnull; + +public class ContainerFluidAmount extends ContainerBase { + public ContainerFluidAmount(EntityPlayer player, ItemStack fluidContainer) { + super(null, player); + + ItemHandlerFluid handler = new ItemHandlerFluid(1, null); + + handler.setStackInSlot(0, ItemHandlerHelper.copyStackWithSize(fluidContainer, 1)); + + addSlotToContainer(new SlotItemHandler(handler, 0, 89, 48) { + @Override + public boolean isItemValid(@Nonnull ItemStack stack) { + return false; + } + + @Nonnull + @Override + public ItemStack getStack() { + return ItemStack.EMPTY; + } + }); + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerGrid.java index 4d772b411..42582665c 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerGrid.java @@ -49,7 +49,7 @@ public class ContainerGrid extends ContainerBase { int headerAndSlots = getTabDelta() + display.getTopHeight() + (display.getVisibleRows() * 18); - if (grid.getType() != GridType.FLUID) { + if (grid.getGridType() != GridType.FLUID) { int yStart = 6; if (grid instanceof IPortableGrid) { @@ -61,7 +61,7 @@ public class ContainerGrid extends ContainerBase { } } - if (grid.getType() == GridType.PATTERN) { + if (grid.getGridType() == GridType.PATTERN) { addSlotToContainer(new SlotItemHandler(((NetworkNodeGrid) grid).getPatterns(), 0, 172, headerAndSlots + 4)); addSlotToContainer(new SlotItemHandler(((NetworkNodeGrid) grid).getPatterns(), 1, 172, headerAndSlots + 40)); } @@ -72,7 +72,7 @@ public class ContainerGrid extends ContainerBase { addPlayerInventory(8, display.getYPlayerInventory()); - if (grid.getType() == GridType.CRAFTING) { + if (grid.getGridType() == GridType.CRAFTING) { int x = 26; int y = headerAndSlots + 4; @@ -88,14 +88,14 @@ public class ContainerGrid extends ContainerBase { } addSlotToContainer(craftingResultSlot = new SlotGridCraftingResult(this, getPlayer(), grid, 0, 130 + 4, headerAndSlots + 22)); - } else if (grid.getType() == GridType.PATTERN) { + } else if (grid.getGridType() == GridType.PATTERN) { if (((NetworkNodeGrid) grid).isProcessingPattern()) { int ox = 8; int x = ox; int y = headerAndSlots + 4; for (int i = 0; i < 9 * 2; ++i) { - addSlotToContainer(new SlotFilter(((NetworkNodeGrid) grid).getProcessingMatrix(), i, x, y, SlotFilter.FILTER_ALLOW_SIZE)); + addSlotToContainer(new SlotFilterType((NetworkNodeGrid) grid, i, x, y, SlotFilter.FILTER_ALLOW_SIZE)); x += 18; @@ -210,7 +210,7 @@ public class ContainerGrid extends ContainerBase { if (slot.getHasStack()) { if (grid instanceof IPortableGrid && slot.slotNumber == 4) { // Prevent moving disk slot into portable grid itself return ItemStack.EMPTY; - } else if (grid.getType() == GridType.PATTERN && slot.slotNumber == 5) { // From output slot to inventory + } else if (grid.getGridType() == GridType.PATTERN && slot.slotNumber == 5) { // From output slot to inventory ItemStack stack = slot.getStack(); int startIndex = 5; @@ -231,7 +231,7 @@ public class ContainerGrid extends ContainerBase { } else if (slot != patternResultSlot && !(slot instanceof SlotFilterLegacy)) { ItemStack stack = slot.getStack(); - if (grid.getType() != GridType.FLUID && stack.getItem() == RSItems.FILTER) { + if (grid.getGridType() != GridType.FLUID && stack.getItem() == RSItems.FILTER) { int startIndex = 0; int endIndex = 4; @@ -239,7 +239,7 @@ public class ContainerGrid extends ContainerBase { if (slotIndex < 4) { startIndex = 4; - if (grid.getType() == GridType.PATTERN) { + if (grid.getGridType() == GridType.PATTERN) { startIndex += 2; // Skip the pattern slots } @@ -258,7 +258,7 @@ public class ContainerGrid extends ContainerBase { return ItemStack.EMPTY; } - } else if ((grid.getType() == GridType.PATTERN && stack.getItem() == RSItems.PATTERN) || (grid instanceof IPortableGrid && stack.getItem() instanceof IStorageDiskFactory)) { + } else if ((grid.getGridType() == GridType.PATTERN && stack.getItem() == RSItems.PATTERN) || (grid instanceof IPortableGrid && stack.getItem() instanceof IStorageDiskFactory)) { int startIndex = 4; int endIndex = startIndex + 1; @@ -287,7 +287,7 @@ public class ContainerGrid extends ContainerBase { } } - if (grid.getType() == GridType.FLUID) { + if (grid.getGridType() == GridType.FLUID) { IFluidGridHandler fluidHandler = grid.getFluidHandler(); if (fluidHandler != null) { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/container/slot/SlotFilter.java b/src/main/java/com/raoulvdberge/refinedstorage/container/slot/SlotFilter.java index 89ccda0a7..4ce915d7b 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/container/slot/SlotFilter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/container/slot/SlotFilter.java @@ -31,7 +31,7 @@ public class SlotFilter extends SlotItemHandler { @Override public boolean isItemValid(@Nonnull ItemStack stack) { if (super.isItemValid(stack)) { - if (allowsBlocks()) { + if (isBlockAllowed()) { return stack.getItem() instanceof ItemBlock || stack.getItem() instanceof ItemBlockSpecial || stack.getItem() instanceof IPlantable || stack.getItem() instanceof ItemSkull; } @@ -43,21 +43,37 @@ public class SlotFilter extends SlotItemHandler { @Override public void putStack(@Nonnull ItemStack stack) { - if (!stack.isEmpty() && !allowsSize()) { + if (!stack.isEmpty() && !isSizeAllowed()) { stack.setCount(1); } super.putStack(stack); } - public boolean allowsSize() { + public boolean isSizeAllowed() { return (flags & FILTER_ALLOW_SIZE) == FILTER_ALLOW_SIZE; } - public boolean allowsBlocks() { + public boolean isBlockAllowed() { return (flags & FILTER_ALLOW_BLOCKS) == FILTER_ALLOW_BLOCKS; } + public int getAmountModified(int dragType) { + int amount = getStack().getCount(); + + if (dragType == 0) { + amount = Math.max(1, amount - 1); + } else if (dragType == 1) { + amount = Math.min(getStack().getMaxStackSize(), amount + 1); + } + + return amount; + } + + public int getInitialAmount(ItemStack stack) { + return stack.getCount(); + } + @Nullable public static IBlockState getBlockState(IBlockAccess world, BlockPos pos, @Nullable ItemStack stack) { if (stack != null) { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/container/slot/SlotFilterType.java b/src/main/java/com/raoulvdberge/refinedstorage/container/slot/SlotFilterType.java index 70a212ab3..0eec0957d 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/container/slot/SlotFilterType.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/container/slot/SlotFilterType.java @@ -3,6 +3,7 @@ package com.raoulvdberge.refinedstorage.container.slot; import com.raoulvdberge.refinedstorage.apiimpl.network.node.NetworkNode; import com.raoulvdberge.refinedstorage.tile.config.IType; import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.items.IItemHandler; import javax.annotation.Nonnull; @@ -26,13 +27,8 @@ public class SlotFilterType extends SlotFilter { } @Override - public boolean allowsSize() { - return super.allowsSize() && type.getType() != IType.FLUIDS; - } - - @Override - public boolean allowsBlocks() { - return super.allowsBlocks() && type.getType() == IType.ITEMS; + public boolean isBlockAllowed() { + return super.isBlockAllowed() && type.getType() == IType.ITEMS; } @Override @@ -41,7 +37,20 @@ public class SlotFilterType extends SlotFilter { return (type.getType() == IType.ITEMS || !((NetworkNode) type).getWorld().isRemote) ? super.getStack() : ItemStack.EMPTY; } - public ItemStack getRealStack() { + public ItemStack getActualStack() { return super.getStack(); } + + public IType getType() { + return type; + } + + @Override + public int getInitialAmount(ItemStack stack) { + if (type.getType() == IType.FLUIDS && isSizeAllowed()) { + return Fluid.BUCKET_VOLUME; + } + + return super.getInitialAmount(stack); + } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiBase.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiBase.java index e29e5d62c..8c53a1b16 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiBase.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiBase.java @@ -3,6 +3,7 @@ package com.raoulvdberge.refinedstorage.gui; import com.raoulvdberge.refinedstorage.RS; import com.raoulvdberge.refinedstorage.api.render.IElementDrawer; import com.raoulvdberge.refinedstorage.api.render.IElementDrawers; +import com.raoulvdberge.refinedstorage.container.slot.SlotFilterType; import com.raoulvdberge.refinedstorage.gui.control.Scrollbar; import com.raoulvdberge.refinedstorage.gui.control.SideButton; import com.raoulvdberge.refinedstorage.integration.jei.IntegrationJEI; @@ -24,6 +25,7 @@ import net.minecraftforge.fml.client.config.GuiUtils; import net.minecraftforge.items.SlotItemHandler; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -187,6 +189,16 @@ public abstract class GuiBase extends GuiContainer { if (stack != null) { FLUID_RENDERER.draw(mc, guiLeft + slot.xPos, guiTop + slot.yPos, stack); + if (slot instanceof SlotFilterType) { + int count = ((SlotFilterType) slot).getActualStack().getCount(); + + if (count != 1) { + drawQuantity(guiLeft + slot.xPos, guiTop + slot.yPos, String.valueOf(count)); + + GL11.glDisable(GL11.GL_LIGHTING); + } + } + if (inBounds(guiLeft + slot.xPos, guiTop + slot.yPos, 18, 18, mouseX, mouseY)) { this.hoveringFluid = stack.getLocalizedName(); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingMonitor.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingMonitor.java index 700c3e130..d5233098f 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingMonitor.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingMonitor.java @@ -4,11 +4,13 @@ import com.google.common.base.Optional; import com.google.common.collect.Lists; import com.raoulvdberge.refinedstorage.RS; import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.raoulvdberge.refinedstorage.api.network.grid.IGrid; import com.raoulvdberge.refinedstorage.api.network.grid.IGridTab; import com.raoulvdberge.refinedstorage.api.render.IElementDrawer; import com.raoulvdberge.refinedstorage.api.render.IElementDrawers; import com.raoulvdberge.refinedstorage.api.util.IFilter; +import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.container.ContainerCraftingMonitor; import com.raoulvdberge.refinedstorage.gui.control.Scrollbar; import com.raoulvdberge.refinedstorage.gui.control.SideButtonGridSize; @@ -23,6 +25,7 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; import javax.annotation.Nullable; import java.io.IOException; @@ -46,12 +49,12 @@ public class GuiCraftingMonitor extends GuiBase implements IResizableDisplay { public static class CraftingMonitorTask implements IGridTab { private UUID id; - private ItemStack requested; + private ICraftingRequestInfo requested; private int qty; private long executionStarted; private List elements; - public CraftingMonitorTask(UUID id, ItemStack requested, int qty, long executionStarted, List elements) { + public CraftingMonitorTask(UUID id, ICraftingRequestInfo requested, int qty, long executionStarted, List elements) { this.id = id; this.requested = requested; this.qty = qty; @@ -66,22 +69,26 @@ public class GuiCraftingMonitor extends GuiBase implements IResizableDisplay { @Override public void drawTooltip(int x, int y, int screenWidth, int screenHeight, FontRenderer fontRenderer) { - List textLines = Lists.newArrayList(requested.getDisplayName()); + List textLines = Lists.newArrayList(requested.getItem() != null ? requested.getItem().getDisplayName() : requested.getFluid().getLocalizedName()); List smallTextLines = Lists.newArrayList(); int totalSecs = (int) (System.currentTimeMillis() - executionStarted) / 1000; int minutes = (totalSecs % 3600) / 60; int seconds = totalSecs % 60; - smallTextLines.add(I18n.format("gui.refinedstorage:crafting_monitor.tooltip.requested", qty)); + smallTextLines.add(I18n.format("gui.refinedstorage:crafting_monitor.tooltip.requested", requested.getFluid() != null ? API.instance().getQuantityFormatter().formatInBucketForm(qty) : API.instance().getQuantityFormatter().format(qty))); smallTextLines.add(String.format("%02d:%02d", minutes, seconds)); RenderUtils.drawTooltipWithSmallText(textLines, smallTextLines, true, ItemStack.EMPTY, x, y, screenWidth, screenHeight, fontRenderer); } @Override - public ItemStack getIcon() { - return requested; + public void drawIcon(int x, int y, IElementDrawer itemDrawer, IElementDrawer fluidDrawer) { + if (requested.getItem() != null) { + itemDrawer.draw(x, y, requested.getItem()); + } else { + fluidDrawer.draw(x, y, requested.getFluid()); + } } } @@ -105,7 +112,7 @@ public class GuiCraftingMonitor extends GuiBase implements IResizableDisplay { this.craftingMonitor = craftingMonitor; - this.tabs = new TabList(this, () -> tasks, () -> (int) Math.floor((float) Math.max(0, tasks.size() - 1) / (float) ICraftingMonitor.TABS_PER_PAGE), craftingMonitor::getTabPage, () -> { + this.tabs = new TabList(this, new ElementDrawers(), () -> tasks, () -> (int) Math.floor((float) Math.max(0, tasks.size() - 1) / (float) ICraftingMonitor.TABS_PER_PAGE), craftingMonitor::getTabPage, () -> { IGridTab tab = getCurrentTab(); if (tab == null) { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingPreview.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingPreview.java index 3fa64c7af..1791f9298 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingPreview.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiCraftingPreview.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +// TODO: Make bigger/resizeable and allow more space? public class GuiCraftingPreview extends GuiBase { public class CraftingPreviewElementDrawers extends ElementDrawers { private IElementDrawer overlayDrawer = (x, y, colour) -> { @@ -61,7 +62,9 @@ public class GuiCraftingPreview extends GuiBase { private IElementDrawers drawers = new CraftingPreviewElementDrawers(); - public GuiCraftingPreview(GuiScreen parent, List stacks, int hash, int quantity) { + private boolean fluids; + + public GuiCraftingPreview(GuiScreen parent, List stacks, int hash, int quantity, boolean fluids) { super(new Container() { @Override public boolean canInteractWith(EntityPlayer player) { @@ -74,6 +77,7 @@ public class GuiCraftingPreview extends GuiBase { this.hash = hash; this.quantity = quantity; + this.fluids = fluids; this.scrollbar = new Scrollbar(149, 20, 12, 119); } @@ -247,7 +251,7 @@ public class GuiCraftingPreview extends GuiBase { } private void startRequest() { - RS.INSTANCE.network.sendToServer(new MessageGridCraftingStart(hash, quantity)); + RS.INSTANCE.network.sendToServer(new MessageGridCraftingStart(hash, quantity, fluids)); close(); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiFluidAmount.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiFluidAmount.java new file mode 100644 index 000000000..524ebfa27 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/GuiFluidAmount.java @@ -0,0 +1,66 @@ +package com.raoulvdberge.refinedstorage.gui; + +import com.google.common.primitives.Ints; +import com.raoulvdberge.refinedstorage.RS; +import com.raoulvdberge.refinedstorage.container.ContainerFluidAmount; +import com.raoulvdberge.refinedstorage.gui.grid.GuiCraftingStart; +import com.raoulvdberge.refinedstorage.network.MessageGridFluidAmount; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.Fluid; + +public class GuiFluidAmount extends GuiCraftingStart { + private int slot; + private ItemStack fluidContainer; + + public GuiFluidAmount(GuiBase parent, EntityPlayer player, int slot, ItemStack fluidContainer) { + super(parent, null, new ContainerFluidAmount(player, fluidContainer), 172, 99); + + this.slot = slot; + this.fluidContainer = fluidContainer; + } + + @Override + protected int getAmount() { + return fluidContainer.getCount(); + } + + @Override + protected String getStartButtonText() { + return t("misc.refinedstorage:set"); + } + + @Override + protected String getTitle() { + return t("gui.refinedstorage:pattern_grid.fluid_amount"); + } + + @Override + protected boolean canAmountGoNegative() { + return false; + } + + @Override + protected int[] getIncrements() { + return new int[]{ + 10, 50, 100, + -10, -50, -100 + }; + } + + @Override + protected int getMaxAmount() { + return Fluid.BUCKET_VOLUME; + } + + @Override + protected void startRequest(boolean noPreview) { + Integer amount = Ints.tryParse(amountField.getText()); + + if (amount != null && amount > 0 && amount <= Fluid.BUCKET_VOLUME) { + RS.INSTANCE.network.sendToServer(new MessageGridFluidAmount(slot, amount)); + + close(); + } + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/control/SideButtonGridSortingType.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/control/SideButtonGridSortingType.java index d266309b0..ab176cf58 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/control/SideButtonGridSortingType.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/control/SideButtonGridSortingType.java @@ -38,7 +38,7 @@ public class SideButtonGridSortingType extends SideButton { if (type == IGrid.SORTING_TYPE_QUANTITY) { type = IGrid.SORTING_TYPE_NAME; } else if (type == IGrid.SORTING_TYPE_NAME) { - if (grid.getType() == GridType.FLUID) { + if (grid.getGridType() == GridType.FLUID) { type = IGrid.SORTING_TYPE_LAST_MODIFIED; } else { type = IGrid.SORTING_TYPE_ID; @@ -46,7 +46,7 @@ public class SideButtonGridSortingType extends SideButton { } else if (type == IGrid.SORTING_TYPE_ID) { type = IGrid.SORTING_TYPE_LAST_MODIFIED; } else if (type == NetworkNodeGrid.SORTING_TYPE_LAST_MODIFIED) { - if (grid.getType() == GridType.FLUID || !Loader.isModLoaded(GridSorterInventoryTweaks.MOD_ID)) { + if (grid.getGridType() == GridType.FLUID || !Loader.isModLoaded(GridSorterInventoryTweaks.MOD_ID)) { type = IGrid.SORTING_TYPE_QUANTITY; } else { type = IGrid.SORTING_TYPE_INVENTORYTWEAKS; diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/control/TabList.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/control/TabList.java index 08fa6884a..846cc8903 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/control/TabList.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/control/TabList.java @@ -4,7 +4,6 @@ import com.raoulvdberge.refinedstorage.api.network.grid.IGridTab; import com.raoulvdberge.refinedstorage.gui.GuiBase; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.renderer.RenderHelper; import java.util.LinkedList; import java.util.List; @@ -18,6 +17,7 @@ public class TabList { } private GuiBase gui; + private GuiBase.ElementDrawers drawers; private Supplier> tabs; private int tabHovering; @@ -34,8 +34,9 @@ public class TabList { private int width; - public TabList(GuiBase gui, Supplier> tabs, Supplier pages, Supplier page, Supplier selected, int tabsPerPage) { + public TabList(GuiBase gui, GuiBase.ElementDrawers drawers, Supplier> tabs, Supplier pages, Supplier page, Supplier selected, int tabsPerPage) { this.gui = gui; + this.drawers = drawers; this.tabs = tabs; this.pages = pages; this.page = page; @@ -138,9 +139,7 @@ public class TabList { gui.drawTexture(tx, ty, uvx, uvy, tbw, IGridTab.TAB_HEIGHT); - RenderHelper.enableGUIStandardItemLighting(); - - gui.drawItem(otx + 6, ty + 9 - (!isSelected ? 3 : 0), tab.getIcon()); + tab.drawIcon(otx + 6, ty + 9 - (!isSelected ? 3 : 0), drawers.getItemDrawer(), drawers.getFluidDrawer()); } public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY) { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiCraftingStart.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiCraftingStart.java index e7accc9e7..00eba4e75 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiCraftingStart.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiCraftingStart.java @@ -4,7 +4,8 @@ import com.google.common.primitives.Ints; import com.raoulvdberge.refinedstorage.RS; import com.raoulvdberge.refinedstorage.container.ContainerCraftingSettings; import com.raoulvdberge.refinedstorage.gui.GuiBase; -import com.raoulvdberge.refinedstorage.gui.grid.stack.GridStackItem; +import com.raoulvdberge.refinedstorage.gui.grid.stack.GridStackFluid; +import com.raoulvdberge.refinedstorage.gui.grid.stack.IGridStack; import com.raoulvdberge.refinedstorage.network.MessageGridCraftingPreview; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiTextField; @@ -16,25 +17,27 @@ import org.lwjgl.input.Keyboard; import java.io.IOException; +// TODO: Change quantities for fluid craft. +// TODO: Cleanup childclasses. public class GuiCraftingStart extends GuiBase { private static final int DEFAULT_AMOUNT = 1; protected GuiTextField amountField; private GuiBase parent; - private GridStackItem stack; + private IGridStack stack; private GuiButton startButton; private GuiButton cancelButton; private GuiButton[] incrementButtons = new GuiButton[6]; - public GuiCraftingStart(GuiBase parent, GridStackItem stack, Container container, int w, int h) { + public GuiCraftingStart(GuiBase parent, IGridStack stack, Container container, int w, int h) { super(container, w, h); this.parent = parent; this.stack = stack; } - public GuiCraftingStart(GuiGrid parent, EntityPlayer player, GridStackItem stack) { - this(parent, stack, new ContainerCraftingSettings(player, stack.getStack()), 172, 99); + public GuiCraftingStart(GuiGrid parent, EntityPlayer player, IGridStack stack) { + this(parent, stack, new ContainerCraftingSettings(player, stack), 172, 99); } protected String getStartButtonText() { @@ -50,14 +53,21 @@ public class GuiCraftingStart extends GuiBase { } protected int[] getIncrements() { - return new int[]{ - 1, 10, 64, - -1, -10, -64 - }; + if (stack instanceof GridStackFluid) { + return new int[]{ + 1, 500, 1000, + -1, -500, -1000 + }; + } else { + return new int[]{ + 1, 10, 64, + -1, -10, -64 + }; + } } protected int getAmount() { - return DEFAULT_AMOUNT; + return stack instanceof GridStackFluid ? 1000 : DEFAULT_AMOUNT; } protected Tuple getAmountPos() { @@ -164,6 +174,10 @@ public class GuiCraftingStart extends GuiBase { newAmount = oldAmount + newAmount; } + if (newAmount > getMaxAmount()) { + newAmount = getMaxAmount(); + } + amountField.setText(String.valueOf(newAmount)); break; @@ -172,11 +186,15 @@ public class GuiCraftingStart extends GuiBase { } } + protected int getMaxAmount() { + return Integer.MAX_VALUE; + } + protected void startRequest(boolean noPreview) { Integer quantity = Ints.tryParse(amountField.getText()); if (quantity != null && quantity > 0) { - RS.INSTANCE.network.sendToServer(new MessageGridCraftingPreview(stack.getHash(), quantity, noPreview)); + RS.INSTANCE.network.sendToServer(new MessageGridCraftingPreview(stack.getHash(), quantity, noPreview, stack instanceof GridStackFluid)); startButton.enabled = false; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiGrid.java index 2a004c47c..2ab3868f9 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiGrid.java @@ -55,7 +55,7 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { private int slotNumber; public GuiGrid(ContainerGrid container, IGrid grid) { - super(container, grid.getType() == GridType.FLUID ? 193 : 227, 0); + super(container, grid.getGridType() == GridType.FLUID ? 193 : 227, 0); IGridSorter defaultSorter; @@ -67,9 +67,9 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { sorters.add(new GridSorterLastModified()); this.grid = grid; - this.view = grid.getType() == GridType.FLUID ? new GridViewFluid(this, defaultSorter, sorters) : new GridViewItem(this, defaultSorter, sorters); + this.view = grid.getGridType() == GridType.FLUID ? new GridViewFluid(this, defaultSorter, sorters) : new GridViewItem(this, defaultSorter, sorters); this.wasConnected = this.grid.isActive(); - this.tabs = new TabList(this, grid::getTabs, grid::getTotalTabPages, grid::getTabPage, grid::getTabSelected, IGrid.TABS_PER_PAGE); + this.tabs = new TabList(this, new ElementDrawers(), grid::getTabs, grid::getTotalTabPages, grid::getTabPage, grid::getTabSelected, IGrid.TABS_PER_PAGE); this.tabs.addListener(new TabList.ITabListListener() { @Override public void onSelectionChanged(int tab) { @@ -113,12 +113,7 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { searchField.y = sy; } - if (grid.getType() == GridType.PATTERN) { - processingPattern = addCheckBox(x + 7, y + tabs.getHeight() + getTopHeight() + (getVisibleRows() * 18) + 60, t("misc.refinedstorage:processing"), TileGrid.PROCESSING_PATTERN.getValue()); - oredictPattern = addCheckBox(processingPattern.x + processingPattern.width + 5, y + tabs.getHeight() + getTopHeight() + (getVisibleRows() * 18) + 60, t("misc.refinedstorage:oredict"), TileGrid.OREDICT_PATTERN.getValue()); - } - - if (grid.getType() != GridType.FLUID && grid.getViewType() != -1) { + if (grid.getGridType() != GridType.FLUID && grid.getViewType() != -1) { addSideButton(new SideButtonGridViewType(this, grid)); } @@ -127,6 +122,13 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { addSideButton(new SideButtonGridSearchBoxMode(this)); addSideButton(new SideButtonGridSize(this, () -> grid.getSize(), size -> grid.onSizeChanged(size))); + if (grid.getGridType() == GridType.PATTERN) { + processingPattern = addCheckBox(x + 7, y + tabs.getHeight() + getTopHeight() + (getVisibleRows() * 18) + 60, t("misc.refinedstorage:processing"), TileGrid.PROCESSING_PATTERN.getValue()); + oredictPattern = addCheckBox(processingPattern.x + processingPattern.width + 5, y + tabs.getHeight() + getTopHeight() + (getVisibleRows() * 18) + 60, t("misc.refinedstorage:oredict"), TileGrid.OREDICT_PATTERN.getValue()); + + addSideButton(new SideButtonType(this, TileGrid.PROCESSING_TYPE)); + } + updateScrollbar(); } @@ -161,9 +163,9 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { @Override public int getBottomHeight() { - if (grid.getType() == GridType.CRAFTING) { + if (grid.getGridType() == GridType.CRAFTING) { return 156; - } else if (grid.getType() == GridType.PATTERN) { + } else if (grid.getGridType() == GridType.PATTERN) { return 169; } else { return 99; @@ -174,11 +176,11 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { public int getYPlayerInventory() { int yp = tabs.getHeight() + getTopHeight() + (getVisibleRows() * 18); - if (grid.getType() == GridType.NORMAL || grid.getType() == GridType.FLUID) { + if (grid.getGridType() == GridType.NORMAL || grid.getGridType() == GridType.FLUID) { yp += 16; - } else if (grid.getType() == GridType.CRAFTING) { + } else if (grid.getGridType() == GridType.CRAFTING) { yp += 73; - } else if (grid.getType() == GridType.PATTERN) { + } else if (grid.getGridType() == GridType.PATTERN) { yp += 86; } @@ -237,7 +239,7 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { private boolean isOverClear(int mouseX, int mouseY) { int y = tabs.getHeight() + getTopHeight() + (getVisibleRows() * 18) + 4; - switch (grid.getType()) { + switch (grid.getGridType()) { case CRAFTING: return inBounds(82, y, 7, 7, mouseX, mouseY); case PATTERN: @@ -252,16 +254,16 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { } private boolean isOverCreatePattern(int mouseX, int mouseY) { - return grid.getType() == GridType.PATTERN && inBounds(172, tabs.getHeight() + getTopHeight() + (getVisibleRows() * 18) + 22, 16, 16, mouseX, mouseY) && ((NetworkNodeGrid) grid).canCreatePattern(); + return grid.getGridType() == GridType.PATTERN && inBounds(172, tabs.getHeight() + getTopHeight() + (getVisibleRows() * 18) + 22, 16, 16, mouseX, mouseY) && ((NetworkNodeGrid) grid).canCreatePattern(); } @Override public void drawBackground(int x, int y, int mouseX, int mouseY) { tabs.drawBackground(x, y); - if (grid.getType() == GridType.CRAFTING) { + if (grid.getGridType() == GridType.CRAFTING) { bindTexture("gui/crafting_grid.png"); - } else if (grid.getType() == GridType.PATTERN) { + } else if (grid.getGridType() == GridType.PATTERN) { bindTexture("gui/pattern_grid" + (((NetworkNodeGrid) grid).isProcessingPattern() ? "_processing" : "") + ".png"); } else if (grid instanceof IPortableGrid) { bindTexture("gui/portable_grid.png"); @@ -271,9 +273,9 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { int yy = y + tabs.getHeight(); - drawTexture(x, yy, 0, 0, screenWidth - (grid.getType() != GridType.FLUID ? 34 : 0), getTopHeight()); + drawTexture(x, yy, 0, 0, screenWidth - (grid.getGridType() != GridType.FLUID ? 34 : 0), getTopHeight()); - if (grid.getType() != GridType.FLUID) { + if (grid.getGridType() != GridType.FLUID) { drawTexture(x + screenWidth - 34 + 4, y + tabs.getHeight(), 197, 0, 30, grid instanceof IPortableGrid ? 114 : 82); } @@ -282,14 +284,14 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { for (int i = 0; i < rows; ++i) { yy += 18; - drawTexture(x, yy, 0, getTopHeight() + (i > 0 ? (i == rows - 1 ? 18 * 2 : 18) : 0), screenWidth - (grid.getType() != GridType.FLUID ? 34 : 0), 18); + drawTexture(x, yy, 0, getTopHeight() + (i > 0 ? (i == rows - 1 ? 18 * 2 : 18) : 0), screenWidth - (grid.getGridType() != GridType.FLUID ? 34 : 0), 18); } yy += 18; - drawTexture(x, yy, 0, getTopHeight() + (18 * 3), screenWidth - (grid.getType() != GridType.FLUID ? 34 : 0), getBottomHeight()); + drawTexture(x, yy, 0, getTopHeight() + (18 * 3), screenWidth - (grid.getGridType() != GridType.FLUID ? 34 : 0), getBottomHeight()); - if (grid.getType() == GridType.PATTERN) { + if (grid.getGridType() == GridType.PATTERN) { int ty = 0; if (isOverCreatePattern(mouseX - guiLeft, mouseY - guiTop)) { @@ -383,7 +385,7 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { List textLines = Lists.newArrayList(gridStack.getTooltip().split("\n")); List smallTextLines = Lists.newArrayList(); - if (!(gridStack instanceof GridStackItem) || !((GridStackItem) gridStack).doesDisplayCraftText()) { + if (!gridStack.doesDisplayCraftText()) { smallTextLines.add(I18n.format("misc.refinedstorage:total", gridStack.getFormattedFullQuantity())); } @@ -439,16 +441,21 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { ItemStack held = ((ContainerGrid) this.inventorySlots).getPlayer().inventory.getItemStack(); if (isOverSlotArea(mouseX - guiLeft, mouseY - guiTop) && !held.isEmpty() && (clickedButton == 0 || clickedButton == 1)) { - RS.INSTANCE.network.sendToServer(grid.getType() == GridType.FLUID ? new MessageGridFluidInsertHeld() : new MessageGridItemInsertHeld(clickedButton == 1)); + RS.INSTANCE.network.sendToServer(grid.getGridType() == GridType.FLUID ? new MessageGridFluidInsertHeld() : new MessageGridItemInsertHeld(clickedButton == 1)); } if (isOverSlotWithStack()) { - if (grid.getType() != GridType.FLUID && (held.isEmpty() || (!held.isEmpty() && clickedButton == 2))) { - GridStackItem stack = (GridStackItem) view.getStacks().get(slotNumber); + boolean isMiddleClickPulling = !held.isEmpty() && clickedButton == 2; + boolean isPulling = held.isEmpty() || isMiddleClickPulling; - if (stack.isCraftable() && (stack.doesDisplayCraftText() || (GuiScreen.isShiftKeyDown() && GuiScreen.isCtrlKeyDown())) && view.canCraft()) { + IGridStack stack = view.getStacks().get(slotNumber); + + if (isPulling) { + if (stack.isCraftable() && view.canCraft() && (stack.doesDisplayCraftText() || (GuiScreen.isShiftKeyDown() && GuiScreen.isCtrlKeyDown()))) { FMLCommonHandler.instance().showGuiScreen(new GuiCraftingStart(this, ((ContainerGrid) this.inventorySlots).getPlayer(), stack)); - } else { + } else if (grid.getGridType() == GridType.FLUID && held.isEmpty()) { + RS.INSTANCE.network.sendToServer(new MessageGridFluidPull(view.getStacks().get(slotNumber).getHash(), GuiScreen.isShiftKeyDown())); + } else if (grid.getGridType() == GridType.NORMAL || grid.getGridType() == GridType.PATTERN) { int flags = 0; if (clickedButton == 1) { @@ -465,8 +472,6 @@ public class GuiGrid extends GuiBase implements IResizableDisplay { RS.INSTANCE.network.sendToServer(new MessageGridItemPull(stack.getHash(), flags)); } - } else if (grid.getType() == GridType.FLUID && held.isEmpty()) { - RS.INSTANCE.network.sendToServer(new MessageGridFluidPull(view.getStacks().get(slotNumber).getHash(), GuiScreen.isShiftKeyDown())); } } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/GridStackFluid.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/GridStackFluid.java index 9d6b38127..cfa46d74e 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/GridStackFluid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/GridStackFluid.java @@ -3,6 +3,7 @@ package com.raoulvdberge.refinedstorage.gui.grid.stack; import com.raoulvdberge.refinedstorage.api.storage.IStorageTracker; import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.gui.GuiBase; +import net.minecraft.client.resources.I18n; import net.minecraftforge.fluids.FluidStack; import org.apache.commons.lang3.tuple.Pair; @@ -13,17 +14,36 @@ public class GridStackFluid implements IGridStack { private FluidStack stack; @Nullable private IStorageTracker.IStorageTrackerEntry entry; + private boolean craftable; + private boolean displayCraftText; - public GridStackFluid(Pair data, @Nullable IStorageTracker.IStorageTrackerEntry entry) { + public GridStackFluid(Pair data, @Nullable IStorageTracker.IStorageTrackerEntry entry, boolean craftable, boolean displayCraftText) { this.hash = data.getLeft(); this.stack = data.getRight(); this.entry = entry; + this.craftable = craftable; + this.displayCraftText = displayCraftText; } public FluidStack getStack() { return stack; } + @Override + public boolean isCraftable() { + return craftable; + } + + @Override + public boolean doesDisplayCraftText() { + return displayCraftText; + } + + @Override + public void setDisplayCraftText(boolean displayCraftText) { + this.displayCraftText = displayCraftText; + } + @Override public int getHash() { return hash; @@ -63,11 +83,15 @@ public class GridStackFluid implements IGridStack { public void draw(GuiBase gui, int x, int y) { GuiBase.FLUID_RENDERER.draw(gui.mc, x, y, stack); - float amountRaw = ((float) stack.amount / 1000F); - int amount = (int) amountRaw; - String formattedAmount = amount >= 1 ? API.instance().getQuantityFormatter().formatWithUnits(amount) : String.format("%.1f", amountRaw); + String text; - gui.drawQuantity(x, y, formattedAmount); + if (displayCraftText) { + text = I18n.format("gui.refinedstorage:grid.craft"); + } else { + text = API.instance().getQuantityFormatter().formatInBucketFormWithOnlyTrailingDigitsIfZero(getQuantity()); + } + + gui.drawQuantity(x, y, text); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/GridStackItem.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/GridStackItem.java index 9a7d3f1f3..1a1875dee 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/GridStackItem.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/GridStackItem.java @@ -45,14 +45,17 @@ public class GridStackItem implements IGridStack { return stack; } + @Override public boolean isCraftable() { return craftable; } + @Override public boolean doesDisplayCraftText() { return displayCraftText; } + @Override public void setDisplayCraftText(boolean displayCraftText) { this.displayCraftText = displayCraftText; diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/IGridStack.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/IGridStack.java index 978a7ba67..7abecaf25 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/IGridStack.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/stack/IGridStack.java @@ -28,4 +28,10 @@ public interface IGridStack { IStorageTracker.IStorageTrackerEntry getTrackerEntry(); void setTrackerEntry(@Nullable IStorageTracker.IStorageTrackerEntry entry); + + boolean isCraftable(); + + boolean doesDisplayCraftText(); + + void setDisplayCraftText(boolean displayCraftText); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/view/GridViewFluid.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/view/GridViewFluid.java index 05564001f..2d694056e 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/view/GridViewFluid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/view/GridViewFluid.java @@ -17,6 +17,11 @@ public class GridViewFluid extends GridViewBase { map.clear(); for (IGridStack stack : stacks) { + // Don't let a craftable stack override a normal stack + if (stack.doesDisplayCraftText() && map.containsKey(stack.getHash())) { + continue; + } + map.put(stack.getHash(), stack); } } @@ -30,12 +35,24 @@ public class GridViewFluid extends GridViewBase { GridStackFluid existing = (GridStackFluid) map.get(stack.getHash()); if (existing == null) { + ((GridStackFluid) stack).getStack().amount = delta; + map.put(stack.getHash(), stack); } else { if (existing.getStack().amount + delta <= 0) { - map.remove(existing.getHash()); + if (existing.isCraftable()) { + existing.setDisplayCraftText(true); + } else { + map.remove(existing.getHash()); + } } else { - existing.getStack().amount += delta; + if (existing.doesDisplayCraftText()) { + existing.setDisplayCraftText(false); + + existing.getStack().amount = delta; + } else { + existing.getStack().amount += delta; + } } existing.setTrackerEntry(stack.getTrackerEntry()); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/view/GridViewItem.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/view/GridViewItem.java index 8e8592e9c..6e55d5b34 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/view/GridViewItem.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/view/GridViewItem.java @@ -18,7 +18,7 @@ public class GridViewItem extends GridViewBase { for (IGridStack stack : stacks) { // Don't let a craftable stack override a normal stack - if (((GridStackItem) stack).doesDisplayCraftText() && map.containsKey(stack.getHash())) { + if (stack.doesDisplayCraftText() && map.containsKey(stack.getHash())) { continue; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/integration/craftingtweaks/IntegrationCraftingTweaks.java b/src/main/java/com/raoulvdberge/refinedstorage/integration/craftingtweaks/IntegrationCraftingTweaks.java index 948465ab4..bac433553 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/integration/craftingtweaks/IntegrationCraftingTweaks.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/integration/craftingtweaks/IntegrationCraftingTweaks.java @@ -30,7 +30,7 @@ public final class IntegrationCraftingTweaks { public static class ValidContainerPredicate implements Predicate { @Override public boolean apply(ContainerGrid containerGrid) { - return containerGrid.getGrid().getType() == GridType.CRAFTING; + return containerGrid.getGrid().getGridType() == GridType.CRAFTING; } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/integration/jei/RecipeTransferHandlerGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/integration/jei/RecipeTransferHandlerGrid.java index 64adcb95a..12dd69fed 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/integration/jei/RecipeTransferHandlerGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/integration/jei/RecipeTransferHandlerGrid.java @@ -50,7 +50,7 @@ public class RecipeTransferHandlerGrid implements IRecipeTransferHandler { if (doTransfer) { LAST_TRANSFER = System.currentTimeMillis(); - if (grid.getType() == GridType.PATTERN && ((NetworkNodeGrid) grid).isProcessingPattern()) { + if (grid.getGridType() == GridType.PATTERN && ((NetworkNodeGrid) grid).isProcessingPattern()) { List inputs = new LinkedList<>(); List outputs = new LinkedList<>(); @@ -71,7 +71,7 @@ public class RecipeTransferHandlerGrid implements IRecipeTransferHandler { RS.INSTANCE.network.sendToServer(new MessageGridTransfer(recipeLayout.getItemStacks().getGuiIngredients(), container.inventorySlots.stream().filter(s -> s.inventory instanceof InventoryCrafting).collect(Collectors.toList()))); } } else { - if (grid.getType() == GridType.PATTERN && ((NetworkNodeGrid) grid).isProcessingPattern()) { + if (grid.getGridType() == GridType.PATTERN && ((NetworkNodeGrid) grid).isProcessingPattern()) { if (recipeLayout.getRecipeCategory().getUid().equals(VanillaRecipeCategoryUid.CRAFTING)) { return ERROR_CANNOT_TRANSFER; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/integration/oc/EnvironmentNetwork.java b/src/main/java/com/raoulvdberge/refinedstorage/integration/oc/EnvironmentNetwork.java index 851a0b360..c65c56bfb 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/integration/oc/EnvironmentNetwork.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/integration/oc/EnvironmentNetwork.java @@ -150,10 +150,12 @@ public class EnvironmentNetwork extends AbstractManagedEnvironment { int count = 0; for (ICraftingTask task : node.getNetwork().getCraftingManager().getTasks()) { - if (API.instance().getComparer().isEqual(task.getRequested(), stack, COMPARE_NBT | COMPARE_DAMAGE)) { - node.getNetwork().getCraftingManager().cancel(task.getId()); + if (task.getRequested().getItem() != null) { + if (API.instance().getComparer().isEqual(task.getRequested().getItem(), stack, COMPARE_NBT | COMPARE_DAMAGE)) { + node.getNetwork().getCraftingManager().cancel(task.getId()); - count++; + count++; + } } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerFluid.java b/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerFluid.java index 80b68bb6e..d03062e64 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerFluid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerFluid.java @@ -24,12 +24,16 @@ public class ItemHandlerFluid extends ItemHandlerBase { ItemStack stack = getStackInSlot(slot); if (stack.isEmpty()) { - fluids[slot] = null; + setFluidStack(slot, null); } else { - fluids[slot] = StackUtils.getFluid(ItemHandlerHelper.copyStackWithSize(stack, 1), true).getValue(); + setFluidStack(slot, StackUtils.getFluid(ItemHandlerHelper.copyStackWithSize(stack, 1), true).getValue()); } } + public void setFluidStack(int slot, @Nullable FluidStack stack) { + fluids[slot] = stack; + } + @Nullable public FluidStack getFluidStackInSlot(int slot) { return fluids[slot]; diff --git a/src/main/java/com/raoulvdberge/refinedstorage/item/ItemPattern.java b/src/main/java/com/raoulvdberge/refinedstorage/item/ItemPattern.java index 3a83336be..e3512273a 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/item/ItemPattern.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/item/ItemPattern.java @@ -25,6 +25,7 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -41,6 +42,8 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider { private static final String NBT_VERSION = "Version"; public static final String NBT_INPUT_SLOT = "Input_%d"; public static final String NBT_OUTPUT_SLOT = "Output_%d"; + private static final String NBT_FLUID_INPUT_SLOT = "FluidInput_%d"; + private static final String NBT_FLUID_OUTPUT_SLOT = "FluidOutput_%d"; private static final String NBT_OREDICT = "Oredict"; public static final String NBT_PROCESSING = "Processing"; @@ -81,11 +84,13 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider { tooltip.add(TextFormatting.YELLOW + I18n.format("misc.refinedstorage:pattern.inputs") + TextFormatting.RESET); RenderUtils.addCombinedItemsToTooltip(tooltip, true, pattern.getInputs().stream().map(i -> i.size() > 0 ? i.get(0) : ItemStack.EMPTY).collect(Collectors.toList())); + RenderUtils.addCombinedFluidsToTooltip(tooltip, pattern.getFluidInputs()); tooltip.add(TextFormatting.YELLOW + I18n.format("misc.refinedstorage:pattern.outputs") + TextFormatting.RESET); } RenderUtils.addCombinedItemsToTooltip(tooltip, true, pattern.getOutputs()); + RenderUtils.addCombinedFluidsToTooltip(tooltip, pattern.getFluidOutputs()); if (isOredict(stack)) { tooltip.add(TextFormatting.BLUE + I18n.format("misc.refinedstorage:pattern.oredict") + TextFormatting.RESET); @@ -147,6 +152,44 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider { return stack; } + public static void setFluidInputSlot(ItemStack pattern, int slot, FluidStack stack) { + if (!pattern.hasTagCompound()) { + pattern.setTagCompound(new NBTTagCompound()); + } + + pattern.getTagCompound().setTag(String.format(NBT_FLUID_INPUT_SLOT, slot), stack.writeToNBT(new NBTTagCompound())); + } + + @Nullable + public static FluidStack getFluidInputSlot(ItemStack pattern, int slot) { + String id = String.format(NBT_FLUID_INPUT_SLOT, slot); + + if (!pattern.hasTagCompound() || !pattern.getTagCompound().hasKey(id)) { + return null; + } + + return FluidStack.loadFluidStackFromNBT(pattern.getTagCompound().getCompoundTag(id)); + } + + public static void setFluidOutputSlot(ItemStack pattern, int slot, FluidStack stack) { + if (!pattern.hasTagCompound()) { + pattern.setTagCompound(new NBTTagCompound()); + } + + pattern.getTagCompound().setTag(String.format(NBT_FLUID_OUTPUT_SLOT, slot), stack.writeToNBT(new NBTTagCompound())); + } + + @Nullable + public static FluidStack getFluidOutputSlot(ItemStack pattern, int slot) { + String id = String.format(NBT_FLUID_OUTPUT_SLOT, slot); + + if (!pattern.hasTagCompound() || !pattern.getTagCompound().hasKey(id)) { + return null; + } + + return FluidStack.loadFluidStackFromNBT(pattern.getTagCompound().getCompoundTag(id)); + } + public static boolean isProcessing(ItemStack pattern) { return pattern.hasTagCompound() && pattern.getTagCompound().hasKey(NBT_PROCESSING) && pattern.getTagCompound().getBoolean(NBT_PROCESSING); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageCraftingMonitorElements.java b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageCraftingMonitorElements.java index 2f527a49e..6061bef73 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageCraftingMonitorElements.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageCraftingMonitorElements.java @@ -1,6 +1,8 @@ package com.raoulvdberge.refinedstorage.network; import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; import com.raoulvdberge.refinedstorage.api.network.grid.IGridTab; import com.raoulvdberge.refinedstorage.apiimpl.API; @@ -8,7 +10,6 @@ import com.raoulvdberge.refinedstorage.gui.GuiBase; import com.raoulvdberge.refinedstorage.gui.GuiCraftingMonitor; import com.raoulvdberge.refinedstorage.tile.craftingmonitor.ICraftingMonitor; import io.netty.buffer.ByteBuf; -import net.minecraft.item.ItemStack; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; @@ -37,7 +38,14 @@ public class MessageCraftingMonitorElements implements IMessage, IMessageHandler for (int i = 0; i < size; ++i) { UUID id = UUID.fromString(ByteBufUtils.readUTF8String(buf)); - ItemStack requested = ByteBufUtils.readItemStack(buf); + + ICraftingRequestInfo requested = null; + try { + requested = API.instance().createCraftingRequestInfo(ByteBufUtils.readTag(buf)); + } catch (CraftingTaskReadException e) { + e.printStackTrace(); + } + int qty = buf.readInt(); long executionStarted = buf.readLong(); @@ -63,7 +71,7 @@ public class MessageCraftingMonitorElements implements IMessage, IMessageHandler for (ICraftingTask task : craftingMonitor.getTasks()) { ByteBufUtils.writeUTF8String(buf, task.getId().toString()); - ByteBufUtils.writeItemStack(buf, task.getRequested()); + ByteBufUtils.writeTag(buf, task.getRequested().writeToNbt()); buf.writeInt(task.getQuantity()); buf.writeLong(task.getExecutionStarted()); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridClear.java b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridClear.java index 06b285021..6a22953d8 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridClear.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridClear.java @@ -37,7 +37,7 @@ public class MessageGridClear extends MessageHandlerPlayerToServer { - public List stacks; - public int hash; - public int quantity; + private List stacks; + private int hash; + private int quantity; + private boolean fluids; public MessageGridCraftingPreviewResponse() { } - public MessageGridCraftingPreviewResponse(List stacks, int hash, int quantity) { + public MessageGridCraftingPreviewResponse(List stacks, int hash, int quantity, boolean fluids) { this.stacks = stacks; this.hash = hash; this.quantity = quantity; + this.fluids = fluids; } @Override public void fromBytes(ByteBuf buf) { this.hash = buf.readInt(); this.quantity = buf.readInt(); + this.fluids = buf.readBoolean(); this.stacks = new LinkedList<>(); @@ -50,6 +53,7 @@ public class MessageGridCraftingPreviewResponse implements IMessage, IMessageHan public void toBytes(ByteBuf buf) { buf.writeInt(hash); buf.writeInt(quantity); + buf.writeBoolean(fluids); buf.writeInt(stacks.size()); @@ -69,7 +73,7 @@ public class MessageGridCraftingPreviewResponse implements IMessage, IMessageHan screen = ((GuiCraftingStart) screen).getParent(); } - FMLCommonHandler.instance().showGuiScreen(new GuiCraftingPreview(screen, message.stacks, message.hash, message.quantity)); + FMLCommonHandler.instance().showGuiScreen(new GuiCraftingPreview(screen, message.stacks, message.hash, message.quantity, message.fluids)); }); return null; diff --git a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridCraftingStart.java b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridCraftingStart.java index fa4b62cea..96b62b036 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridCraftingStart.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridCraftingStart.java @@ -10,25 +10,29 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage; public class MessageGridCraftingStart extends MessageHandlerPlayerToServer implements IMessage { private int hash; private int quantity; + private boolean fluids; public MessageGridCraftingStart() { } - public MessageGridCraftingStart(int hash, int quantity) { + public MessageGridCraftingStart(int hash, int quantity, boolean fluids) { this.hash = hash; this.quantity = quantity; + this.fluids = fluids; } @Override public void fromBytes(ByteBuf buf) { hash = buf.readInt(); quantity = buf.readInt(); + fluids = buf.readBoolean(); } @Override public void toBytes(ByteBuf buf) { buf.writeInt(hash); buf.writeInt(quantity); + buf.writeBoolean(fluids); } @Override @@ -38,8 +42,14 @@ public class MessageGridCraftingStart extends MessageHandlerPlayerToServer implements IMessage { + private int slot; + private int amount; + + public MessageGridFluidAmount(int slot, int amount) { + this.slot = slot; + this.amount = amount; + } + + public MessageGridFluidAmount() { + // NO OP + } + + @Override + protected void handle(MessageGridFluidAmount message, EntityPlayerMP player) { + Container container = player.openContainer; + + if (container instanceof ContainerGrid && message.slot >= 0 && message.amount > 0 && message.amount <= Fluid.BUCKET_VOLUME) { + IGrid grid = ((ContainerGrid) container).getGrid(); + + if (grid instanceof NetworkNodeGrid) { + NetworkNodeGrid node = (NetworkNodeGrid) grid; + + if (message.slot < node.getMatrixProcessingFluids().getSlots()) { + node.getMatrixProcessingFluids().getStackInSlot(message.slot).setCount(message.amount); + } + } + } + } + + @Override + public void fromBytes(ByteBuf buf) { + slot = buf.readInt(); + amount = buf.readInt(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeInt(slot); + buf.writeInt(amount); + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridFluidDelta.java b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridFluidDelta.java index eeb6e8530..ceea8809f 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridFluidDelta.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridFluidDelta.java @@ -32,7 +32,7 @@ public class MessageGridFluidDelta implements IMessage, IMessageHandler new CraftingMonitorElementItemRender(StackUtils.readItemStack(buf), buf.readInt(), buf.readInt())); - API.instance().getCraftingMonitorElementRegistry().add(CraftingMonitorElementFluidRender.ID, buf -> new CraftingMonitorElementFluidRender(StackUtils.readFluidStack(buf).getRight(), buf.readInt())); + API.instance().getCraftingMonitorElementRegistry().add(CraftingMonitorElementFluidRender.ID, buf -> new CraftingMonitorElementFluidRender(StackUtils.readFluidStack(buf).getRight(), buf.readInt(), buf.readInt())); API.instance().getCraftingMonitorElementRegistry().add(CraftingMonitorElementText.ID, buf -> new CraftingMonitorElementText(ByteBufUtils.readUTF8String(buf), buf.readInt())); API.instance().getCraftingMonitorElementRegistry().add(CraftingMonitorElementColor.ID, buf -> { int color = buf.readInt(); @@ -183,6 +183,7 @@ public class ProxyCommon { RS.INSTANCE.network.registerMessage(MessageStorageDiskSizeRequest.class, MessageStorageDiskSizeRequest.class, id++, Side.SERVER); RS.INSTANCE.network.registerMessage(MessageStorageDiskSizeResponse.class, MessageStorageDiskSizeResponse.class, id++, Side.CLIENT); RS.INSTANCE.network.registerMessage(MessageConfigSync.class, MessageConfigSync.class, id++, Side.CLIENT); + RS.INSTANCE.network.registerMessage(MessageGridFluidAmount.class, MessageGridFluidAmount.class, id++, Side.SERVER); NetworkRegistry.INSTANCE.registerGuiHandler(RS.INSTANCE, new GuiHandler()); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/TileGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/TileGrid.java index f472382db..71b2f95fc 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/TileGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/TileGrid.java @@ -7,6 +7,7 @@ import com.raoulvdberge.refinedstorage.container.ContainerGrid; import com.raoulvdberge.refinedstorage.gui.GuiBase; import com.raoulvdberge.refinedstorage.gui.grid.GuiGrid; import com.raoulvdberge.refinedstorage.tile.TileNode; +import com.raoulvdberge.refinedstorage.tile.config.IType; import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.util.EnumFacing; @@ -82,6 +83,7 @@ public class TileGrid extends TileNode { ((ContainerGrid) player.openContainer).sendAllSlots(); }); }, (initial, p) -> GuiBase.executeLater(GuiGrid.class, GuiBase::initGui)); + public static final TileDataParameter PROCESSING_TYPE = IType.createParameter(); public static void trySortGrid(boolean initial) { if (!initial) { @@ -99,6 +101,7 @@ public class TileGrid extends TileNode { dataManager.addWatchedParameter(TAB_PAGE); dataManager.addWatchedParameter(OREDICT_PATTERN); dataManager.addWatchedParameter(PROCESSING_PATTERN); + dataManager.addWatchedParameter(PROCESSING_TYPE); } @Override @@ -114,12 +117,12 @@ public class TileGrid extends TileNode { @Override public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing side) { - return (getNode().getType() == GridType.PATTERN && capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) || super.hasCapability(capability, side); + return (getNode().getGridType() == GridType.PATTERN && capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) || super.hasCapability(capability, side); } @Override public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing side) { - if (getNode().getType() == GridType.PATTERN && capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + if (getNode().getGridType() == GridType.PATTERN && capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(getNode().getPatterns()); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessFluidGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessFluidGrid.java index ebf68efea..65246013d 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessFluidGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessFluidGrid.java @@ -61,7 +61,7 @@ public class WirelessFluidGrid implements IGridNetworkAware { } @Override - public GridType getType() { + public GridType getGridType() { return GridType.FLUID; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessGrid.java index 782620f9f..3eac2eb24 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessGrid.java @@ -90,7 +90,7 @@ public class WirelessGrid implements IGridNetworkAware { } @Override - public GridType getType() { + public GridType getGridType() { return GridType.NORMAL; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java index ffda944cb..38328d8f0 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java @@ -186,7 +186,7 @@ public class PortableGrid implements IGrid, IPortableGrid, IStorageDiskContainer } @Override - public GridType getType() { + public GridType getGridType() { return GridType.NORMAL; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java index 6bda7ee2a..e358bcab0 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java @@ -257,7 +257,7 @@ public class TilePortableGrid extends TileBase implements IGrid, IPortableGrid, } @Override - public GridType getType() { + public GridType getGridType() { return GridType.NORMAL; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/util/RenderUtils.java b/src/main/java/com/raoulvdberge/refinedstorage/util/RenderUtils.java index 35d4518a8..987007e86 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/util/RenderUtils.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/util/RenderUtils.java @@ -1,6 +1,7 @@ package com.raoulvdberge.refinedstorage.util; import com.google.common.collect.ImmutableMap; +import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.apiimpl.API; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -20,6 +21,7 @@ import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.ItemStack; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; +import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.client.ForgeHooksClient; @@ -257,6 +259,30 @@ public final class RenderUtils { } } + public static void addCombinedFluidsToTooltip(List tooltip, NonNullList stacks) { + Set combinedIndices = new HashSet<>(); + + for (int i = 0; i < stacks.size(); ++i) { + if (!combinedIndices.contains(i)) { + FluidStack stack = stacks.get(i); + + String data = stack.getLocalizedName(); + + int amount = stack.amount; + + for (int j = i + 1; j < stacks.size(); ++j) { + if (API.instance().getComparer().isEqual(stack, stacks.get(j), IComparer.COMPARE_NBT)) { + amount += stacks.get(j).amount; + + combinedIndices.add(j); + } + } + + tooltip.add(API.instance().getQuantityFormatter().formatInBucketForm(amount) + " " + data); + } + } + } + // Copied with some tweaks from GuiUtils#drawHoveringText(@Nonnull final ItemStack stack, List textLines, int mouseX, int mouseY, int screenWidth, int screenHeight, int maxTextWidth, FontRenderer font) public static void drawTooltipWithSmallText(List textLines, List smallTextLines, boolean showSmallText, @Nonnull ItemStack stack, int mouseX, int mouseY, int screenWidth, int screenHeight, FontRenderer fontRenderer) { // RS BEGIN diff --git a/src/main/java/com/raoulvdberge/refinedstorage/util/StackUtils.java b/src/main/java/com/raoulvdberge/refinedstorage/util/StackUtils.java index a62631e8c..ec35a2a2c 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/util/StackUtils.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/util/StackUtils.java @@ -106,17 +106,15 @@ public final class StackUtils { } } - public static void writeItems(IItemHandler handler, int id, NBTTagCompound tag) { + public static void writeItems(IItemHandler handler, int id, NBTTagCompound tag, Function serializer) { NBTTagList tagList = new NBTTagList(); for (int i = 0; i < handler.getSlots(); i++) { if (!handler.getStackInSlot(i).isEmpty()) { - NBTTagCompound stackTag = new NBTTagCompound(); + NBTTagCompound stackTag = serializer.apply(handler.getStackInSlot(i)); stackTag.setInteger(NBT_SLOT, i); - handler.getStackInSlot(i).writeToNBT(stackTag); - tagList.appendTag(stackTag); } } @@ -124,7 +122,11 @@ public final class StackUtils { tag.setTag(String.format(NBT_INVENTORY, id), tagList); } - public static void readItems(IItemHandlerModifiable handler, int id, NBTTagCompound tag) { + public static void writeItems(IItemHandler handler, int id, NBTTagCompound tag) { + writeItems(handler, id, tag, stack -> stack.writeToNBT(new NBTTagCompound())); + } + + public static void readItems(IItemHandlerModifiable handler, int id, NBTTagCompound tag, Function deserializer) { String name = String.format(NBT_INVENTORY, id); if (tag.hasKey(name)) { @@ -134,12 +136,16 @@ public final class StackUtils { int slot = tagList.getCompoundTagAt(i).getInteger(NBT_SLOT); if (slot >= 0 && slot < handler.getSlots()) { - handler.setStackInSlot(slot, new ItemStack(tagList.getCompoundTagAt(i))); + handler.setStackInSlot(slot, deserializer.apply(tagList.getCompoundTagAt(i))); } } } } + public static void readItems(IItemHandlerModifiable handler, int id, NBTTagCompound tag) { + readItems(handler, id, tag, ItemStack::new); + } + public static void writeItems(IInventory inventory, int id, NBTTagCompound tag) { NBTTagList tagList = new NBTTagList(); diff --git a/src/main/resources/assets/refinedstorage/lang/en_us.lang b/src/main/resources/assets/refinedstorage/lang/en_us.lang index 3ec417520..58e98971d 100644 --- a/src/main/resources/assets/refinedstorage/lang/en_us.lang +++ b/src/main/resources/assets/refinedstorage/lang/en_us.lang @@ -10,6 +10,7 @@ gui.refinedstorage:grid=Grid gui.refinedstorage:grid.craft=Craft gui.refinedstorage:crafting_grid=Crafting Grid gui.refinedstorage:pattern_grid=Pattern Grid +gui.refinedstorage:pattern_grid.fluid_amount=Fluid amount in mB gui.refinedstorage:grid.pattern_create=Create Pattern gui.refinedstorage:fluid_grid=Fluid Grid gui.refinedstorage:disk_drive=Drive