Merge branch 'integration-table-advanced-recipe' of https://github.com/Prototik/BuildCraft into Prototik-integration-table-advanced-recipe

This commit is contained in:
SpaceToad 2014-06-01 15:17:22 +02:00
commit fbf2cef772
9 changed files with 119 additions and 236 deletions

View file

@ -0,0 +1,67 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.recipes;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
public interface IIntegrationRecipe {
public static class IntegrationResult {
public double energyCost;
public ItemStack output;
public ItemStack[] usedComponents;
public static IntegrationResult create(double energyCost, ItemStack output, ItemStack... usedComponents) {
IntegrationResult result = new IntegrationResult();
result.energyCost = energyCost;
result.output = output;
result.usedComponents = usedComponents;
return result;
}
public static boolean enoughComponents(ItemStack[] components, ItemStack... needs) {
for (ItemStack need : needs) {
int found = 0;
for (ItemStack component : components) {
if (isMatchingItem(need, component)) {
found += component.stackSize;
}
}
if (found < need.stackSize) {
return false;
}
}
return true;
}
public static boolean isMatchingItem(ItemStack a, ItemStack b) {
if (a == null || b == null) {
return false;
}
if (a.getItem() != b.getItem()) {
return false;
}
if (a.getHasSubtypes() && !isWildcard(a) && !isWildcard(b) && a.getItemDamage() != b.getItemDamage()) {
return false;
}
return a.stackTagCompound == null ? b.stackTagCompound == null : a.stackTagCompound.equals(b.stackTagCompound);
}
private static boolean isWildcard(ItemStack stack) {
final int damage = stack.getItemDamage();
return damage == -1 || damage == OreDictionary.WILDCARD_VALUE;
}
}
boolean isValidInputA(ItemStack inputA);
boolean isValidInputB(ItemStack inputB);
IntegrationResult integrate(ItemStack inputA, ItemStack inputB, ItemStack[] components);
}

View file

