299 lines
10 KiB
Java
299 lines
10 KiB
Java
|
package resonantinduction.mechanical.fluid;
|
||
|
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.HashMap;
|
||
|
import java.util.List;
|
||
|
|
||
|
import net.minecraft.block.Block;
|
||
|
import net.minecraft.item.ItemStack;
|
||
|
import net.minecraft.nbt.NBTTagCompound;
|
||
|
import net.minecraftforge.fluids.Fluid;
|
||
|
import net.minecraftforge.fluids.FluidRegistry;
|
||
|
import net.minecraftforge.fluids.FluidStack;
|
||
|
import resonantinduction.mechanical.fluid.network.IFluidRecipeCrafter;
|
||
|
import resonantinduction.mechanical.fluid.network.FluidRecipeInfo.SimpleFluidRecipe;
|
||
|
import calclavia.lib.utility.FluidHelper;
|
||
|
|
||
|
import com.builtbroken.common.Pair;
|
||
|
import com.builtbroken.common.Triple;
|
||
|
|
||
|
/**
|
||
|
* Handles all kinds of process involving mixing Fluids with other fluids and/or Items, Blocks,
|
||
|
* ItemStack, or Liquids
|
||
|
*
|
||
|
* @author DarkGuardsman
|
||
|
*/
|
||
|
public class FluidCraftingHandler
|
||
|
{
|
||
|
/** Map of results of two different liquids merging */
|
||
|
public static HashMap<Pair<Object, Object>, Object> fluidMergeResults = new HashMap<Pair<Object, Object>, Object>();
|
||
|
|
||
|
static
|
||
|
{
|
||
|
registerRecipe(FluidRegistry.LAVA, FluidRegistry.WATER, Block.obsidian);
|
||
|
registerRecipe(FluidRegistry.WATER, FluidRegistry.LAVA, Block.cobblestone);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a very basic A + B = C result for mixing two objects together. Suggest that the use
|
||
|
* of a SimpleFluidRecipe i used instead to create a more refined fluid mixing that takes into
|
||
|
* account ratios, and fluid volumes
|
||
|
*/
|
||
|
public static void registerRecipe(Object a, Object b, Object c)
|
||
|
{
|
||
|
if (a != null && b != null && c != null)
|
||
|
{
|
||
|
registerFluidRecipe(new SimpleFluidRecipe(a, b, c));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void registerFluidRecipe(SimpleFluidRecipe recipe)
|
||
|
{
|
||
|
if (recipe != null && recipe.recipeObjectA != null && recipe.recipeObjectB != null && recipe.recipeObjectC != null)
|
||
|
{
|
||
|
if (!fluidMergeResults.containsKey(new Pair<Object, Object>(recipe.recipeObjectA, recipe.recipeObjectB)))
|
||
|
{
|
||
|
fluidMergeResults.put(new Pair<Object, Object>(recipe.recipeObjectA, recipe.recipeObjectB), recipe);
|
||
|
}
|
||
|
if (recipe.canBeReversed)
|
||
|
{
|
||
|
if (!fluidMergeResults.containsKey(new Pair<Object, Object>(recipe.recipeObjectB, recipe.recipeObjectA)))
|
||
|
{
|
||
|
fluidMergeResults.put(new Pair<Object, Object>(recipe.recipeObjectB, recipe.recipeObjectA), recipe);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void loadPotionRecipes()
|
||
|
{
|
||
|
// TODO load the process by which a potion would be created threw fliud crafting
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Does the fluid recipe crafting for the crafter object. Requires that the object fully use all
|
||
|
* methods from the #IFluidRecipeCrafter
|
||
|
*
|
||
|
* @param crafter - crafting object, recommend it be a tile but can be anything as long as the
|
||
|
* method are used correctly. In some recipe cases when the setRecipeObjectContent nothing will
|
||
|
* be used. If result is null assume not crafting was performed. If there is a result the
|
||
|
* crafter couldn't use the output to reduce the input values. From here the IFluidRecipeCrafter
|
||
|
* will need to process the output and decress the input values correctly
|
||
|
*/
|
||
|
public static void craft(IFluidRecipeCrafter crafter)
|
||
|
{
|
||
|
Object received = crafter.getReceivingObjectStack();
|
||
|
int receivedVolume = 0;
|
||
|
Object input = crafter.getInputObjectStack();
|
||
|
int inputVolume = 0;
|
||
|
if (crafter != null && received != null && input != null)
|
||
|
{
|
||
|
// Trip input values so they will match the correct mapped values
|
||
|
if (received instanceof FluidStack)
|
||
|
{
|
||
|
receivedVolume = ((FluidStack) received).amount;
|
||
|
received = FluidHelper.getStack((FluidStack) received, 1);
|
||
|
}
|
||
|
if (received instanceof ItemStack)
|
||
|
{
|
||
|
receivedVolume = ((ItemStack) received).stackSize;
|
||
|
((ItemStack) received).stackSize = 1;
|
||
|
}
|
||
|
if (input instanceof FluidStack)
|
||
|
{
|
||
|
inputVolume = ((FluidStack) input).amount;
|
||
|
input = FluidHelper.getStack((FluidStack) input, 1);
|
||
|
}
|
||
|
if (input instanceof ItemStack)
|
||
|
{
|
||
|
receivedVolume = ((ItemStack) input).stackSize;
|
||
|
((ItemStack) input).stackSize = 1;
|
||
|
}
|
||
|
|
||
|
// Get result
|
||
|
Object result = fluidMergeResults.containsKey(new Pair<Object, Object>(crafter.getReceivingObjectStack(), crafter.getInputObjectStack()));
|
||
|
|
||
|
// reset stack sized
|
||
|
if (received instanceof FluidStack)
|
||
|
{
|
||
|
((FluidStack) received).amount = receivedVolume;
|
||
|
}
|
||
|
if (received instanceof ItemStack)
|
||
|
{
|
||
|
((ItemStack) received).stackSize = receivedVolume;
|
||
|
}
|
||
|
if (input instanceof FluidStack)
|
||
|
{
|
||
|
((FluidStack) input).amount = inputVolume;
|
||
|
}
|
||
|
if (input instanceof ItemStack)
|
||
|
{
|
||
|
((ItemStack) input).stackSize = inputVolume;
|
||
|
}
|
||
|
if (result != null)
|
||
|
{
|
||
|
if (result instanceof SimpleFluidRecipe)
|
||
|
{
|
||
|
Triple<Integer, Integer, Pair<Object, Integer>> re = ((SimpleFluidRecipe) result).mix(crafter.getInputObjectStack(), crafter.getInputObjectStack());
|
||
|
crafter.setRecipeObjectContent(received, re.getA(), input, re.getB(), re.getC().left(), re.getC().right());
|
||
|
}
|
||
|
}
|
||
|
crafter.setRecipeObjectContent(received, 0, input, 0, result, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** Merges two fluids together that don't result in damage to the network */
|
||
|
public static FluidStack mergeFluidStacks(FluidStack stackOne, FluidStack stackTwo)
|
||
|
{
|
||
|
FluidStack resultStack = null;
|
||
|
|
||
|
if (stackTwo != null && stackOne != null && stackOne.isFluidEqual(stackTwo))
|
||
|
{
|
||
|
resultStack = stackOne.copy();
|
||
|
resultStack.amount += stackTwo.amount;
|
||
|
}
|
||
|
else if (stackOne == null && stackTwo != null)
|
||
|
{
|
||
|
resultStack = stackTwo.copy();
|
||
|
}
|
||
|
else if (stackOne != null && stackTwo == null)
|
||
|
{
|
||
|
resultStack = stackOne.copy();
|
||
|
}
|
||
|
else if (stackTwo != null && stackOne != null && !stackOne.isFluidEqual(stackTwo))
|
||
|
{
|
||
|
System.out.println("preforming fluid merge event");
|
||
|
Object result = fluidMergeResults.get(new Pair<Fluid, Fluid>(stackOne.getFluid(), stackTwo.getFluid()));
|
||
|
/* Try to merge fluids by mod defined rules first */
|
||
|
if (result != null)
|
||
|
{
|
||
|
System.out.println("result = " + result.toString());
|
||
|
if (result instanceof Fluid)
|
||
|
{
|
||
|
resultStack = new FluidStack(((Fluid) result).getID(), stackOne.amount + stackTwo.amount);
|
||
|
}
|
||
|
else if (result instanceof FluidStack)
|
||
|
{
|
||
|
resultStack = ((FluidStack) result).copy();
|
||
|
resultStack.amount = stackOne.amount + stackTwo.amount;
|
||
|
}
|
||
|
else if (result instanceof String && ((String) result).startsWith("Liquid:"))
|
||
|
{
|
||
|
resultStack = new FluidStack(FluidRegistry.getFluid(((String) result).replace("Liquid:", "")), stackOne.amount + stackTwo.amount);
|
||
|
}
|
||
|
else if (result instanceof SimpleFluidRecipe)
|
||
|
{
|
||
|
Triple<Integer, Integer, Pair<Object, Integer>> re = ((SimpleFluidRecipe) result).mix(stackOne, stackTwo);
|
||
|
if (re.getC().left() instanceof FluidStack)
|
||
|
{
|
||
|
resultStack = FluidHelper.getStack((FluidStack) re.getC().left(), re.getC().right());
|
||
|
}
|
||
|
else if (re.getC().left() instanceof FluidStack)
|
||
|
{
|
||
|
resultStack = new FluidStack((Fluid) re.getC().left(), re.getC().right());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (resultStack == null)
|
||
|
{
|
||
|
System.out.println("Merging fluids into a waste fluid stack");
|
||
|
Fluid waste = FluidRegistry.getFluid("waste");
|
||
|
if (waste == null)
|
||
|
{
|
||
|
System.out.println("[FluidNetworkHelper] Attempted to merge two fluids into a waste fluid stack but Forge fluid registry return null for waste. Possible that waste fluid was disabled or not registered correctly.");
|
||
|
return null;
|
||
|
}
|
||
|
/* If both liquids are waste then copy fluidStack lists then merge */
|
||
|
if (stackTwo.fluidID == waste.getID() && stackOne.fluidID == waste.getID())
|
||
|
{
|
||
|
List<FluidStack> stacks = new ArrayList<FluidStack>();
|
||
|
stacks.addAll(getStacksFromWaste(stackOne.copy()));
|
||
|
stacks.addAll(getStacksFromWaste(stackTwo.copy()));
|
||
|
resultStack = createNewWasteStack(stacks.toArray(new FluidStack[stacks.size()]));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
resultStack = createNewWasteStack(stackOne.copy(), stackTwo.copy());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return resultStack;
|
||
|
}
|
||
|
|
||
|
/** Gets the fluidStacks that make up a waste FluidStack */
|
||
|
public static List<FluidStack> getStacksFromWaste(FluidStack wasteStack)
|
||
|
{
|
||
|
List<FluidStack> stacks = new ArrayList<FluidStack>();
|
||
|
if (wasteStack.fluidID == FluidRegistry.getFluidID("waste"))
|
||
|
{
|
||
|
for (int i = 1; i <= wasteStack.tag.getInteger("liquids"); i++)
|
||
|
{
|
||
|
FluidStack readStack = FluidStack.loadFluidStackFromNBT(wasteStack.tag.getCompoundTag("Liquid" + i));
|
||
|
if (readStack != null)
|
||
|
{
|
||
|
stacks.add(readStack);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return stacks;
|
||
|
}
|
||
|
|
||
|
/** Creates a new waste stack from the listed fluidStacks */
|
||
|
public static FluidStack createNewWasteStack(FluidStack... liquids)
|
||
|
{
|
||
|
FluidStack stack = new FluidStack(FluidRegistry.getFluid("waste"), 0);
|
||
|
stack.tag = new NBTTagCompound();
|
||
|
if (liquids != null)
|
||
|
{
|
||
|
int count = 0;
|
||
|
for (int i = 0; i < liquids.length; i++)
|
||
|
{
|
||
|
if (liquids[i] != null)
|
||
|
{
|
||
|
if (!liquids[i].getFluid().equals(stack.getFluid()))
|
||
|
{
|
||
|
count++;
|
||
|
stack.tag.setCompoundTag("Liquids" + count, liquids[i].writeToNBT(new NBTTagCompound()));
|
||
|
stack.amount += liquids[i].amount;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (FluidStack loadStack : getStacksFromWaste(liquids[i]))
|
||
|
{
|
||
|
count++;
|
||
|
stack.tag.setCompoundTag("Liquids" + count, loadStack.writeToNBT(new NBTTagCompound()));
|
||
|
stack.amount += loadStack.amount;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
stack.tag.setInteger("liquids", count);
|
||
|
}
|
||
|
return stack;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the result of the merge of the two fluids, order of merge does matter and will produce
|
||
|
* different results.
|
||
|
*
|
||
|
* @param stackOne - Receiving fluid, eg the one that is not moving
|
||
|
* @param stackTwo - Flowing fluid, eg the one moving into the first fluid
|
||
|
* @return Object result of the merge, can be anything from string, ItemStack, Item, Block, or
|
||
|
* enum action
|
||
|
*/
|
||
|
public static Object getMergeResult(FluidStack stackOne, FluidStack stackTwo)
|
||
|
{
|
||
|
FluidStack sampleStackOne, sampleStackTwo;
|
||
|
if (stackOne != null && stackTwo != null && !stackOne.equals(stackTwo))
|
||
|
{
|
||
|
sampleStackOne = FluidHelper.getStack(stackOne, 1);
|
||
|
sampleStackTwo = FluidHelper.getStack(stackTwo, 1);
|
||
|
if (fluidMergeResults.containsKey(new Pair<Object, Object>(sampleStackOne, sampleStackTwo)))
|
||
|
{
|
||
|
return fluidMergeResults.get(new Pair<Object, Object>(sampleStackOne, sampleStackTwo));
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
}
|