More work on Fluid crafting system

This commit is contained in:
DarkGuardsman 2013-09-13 01:10:13 -04:00
parent c9c9f1d422
commit c39cdc15a1
3 changed files with 256 additions and 166 deletions

View file

@ -1,14 +1,211 @@
package dark.core.network.fluid; package dark.core.network.fluid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import dark.core.network.fluid.FluidRecipeInfo.SimpleFluidRecipe;
import dark.core.prefab.helpers.FluidHelper;
import dark.core.prefab.helpers.Pair;
import dark.core.prefab.helpers.Triple;
/** Handles all kinds of process involving mixing Fluids with other fluids and/or Items, Blocks, /** Handles all kinds of process involving mixing Fluids with other fluids and/or Items, Blocks,
* ItemStack, or Liquids * ItemStack, or Liquids
* *
* @author DarkGuardsman */ * @author DarkGuardsman */
public class FluidCraftingHandler 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);
}
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() public static void loadPotionRecipes()
{ {
//TODO load the process by which a potion would be created threw fliud crafting //TODO load the process by which a potion would be created threw fliud crafting
} }
/** 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))
{
Object result = fluidMergeResults.get(new Pair<Fluid, Fluid>(stackOne.getFluid(), stackTwo.getFluid()));
/* Try to merge fluids by mod defined rules first */
if (result != null)
{
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().getKey() instanceof FluidStack)
{
resultStack = FluidHelper.getStack((FluidStack) re.getC().getKey(), re.getC().getValue());
}
else if (re.getC().getKey() instanceof FluidStack)
{
resultStack = new FluidStack((Fluid) re.getC().getKey(), re.getC().getValue());
}
}
}
if (resultStack == null)
{
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;
}
} }

View file

@ -1,32 +1,14 @@
package dark.core.network.fluid; package dark.core.network.fluid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection; import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import universalelectricity.core.vector.Vector3; import universalelectricity.core.vector.Vector3;
import universalelectricity.core.vector.VectorHelper; import universalelectricity.core.vector.VectorHelper;
import dark.api.parts.INetworkPart; import dark.api.parts.INetworkPart;
import dark.core.prefab.helpers.Pair;
import dark.core.prefab.tilenetwork.NetworkTileEntities; import dark.core.prefab.tilenetwork.NetworkTileEntities;
public class FluidNetworkHelper public class FluidNetworkHelper
{ {
/** Map of results of two different liquids merging */
public static HashMap<Pair<Fluid, Fluid>, Object> fluidMergeResults = new HashMap<Pair<Fluid, Fluid>, Object>();
static
{
fluidMergeResults.put(new Pair<Fluid, Fluid>(FluidRegistry.WATER, FluidRegistry.LAVA), Block.obsidian);
fluidMergeResults.put(new Pair<Fluid, Fluid>(FluidRegistry.LAVA, FluidRegistry.WATER), Block.cobblestone);
}
/** Invalidates a TileEntity that is part of a fluid network */ /** Invalidates a TileEntity that is part of a fluid network */
public static void invalidate(TileEntity tileEntity) public static void invalidate(TileEntity tileEntity)
@ -48,140 +30,4 @@ public class FluidNetworkHelper
} }
} }
/** 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))
{
/* Try to merge fluids by mod defined rules first */
if (fluidMergeResults.containsKey(new Pair<Fluid, Fluid>(stackOne.getFluid(), stackTwo.getFluid())))
{
Object result = fluidMergeResults.get(new Pair<Fluid, Fluid>(stackOne.getFluid(), stackTwo.getFluid()));
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);
}
}
if (resultStack == null)
{
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
* diffrent 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)
{
if (stackOne != null && stackTwo != null && !stackOne.equals(stackTwo))
{
if (fluidMergeResults.containsKey(new Pair<Fluid, Fluid>(stackOne.getFluid(), stackTwo.getFluid())))
{
//TODO add volume calculation too see if merge can happen resulting in one liquid just vanishing
//Case 100mb of fuel 10000mb of lava will result in fuel being consumed with no major results
return fluidMergeResults.get(new Pair<Fluid, Fluid>(stackOne.getFluid(), stackTwo.getFluid()));
}
}
return null;
}
} }

View file