@ -10,35 +10,14 @@ package buildcraft.api.recipes;
import java.util.List; import java.util.List;
import net.minecraft.item.ItemStack;
/** /**
* The Integration Table's primary purpose is to modify an input item's NBT * The Integration Table's primary purpose is to modify an input item's NBT
* data. As such its not a "traditional" type of recipe. Rather than predefined * data. As such its not a "traditional" type of recipe. Rather than predefined
* inputs and outputs, it takes an input and transforms it. * inputs and outputs, it takes an input and transforms it.
*/ */
public interface IIntegrationRecipeManager { public interface IIntegrationRecipeManager {
public interface IIntegrationRecipe {
double getEnergyCost();
boolean isValidInputA(ItemStack inputA);
boolean isValidInputB(ItemStack inputB);
ItemStack getOutputForInputs(ItemStack inputA, ItemStack inputB, ItemStack[] components);
ItemStack[] getComponents();
ItemStack[] getExampleInputsA();
ItemStack[] getExampleInputsB();
}
/** /**
* Add an Integration Table recipe. * Add an Integration Table recipe.
*
*/ */
void addRecipe(IIntegrationRecipe recipe); void addRecipe(IIntegrationRecipe recipe);

View file

@ -9,7 +9,6 @@
package buildcraft; package buildcraft;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List; import java.util.List;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
@ -213,13 +212,8 @@ public class BuildCraftSilicon extends BuildCraftMod {
BuildcraftRecipes.assemblyTable.addRecipe(new BoardRecipe()); BuildcraftRecipes.assemblyTable.addRecipe(new BoardRecipe());
BuildcraftRecipes.integrationTable.addRecipe(new RobotIntegrationRecipe()); BuildcraftRecipes.integrationTable.addRecipe(new RobotIntegrationRecipe());
// REVERSAL RECIPES // REVERSAL RECIPE
EnumSet<GateMaterial> materials = EnumSet.allOf(GateMaterial.class); BuildcraftRecipes.integrationTable.addRecipe(new GateLogicSwapRecipe());
materials.remove(GateMaterial.REDSTONE);
for (GateMaterial material : materials) {
BuildcraftRecipes.integrationTable.addRecipe(new GateLogicSwapRecipe(material, GateLogic.AND, GateLogic.OR));
BuildcraftRecipes.integrationTable.addRecipe(new GateLogicSwapRecipe(material, GateLogic.OR, GateLogic.AND));
}
// EXPANSIONS // EXPANSIONS
BuildcraftRecipes.integrationTable.addRecipe(new GateExpansionRecipe(GateExpansionPulsar.INSTANCE, Chipset.PULSATING.getStack())); BuildcraftRecipes.integrationTable.addRecipe(new GateExpansionRecipe(GateExpansionPulsar.INSTANCE, Chipset.PULSATING.getStack()));

View file

@ -11,10 +11,10 @@ package buildcraft.core.recipes;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import buildcraft.api.recipes.IIntegrationRecipe;
import buildcraft.api.recipes.IIntegrationRecipeManager; import buildcraft.api.recipes.IIntegrationRecipeManager;
public class IntegrationRecipeManager implements IIntegrationRecipeManager { public class IntegrationRecipeManager implements IIntegrationRecipeManager {
public static final IntegrationRecipeManager INSTANCE = new IntegrationRecipeManager(); public static final IntegrationRecipeManager INSTANCE = new IntegrationRecipeManager();
private List<IIntegrationRecipe> integrationRecipes = new LinkedList<IIntegrationRecipe>(); private List<IIntegrationRecipe> integrationRecipes = new LinkedList<IIntegrationRecipe>();
@ -24,7 +24,7 @@ public class IntegrationRecipeManager implements IIntegrationRecipeManager {
} }
@Override @Override
public List<IIntegrationRecipe> getRecipes() { public List<? extends IIntegrationRecipe> getRecipes() {
return integrationRecipes; return integrationRecipes;
} }
} }

View file

@ -11,19 +11,12 @@ package buildcraft.core.robots;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import buildcraft.BuildCraftSilicon; import buildcraft.BuildCraftSilicon;
import buildcraft.api.recipes.IIntegrationRecipeManager.IIntegrationRecipe; import buildcraft.api.recipes.IIntegrationRecipe;
import buildcraft.core.ItemRobot; import buildcraft.core.ItemRobot;
import buildcraft.core.utils.NBTUtils; import buildcraft.core.utils.NBTUtils;
import buildcraft.silicon.ItemRedstoneBoard; import buildcraft.silicon.ItemRedstoneBoard;
public class RobotIntegrationRecipe implements IIntegrationRecipe { public class RobotIntegrationRecipe implements IIntegrationRecipe {
@Override
public double getEnergyCost() {
// return 10000;
return 100;
}
@Override @Override
public boolean isValidInputA(ItemStack inputA) { public boolean isValidInputA(ItemStack inputA) {
return inputA != null && inputA.getItem() instanceof ItemRobot; return inputA != null && inputA.getItem() instanceof ItemRobot;
@ -35,27 +28,11 @@ public class RobotIntegrationRecipe implements IIntegrationRecipe {
} }
@Override @Override
public ItemStack getOutputForInputs(ItemStack inputA, ItemStack inputB, ItemStack[] components) { public IntegrationResult integrate(ItemStack inputA, ItemStack inputB, ItemStack[] components) {
ItemStack robot = new ItemStack(BuildCraftSilicon.robotItem); ItemStack robot = new ItemStack(BuildCraftSilicon.robotItem);
NBTUtils.getItemData(robot).setTag("board", NBTUtils.getItemData(inputB)); NBTUtils.getItemData(robot).setTag("board", NBTUtils.getItemData(inputB));
return robot; return IntegrationResult.create(10000, robot);
} }
@Override
public ItemStack[] getComponents() {
return new ItemStack[0];
}
@Override
public ItemStack[] getExampleInputsA() {
return null;
}
@Override
public ItemStack[] getExampleInputsB() {
return null;
}
} }

View file

@ -15,7 +15,7 @@ import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.recipes.BuildcraftRecipes; import buildcraft.api.recipes.BuildcraftRecipes;
import buildcraft.api.recipes.IIntegrationRecipeManager.IIntegrationRecipe; import buildcraft.api.recipes.IIntegrationRecipe;
import buildcraft.core.inventory.ITransactor; import buildcraft.core.inventory.ITransactor;
import buildcraft.core.inventory.InventoryMapper; import buildcraft.core.inventory.InventoryMapper;
import buildcraft.core.inventory.SimpleInventory; import buildcraft.core.inventory.SimpleInventory;
@ -36,7 +36,7 @@ public class TileIntegrationTable extends TileLaserTableBase implements ISidedIn
private int tick = 0; private int tick = 0;
private SimpleInventory invRecipeOutput = new SimpleInventory(1, "integrationOutput", 64); private SimpleInventory invRecipeOutput = new SimpleInventory(1, "integrationOutput", 64);
private InventoryMapper invOutput = new InventoryMapper(inv, SLOT_OUTPUT, 1, false); private InventoryMapper invOutput = new InventoryMapper(inv, SLOT_OUTPUT, 1, false);
private IIntegrationRecipe currentRecipe; private IIntegrationRecipe.IntegrationResult integrationResult;
private boolean canCraft = false; private boolean canCraft = false;
public IInventory getRecipeOutput() { public IInventory getRecipeOutput() {
@ -51,35 +51,6 @@ public class TileIntegrationTable extends TileLaserTableBase implements ISidedIn
return components; return components;
} }
private boolean containsComponents(IIntegrationRecipe recipe) {
if (recipe == null) {
return false;
}
ItemStack[] components = recipe.getComponents();
if (components == null || components.length == 0) {
return true;
}
for (ItemStack stack : components) {
int found = 0;
for (int i = SLOT_OUTPUT + 1; i < 12; i++) {
ItemStack stack1 = inv.getStackInSlot(i);
if (stack1 != null) {
if (StackHelper.isMatchingItem(stack, stack1, true, false)) {
found += stack1.stackSize;
}
}
}
if (found == 0) {
return false;
}
}
return true;
}
@Override @Override
public void updateEntity() { public void updateEntity() {
super.updateEntity(); super.updateEntity();
@ -95,57 +66,58 @@ public class TileIntegrationTable extends TileLaserTableBase implements ISidedIn
canCraft = false; canCraft = false;
currentRecipe = findMatchingRecipe(); ItemStack inputA = inv.getStackInSlot(SLOT_INPUT_A);
ItemStack inputB = inv.getStackInSlot(SLOT_INPUT_B);
if (currentRecipe == null) { ItemStack[] components = getComponents();
integrationResult = integrate(inputA, inputB, components);
if (integrationResult == null || integrationResult.output == null) {
setEnergy(0); setEnergy(0);
return; return;
} }
ItemStack inputA = inv.getStackInSlot(SLOT_INPUT_A); invRecipeOutput.setInventorySlotContents(0, integrationResult.output);
ItemStack inputB = inv.getStackInSlot(SLOT_INPUT_B);
ItemStack[] components = getComponents();
ItemStack output = currentRecipe.getOutputForInputs(inputA, inputB, components);
invRecipeOutput.setInventorySlotContents(0, output);
if (!isRoomForOutput(output)) { if (!isRoomForOutput(integrationResult.output)) {
setEnergy(0); setEnergy(0);
return; return;
} }
canCraft = true; canCraft = true;
if (getEnergy() >= currentRecipe.getEnergyCost() && lastMode != ActionMachineControl.Mode.Off) { if (getEnergy() >= integrationResult.energyCost && lastMode != ActionMachineControl.Mode.Off) {
setEnergy(0); setEnergy(0);
inv.decrStackSize(SLOT_INPUT_A, 1); inv.decrStackSize(SLOT_INPUT_A, 1);
inv.decrStackSize(SLOT_INPUT_B, 1); inv.decrStackSize(SLOT_INPUT_B, 1);
// For each required component, loop through the component inventory // For each required component, loop through the component inventory
for (ItemStack stack : currentRecipe.getComponents()) { for (ItemStack stack : integrationResult.usedComponents) {
int decreased = 0;
for (int i = SLOT_OUTPUT + 1; i < 12; i++) { for (int i = SLOT_OUTPUT + 1; i < 12; i++) {
ItemStack stack1 = inv.getStackInSlot(i); ItemStack stack1 = inv.getStackInSlot(i);
if (stack1 != null) { if (stack1 != null) {
if (StackHelper.isMatchingItem(stack, stack1, true, false)) { if (StackHelper.isMatchingItem(stack, stack1, true, false)) {
inv.decrStackSize(i, 1); decreased += stack1.stackSize;
break; inv.decrStackSize(i, stack.stackSize - decreased);
} }
} }
if (decreased >= stack.stackSize) {
break;
}
} }
} }
ITransactor trans = Transactor.getTransactorFor(invOutput); ITransactor trans = Transactor.getTransactorFor(invOutput);
trans.add(output, ForgeDirection.UP, true); trans.add(integrationResult.output, ForgeDirection.UP, true);
} }
} }
private IIntegrationRecipe findMatchingRecipe() { private IIntegrationRecipe.IntegrationResult integrate(ItemStack inputA, ItemStack inputB, ItemStack[] components) {
ItemStack inputA = inv.getStackInSlot(SLOT_INPUT_A); IIntegrationRecipe.IntegrationResult result;
ItemStack inputB = inv.getStackInSlot(SLOT_INPUT_B);
for (IIntegrationRecipe recipe : BuildcraftRecipes.integrationTable.getRecipes()) { for (IIntegrationRecipe recipe : BuildcraftRecipes.integrationTable.getRecipes()) {
if (recipe.isValidInputA(inputA) && recipe.isValidInputB(inputB) && containsComponents(recipe)) { if (recipe.isValidInputA(inputA) && recipe.isValidInputB(inputB) &&
return recipe; (result = recipe.integrate(inputA, inputB, components)) != null) {
return result;
} }
} }
return null; return null;
@ -164,8 +136,8 @@ public class TileIntegrationTable extends TileLaserTableBase implements ISidedIn
@Override @Override
public double getRequiredEnergy() { public double getRequiredEnergy() {
if (currentRecipe != null) { if (integrationResult != null) {
return currentRecipe.getEnergyCost(); return integrationResult.energyCost;
} }
return 0.0; return 0.0;
} }
@ -238,6 +210,7 @@ public class TileIntegrationTable extends TileLaserTableBase implements ISidedIn
@Override @Override
public boolean isActive() { public boolean isActive() {
return currentRecipe != null && super.isActive(); return integrationResult != null && super.isActive();
} }
} }

View file

@ -14,18 +14,14 @@ import net.minecraftforge.oredict.OreDictionary;
import buildcraft.BuildCraftTransport; import buildcraft.BuildCraftTransport;
import buildcraft.api.core.JavaTools; import buildcraft.api.core.JavaTools;
import buildcraft.api.recipes.IIntegrationRecipeManager; import buildcraft.api.recipes.IIntegrationRecipe;
import buildcraft.api.transport.PipeWire; import buildcraft.api.transport.PipeWire;
import buildcraft.silicon.ItemRedstoneChipset; import buildcraft.silicon.ItemRedstoneChipset;
import buildcraft.transport.ItemFacade; import buildcraft.transport.ItemFacade;
import buildcraft.transport.ItemPipeWire; import buildcraft.transport.ItemPipeWire;
public class AdvancedFacadeRecipe implements IIntegrationRecipeManager.IIntegrationRecipe { public class AdvancedFacadeRecipe implements IIntegrationRecipe {
private final ItemStack[] requiredComponents = new ItemStack[] {new ItemStack(BuildCraftTransport.pipeWire, 1, OreDictionary.WILDCARD_VALUE), ItemRedstoneChipset.Chipset.RED.getStack()};
@Override
public double getEnergyCost() {
return 2500;
}
@Override @Override
public boolean isValidInputA(ItemStack inputA) { public boolean isValidInputA(ItemStack inputA) {
@ -39,12 +35,8 @@ public class AdvancedFacadeRecipe implements IIntegrationRecipeManager.IIntegrat
} }
@Override @Override
public ItemStack getOutputForInputs(ItemStack inputA, ItemStack inputB, ItemStack[] components) { public IntegrationResult integrate(ItemStack inputA, ItemStack inputB, ItemStack[] components) {
if (!isValidInputA(inputA)) { if (!IntegrationResult.enoughComponents(components, requiredComponents)) {
return null;
}
if (!isValidInputB(inputB)) {
return null; return null;
} }
@ -57,6 +49,7 @@ public class AdvancedFacadeRecipe implements IIntegrationRecipeManager.IIntegrat
} }
} }
if (wire != null) { if (wire != null) {
ItemFacade.FacadeState[] states = ItemFacade.getFacadeStates(inputA); ItemFacade.FacadeState[] states = ItemFacade.getFacadeStates(inputA);
ItemFacade.FacadeState additionalState; ItemFacade.FacadeState additionalState;
@ -71,30 +64,13 @@ public class AdvancedFacadeRecipe implements IIntegrationRecipeManager.IIntegrat
for (int i = 0; i < states.length; i++) { for (int i = 0; i < states.length; i++) {
if (states[i].wire == wire) { if (states[i].wire == wire) {
states[i] = additionalState; states[i] = additionalState;
return ItemFacade.getFacade(states); return IntegrationResult.create(2000, ItemFacade.getFacade(states), requiredComponents);
} }
} }
// otherwise concat all states into one facade // otherwise concat all states into one facade
return ItemFacade.getFacade(JavaTools.concat(states, new ItemFacade.FacadeState[] {additionalState})); return IntegrationResult.create(5000, ItemFacade.getFacade(JavaTools.concat(states, new ItemFacade.FacadeState[] {additionalState})), requiredComponents);
} else { } else {
return null; return null;
} }
} }
@Override
public ItemStack[] getComponents() {
// Any pipe wire and redstone chipset
return new ItemStack[] {new ItemStack(BuildCraftTransport.pipeWire, 1, OreDictionary.WILDCARD_VALUE), ItemRedstoneChipset.Chipset.RED.getStack()};
}
@Override
public ItemStack[] getExampleInputsA() {
return new ItemStack[0];
}
@Override
public ItemStack[] getExampleInputsB() {
return new ItemStack[0];
}
} }