@ -12,20 +12,43 @@ import dark.core.prefab.helpers.Triple;
* @author DarkGuardsman */ * @author DarkGuardsman */
public class FluidRecipeInfo public class FluidRecipeInfo
{ {
/** A + Energy = C, simple recipe designed to tell a boiler like machine how to handle input to
* output process */
public static class BoilingFluidRecipe public static class BoilingFluidRecipe
{ {
Object boiledObject; /** Unboiled object */
Object boiledResult; public Object boiledObject;
/** Boiled object */
public Object boiledResult;
/** In kelvin tempature units only */
public float heatLevel = 0;
/** Energy in jouls need to turn convert A to B */
public float energyPerMb = 1;
public BoilingFluidRecipe(Object unboiled, Object boiled, float boilingTempature, float energyPerUnitBoiled)
{
this.boiledObject = unboiled;
this.boiledResult = boiled;
this.heatLevel = boilingTempature;
this.energyPerMb = energyPerUnitBoiled;
}
@Override
public String toString()
{
return "[BoilingFluidRecipe] UnboiledObject: " + (this.boiledObject != null ? this.boiledObject.toString() : "null") + " | BoiledObject: " + (this.boiledResult != null ? this.boiledResult.toString() : "null") + " | BoilingTemp: " + this.heatLevel + "k | EnergyPerUnit: " + this.energyPerMb + "j";
}
} }
/** Basic A + B = C recipe result that should involve fluids but can be used as a 2 item crafting /** Basic A + B = C recipe result that should involve fluids but can be used as a 2 item crafting
* system if needed */ * system if needed */
public static class SimpleFluidRecipe public static class SimpleFluidRecipe
{ {
Object recipeObjectA, recipeObjectB, recipeObjectC; public Object recipeObjectA, recipeObjectB, recipeObjectC;
int ratioOfA = 1, ratioOfB = 1, ratioOfC = 1; public int ratioOfA = 1, ratioOfB = 1, ratioOfC = 1;
/** Size compared to the largest volume that the smallest volume can be */ /** Size compared to the largest volume that the smallest volume can be */
float mixingPercentMin = .1f; public float mixingPercentMin = .1f;
public boolean canBeReversed = false;
/** receiving & input object must be either be an instance of a class extending Item, /** receiving & input object must be either be an instance of a class extending Item,
* ItemStack, Block, Fluid, FluidStack, or OreNames. Anything else and the mixing will never * ItemStack, Block, Fluid, FluidStack, or OreNames. Anything else and the mixing will never
@ -42,6 +65,20 @@ public class FluidRecipeInfo
this.recipeObjectC = output; this.recipeObjectC = output;
} }
public SimpleFluidRecipe setRatio(int receivingVolume, int inputVolume, int result)
{
this.ratioOfA = receivingVolume;
this.ratioOfB = inputVolume;
this.ratioOfC = result;
return this;
}
public SimpleFluidRecipe setIsReversable(boolean canBeReversed)
{
this.canBeReversed = canBeReversed;
return this;
}
public Object getResult() public Object getResult()
{ {
return this.recipeObjectC; return this.recipeObjectC;
@ -137,12 +174,13 @@ public class FluidRecipeInfo
} }
} }
/** Stores the list of process need to complete a long step process of creating a complex fluid /** Stores the list of processes needed to complete a fluid recipe that require more than one
* based mixing recipe */ * step to complete. Only used by brewing factories, and is suggest too still register result as
* a SimpleFluidRecipe unless the result can't be stored or moved easily. */
public static class ComplexFluidRecipe public static class ComplexFluidRecipe
{ {
int numberOfSteps; public int numberOfSteps;
SimpleFluidRecipe[] stepArray; public SimpleFluidRecipe[] stepArray;
public ComplexFluidRecipe(int numberOfSteps) public ComplexFluidRecipe(int numberOfSteps)
{ {
@ -154,18 +192,27 @@ public class FluidRecipeInfo
{ {
if (step < numberOfSteps) if (step < numberOfSteps)
{ {
stepArray[step] = stepRecipe;
} }
return this; return this;
} }
public boolean canCompleteStep(int step, Object receiving, Object input) public boolean canCompleteStep(int step, Object receiving, Object input)
{ {
if (step < numberOfSteps) if (this.getStep(step) != null)
{ {
return this.getStep(step).canComplete(receiving, input);
} }
return false; return false;
} }
public SimpleFluidRecipe getStep(int step)
{
if (step < numberOfSteps)
{
return stepArray[step];
}
return null;
}
} }
} }