View file

@ -10,7 +10,7 @@ package buildcraft.silicon.recipes;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import buildcraft.api.gates.IGateExpansion; import buildcraft.api.gates.IGateExpansion;
import buildcraft.api.recipes.IIntegrationRecipeManager.IIntegrationRecipe; import buildcraft.api.recipes.IIntegrationRecipe;
import buildcraft.core.inventory.StackHelper; import buildcraft.core.inventory.StackHelper;
import buildcraft.transport.gates.ItemGate; import buildcraft.transport.gates.ItemGate;
@ -18,19 +18,10 @@ public class GateExpansionRecipe implements IIntegrationRecipe {
private final IGateExpansion expansion; private final IGateExpansion expansion;
private final ItemStack chipset; private final ItemStack chipset;
private final ItemStack[] exampleA;
private final ItemStack[] exampleB;
public GateExpansionRecipe(IGateExpansion expansion, ItemStack chipset) { public GateExpansionRecipe(IGateExpansion expansion, ItemStack chipset) {
this.expansion = expansion; this.expansion = expansion;
this.chipset = chipset.copy(); this.chipset = chipset.copy();
exampleA = ItemGate.getGateVarients();
exampleB = new ItemStack[]{chipset};
}
@Override
public double getEnergyCost() {
return 10000;
} }
@Override @Override
@ -50,31 +41,10 @@ public class GateExpansionRecipe implements IIntegrationRecipe {
} }
@Override @Override
public ItemStack getOutputForInputs(ItemStack inputA, ItemStack inputB, ItemStack[] components) { public IntegrationResult integrate(ItemStack inputA, ItemStack inputB, ItemStack[] components) {
if (!isValidInputA(inputA)) {
return null;
}
if (!isValidInputB(inputB)) {
return null;
}
ItemStack output = inputA.copy(); ItemStack output = inputA.copy();
output.stackSize = 1; output.stackSize = 1;
ItemGate.addGateExpansion(output, expansion); ItemGate.addGateExpansion(output, expansion);
return output; return IntegrationResult.create(10000, output);
}
@Override
public ItemStack[] getComponents() {
return new ItemStack[0];
}
@Override
public ItemStack[] getExampleInputsA() {
return exampleA;
}
@Override
public ItemStack[] getExampleInputsB() {
return exampleB;
} }
} }

View file

@ -9,7 +9,8 @@
package buildcraft.silicon.recipes; package buildcraft.silicon.recipes;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import buildcraft.api.recipes.IIntegrationRecipeManager.IIntegrationRecipe;
import buildcraft.api.recipes.IIntegrationRecipe;
import buildcraft.core.inventory.StackHelper; import buildcraft.core.inventory.StackHelper;
import buildcraft.silicon.ItemRedstoneChipset; import buildcraft.silicon.ItemRedstoneChipset;
import buildcraft.transport.gates.GateDefinition.GateLogic; import buildcraft.transport.gates.GateDefinition.GateLogic;
@ -17,75 +18,21 @@ import buildcraft.transport.gates.GateDefinition.GateMaterial;
import buildcraft.transport.gates.ItemGate; import buildcraft.transport.gates.ItemGate;
public class GateLogicSwapRecipe implements IIntegrationRecipe { public class GateLogicSwapRecipe implements IIntegrationRecipe {
private final GateMaterial material;
private final GateLogic logicIn, logicOut;
private final ItemStack chipset;
private final ItemStack[] exampleA;
private final ItemStack[] exampleB;
public GateLogicSwapRecipe(GateMaterial material, GateLogic logicIn, GateLogic logicOut) {
this.material = material;
this.logicIn = logicIn;
this.logicOut = logicOut;
this.chipset = ItemRedstoneChipset.Chipset.RED.getStack();
exampleA = new ItemStack[]{ItemGate.makeGateItem(material, logicIn)};
exampleB = new ItemStack[]{chipset};
}
@Override
public double getEnergyCost() {
return 2000;
}
@Override @Override
public boolean isValidInputA(ItemStack inputA) { public boolean isValidInputA(ItemStack inputA) {
if (inputA == null) { return inputA != null && inputA.getItem() instanceof ItemGate && ItemGate.getMaterial(inputA) != GateMaterial.REDSTONE;
return false;
}
if (!(inputA.getItem() instanceof ItemGate)) {
return false;
}
if (ItemGate.getMaterial(inputA) != material) {
return false;
}
if (ItemGate.getLogic(inputA) != logicIn) {
return false;
}
return true;
} }
@Override @Override
public boolean isValidInputB(ItemStack inputB) { public boolean isValidInputB(ItemStack inputB) {
return StackHelper.isMatchingItem(inputB, chipset); return StackHelper.isMatchingItem(inputB, ItemRedstoneChipset.Chipset.RED.getStack());
} }
@Override @Override
public ItemStack getOutputForInputs(ItemStack inputA, ItemStack inputB, ItemStack[] components) { public IntegrationResult integrate(ItemStack inputA, ItemStack inputB, ItemStack[] components) {
if (!isValidInputA(inputA)) {
return null;
}
if (!isValidInputB(inputB)) {
return null;
}
ItemStack output = inputA.copy(); ItemStack output = inputA.copy();
output.stackSize = 1; output.stackSize = 1;
ItemGate.setLogic(output, logicOut); ItemGate.setLogic(output, ItemGate.getLogic(output) == GateLogic.AND ? GateLogic.OR : GateLogic.AND);
return output; return IntegrationResult.create(2000, output);
}
@Override
public ItemStack[] getComponents() {
return new ItemStack[0];
}
@Override
public ItemStack[] getExampleInputsA() {
return exampleA;
}
@Override
public ItemStack[] getExampleInputsB() {
return exampleB;
} }
} }