diff --git a/html/script/crafting.js b/html/script/crafting.js
index 4603e80fc..66370e30c 100644
--- a/html/script/crafting.js
+++ b/html/script/crafting.js
@@ -60,7 +60,7 @@ function onCraftingSelectorChanged() {
if (! hasRecipe(recipeName)) {
$("#crafting_output").slideUp(SLIDE_DURATION);
} else {
- var plan = createCraftingPlan(count, recipeName);
+ var plan = createCraftingPlan(count, recipeName, __toolsIncluded);
var result = createCraftingResult(__inventory);
plan.alternatives[0].craft(result);
@@ -214,16 +214,19 @@ function updatePageState(count, recipeName) {
// Crafting Node Object ///////////////////////////////////////////////////////////////////////////////////////////////
-function createCraftingNode(count, recipeName, alternatives, recipeBooks) {
+function createCraftingNode(count, recipeName, shouldIncludeTools, alternatives, recipeBooks) {
+ if (shouldIncludeTools !== true) shouldIncludeTools = false;
if (recipeBooks === undefined) recipeBooks = __recipeBooks;
var object = {
alternatives: [],
children: [],
count: count,
+ isToolNode: false,
name: recipeName,
parentNode: undefined,
- recipe: undefined
+ recipe: undefined,
+ shouldIncludeTools: shouldIncludeTools
};
if (count !== undefined) {
@@ -234,9 +237,20 @@ function createCraftingNode(count, recipeName, alternatives, recipeBooks) {
object.recipe = alternatives.shift();
object.alternatives = alternatives;
+ if (shouldIncludeTools) {
+ for (var i = 0; i < object.recipe.tools.length; i++) {
+ var tool = object.recipe.tools[i];
+ var node = createCraftingNode(1, tool, shouldIncludeTools, undefined, recipeBooks);
+ if (node) {
+ node.isToolNode = true;
+ node.parentNode = object;
+ object.children.push(node);
+ }
+ }
+ }
for (var i = 0; i < object.recipe.input.length; i++) {
var input = object.recipe.input[i];
- var node = createCraftingNode(input.count, input.name, undefined, recipeBooks);
+ var node = createCraftingNode(input.count, input.name, shouldIncludeTools, undefined, recipeBooks);
if (node) {
node.parentNode = object;
object.children.push(node);
@@ -248,9 +262,11 @@ function createCraftingNode(count, recipeName, alternatives, recipeBooks) {
var result = createCraftingNode();
result.alternatives = object.alternatives.copy();
result.count = object.count;
+ result.isToolNode = object.isToolNode;
result.name = object.name;
result.parentNode = undefined;
result.recipe = object.recipe.copy();
+ result.shouldIncludeTools = object.shouldIncludeTools;
result.children = object.children.copy();
for (var i = 0; i < result.children.length; i++) {
@@ -260,15 +276,16 @@ function createCraftingNode(count, recipeName, alternatives, recipeBooks) {
return result;
};
- object.craft = function(craftingResult, isCraftingChild) {
+ object.craft = function(craftingResult) {
+ if (shouldIncludeTools !== true) shouldIncludeTools = false;
if (craftingResult === undefined) {
craftingResult = createCraftingResult();
}
var shouldContinueCrafting = function() {
- if (isCraftingChild === true) {
- return craftingResult.missingMaterials.contains(1, object.name);
- } else {
+ if (object.parentNode === undefined || object.isToolNode) {
return ! craftingResult.inventory.contains(object.count, object.name);
+ } else {
+ return craftingResult.missingMaterials.contains(1, object.name);
}
}
@@ -277,6 +294,16 @@ function createCraftingNode(count, recipeName, alternatives, recipeBooks) {
if (count++ > 100000) {
throw "Too many iterations";
}
+ if (object.shouldIncludeTools) {
+ for (var i = 0; i < object.recipe.tools; i++) {
+ var tool = object.recipe.tools[i];
+ var hasTool = craftingResult.inventory.contains(1, tool) ||
+ craftingResult.missingMaterials.contains(1, tool);
+ if (! hasTool) {
+ craftingResult.addMissingMaterial(tool);
+ }
+ }
+ }
for (var i = 0; i < object.recipe.input.length; i++) {
var input = object.recipe.input[i];
for (var j = 0; j < input.count; j++) {
@@ -294,9 +321,9 @@ function createCraftingNode(count, recipeName, alternatives, recipeBooks) {
}
for (var i = 0; i < object.children.length; i++) {
var child = object.children[i];
- child.craft(craftingResult, true);
+ child.craft(craftingResult);
}
- if (isCraftingChild !== true) {
+ if (object.parentNode === undefined) {
craftingResult.sortStepsBy(object);
}
return craftingResult;
@@ -305,7 +332,8 @@ function createCraftingNode(count, recipeName, alternatives, recipeBooks) {
object.createNextAlternative = function(recipeBooks) {
if (recipeBooks === undefined) recipeBooks = __recipeBooks;
if (object.alternatives.length === 0) return undefined;
- var nextAlternative = createCraftingNode(object.count, object.name, object.alternatives, recipeBooks);
+ var nextAlternative = createCraftingNode(
+ object.count, object.name, object.shouldIncludeTools, object.alternatives, recipeBooks);
object.alternatives = [];
return nextAlternative;
};
@@ -365,7 +393,8 @@ function createCraftingNode(count, recipeName, alternatives, recipeBooks) {
// Crafting Plan Object ///////////////////////////////////////////////////////////////////////////////////////////////
-function createCraftingPlan(count, recipeName, recipeBooks) {
+function createCraftingPlan(count, recipeName, shouldIncludeTools, recipeBooks) {
+ if (shouldIncludeTools !== true) shouldIncludeTools = false;
if (recipeBooks === undefined) recipeBooks = __recipeBooks;
var object = {
@@ -374,7 +403,7 @@ function createCraftingPlan(count, recipeName, recipeBooks) {
alternatives: []
};
- var nodesToProcess = [ createCraftingNode(count, recipeName, undefined, recipeBooks) ];
+ var nodesToProcess = [ createCraftingNode(count, recipeName, shouldIncludeTools, undefined, recipeBooks) ];
while (nodesToProcess.length > 0) {
var node = nodesToProcess.shift();
var choiceNode = node.findNodeWithAlternatives();
diff --git a/html/script/test.js b/html/script/test.js
index 5ecbb0b19..ecc13cfe7 100644
--- a/html/script/test.js
+++ b/html/script/test.js
@@ -176,7 +176,7 @@ test("Array.copy", function() {
module("CraftingNode"); ///////////////////////////////////////////////////////////////////////////////////////////////
test("create: simple", function() {
- var node = createCraftingNode(12, "Furnace", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(12, "Furnace", false, undefined, __sampleRecipeBooks);
deepEqual(node.alternatives.length, 0);
deepEqual(node.children.length, 0);
deepEqual(node.count, 12);
@@ -186,7 +186,7 @@ test("create: simple", function() {
});
test("create: complex", function() {
- var node = createCraftingNode(1, "Iron Gear", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Iron Gear", false, undefined, __sampleRecipeBooks);
deepEqual(node.name, "Iron Gear");
deepEqual(node.children.length, 2);
deepEqual(node.children[0].name, "Iron Ingot");
@@ -215,8 +215,16 @@ test("create: complex", function() {
deepEqual(node.children, []);
});
+test("create: with tool", function() {
+ var node = createCraftingNode(1, "Iron Ingot", true, undefined, __sampleRecipeBooks);
+ deepEqual(node.alternatives.length, 0, JSON.stringify(node.alternatives));
+ deepEqual(node.children.length, 1);
+ deepEqual(node.children[0].name, "Furnace");
+ deepEqual(node.name, "Iron Ingot");
+});
+
test("craft: simple", function() {
- var node = createCraftingNode(1, "Furnace", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Furnace", false, undefined, __sampleRecipeBooks);
var result = node.craft();
deepEqual(result.inventory.materials["Furnace"], 1);
@@ -227,7 +235,7 @@ test("craft: simple", function() {
deepEqual(result.stepList[0].count, 1);
deepEqual(result.stepList[0].name, "Furnace");
- node = createCraftingNode(2, "Furnace", undefined, __sampleRecipeBooks);
+ node = createCraftingNode(2, "Furnace", false, undefined, __sampleRecipeBooks);
result = node.craft();
deepEqual(result.inventory.materials["Furnace"], 2, JSON.stringify(result.inventory));
@@ -245,7 +253,7 @@ test("craft: with initial inventory", function() {
var inventory = createManifest();
inventory.add(4, "Cobblestone");
var result = createCraftingResult(inventory);
- var node = createCraftingNode(2, "Furnace", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(2, "Furnace", false, undefined, __sampleRecipeBooks);
node.craft(result);
deepEqual(result.inventory.materials["Furnace"], 2);
@@ -261,7 +269,7 @@ test("craft: no-op", function() {
var inventory = createManifest();
inventory.add(1, "Furnace");
var result = createCraftingResult(inventory);
- var node = createCraftingNode(1, "Furnace", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Furnace", false, undefined, __sampleRecipeBooks);
node.craft(result);
deepEqual(result.inventory.materials["Furnace"], 1, JSON.stringify(result.inventory));
@@ -271,7 +279,7 @@ test("craft: no-op", function() {
});
test("craft: deep tree", function() {
- var node = createCraftingNode(1, "Iron Gear", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Iron Gear", false, undefined, __sampleRecipeBooks);
var result = node.craft();
deepEqual(result.inventory.materials["Iron Gear"], 1);
@@ -300,7 +308,7 @@ test("craft: deep tree", function() {
});
test("craft: repeatedly craft ingredient", function() {
- var node = createCraftingNode(1, "Bookshelf", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Bookshelf", false, undefined, __sampleRecipeBooks);
var result = node.craft();
deepEqual(result.inventory.materials["Bookshelf"], 1, JSON.stringify(result.inventory));
@@ -324,7 +332,7 @@ test("craft: repeatedly craft ingredient", function() {
});
test("craft: same item used multiple places", function() {
- var node = createCraftingNode(1, "Mining Well", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Mining Well", false, undefined, __sampleRecipeBooks);
var result = node.craft();
deepEqual(result.inventory.materials["Mining Well"], 1, JSON.stringify(result.inventory));
@@ -357,9 +365,26 @@ test("craft: same item used multiple places", function() {
deepEqual(result.stepList.length, 8, JSON.stringify(result.stepList));
});
+test("craft: multiple tools needed", function() {
+ var node = createCraftingNode(1, "Iron Pickaxe", true, undefined, __sampleRecipeBooks);
+ var result = node.craft();
+
+ deepEqual(result.inventory.materials["Iron Pickaxe"], 1, JSON.stringify(result.inventory));
+ deepEqual(result.inventory.materials["Birch Plank"], 2, JSON.stringify(result.inventory));
+ deepEqual(result.inventory.materials["Stick"], 2, JSON.stringify(result.inventory));
+ deepEqual(result.inventory.materials["Furnace"], 1, JSON.stringify(result.inventory));
+ deepEqual(result.inventory.materials["Crafting Table"], 1, JSON.stringify(result.inventory));
+ deepEqual(result.inventory.length, 5, JSON.stringify(result.inventory));
+
+ deepEqual(result.missingMaterials.materials["Birch Log"], 2, JSON.stringify(result.missingMaterials));
+ deepEqual(result.missingMaterials.materials["Iron Ore"], 3, JSON.stringify(result.missingMaterials));
+ deepEqual(result.missingMaterials.materials["Cobblestone"], 8, JSON.stringify(result.missingMaterials));
+ deepEqual(result.missingMaterials.materials["milli-coal"], 375, JSON.stringify(result.missingMaterials));
+ deepEqual(result.missingMaterials.length, 4, JSON.stringify(result.missingMaterials));
+});
test("copy", function() {
- var node = createCraftingNode(3, "Stick", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(3, "Stick", false, undefined, __sampleRecipeBooks);
var copiedNode = node.copy();
deepEqual(copiedNode.alternatives.length, 2);
@@ -372,7 +397,7 @@ test("copy", function() {
});
test("createNextAlternative", function() {
- var node = createCraftingNode(1, "Stick", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Stick", false, undefined, __sampleRecipeBooks);
deepEqual(node.alternatives.length, 2);
var firstAlternate = node.createNextAlternative(__sampleRecipeBooks);
@@ -395,7 +420,7 @@ test("createNextAlternative", function() {
});
test("depthFirstTraversal", function() {
- var node = createCraftingNode(1, "Iron Gear", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Iron Gear", false, undefined, __sampleRecipeBooks);
var expectedNames = ["Iron Ingot", "Birch Plank", "Stick", "Wooden Gear", "Stone Gear", "Iron Gear"];
var names = [];
@@ -404,17 +429,17 @@ test("depthFirstTraversal", function() {
});
test("findNodeWithAlternatives", function() {
- var node = createCraftingNode(1, "Iron Gear", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Iron Gear", false, undefined, __sampleRecipeBooks);
var nodeWithAlternatives = node.findNodeWithAlternatives();
deepEqual(nodeWithAlternatives.name, "Stick");
- node = createCraftingNode(1, "Stick", undefined, __sampleRecipeBooks);
+ node = createCraftingNode(1, "Stick", false, undefined, __sampleRecipeBooks);
nodeWithAlternatives = node.findNodeWithAlternatives();
deepEqual(nodeWithAlternatives.name, "Stick");
});
test("getNodeAt", function() {
- var node = createCraftingNode(1, "Electronic Circuit", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Electronic Circuit", false, undefined, __sampleRecipeBooks);
deepEqual(node.getNodeAt([0]).name, "Insulated Copper Cable");
deepEqual(node.getNodeAt([1]).name, "Refined Iron");
deepEqual(node.getNodeAt([0, 0]).name, "Copper Cable");
@@ -423,7 +448,7 @@ test("getNodeAt", function() {
});
test("getPosition", function() {
- var node = createCraftingNode(1, "Electronic Circuit", undefined, __sampleRecipeBooks);
+ var node = createCraftingNode(1, "Electronic Circuit", false, undefined, __sampleRecipeBooks);
deepEqual(node.getNodeAt([0]).getPosition(), [0]);
deepEqual(node.getNodeAt([1]).getPosition(), [1]);
deepEqual(node.getNodeAt([0, 0]).getPosition(), [0, 0]);
@@ -432,8 +457,8 @@ test("getPosition", function() {
});
test("setNodeAt", function() {
- var ironGearNode = createCraftingNode(1, "Iron Gear", undefined, __sampleRecipeBooks);
- var furnaceNode = createCraftingNode(1, "Furnace", undefined, __sampleRecipeBooks);
+ var ironGearNode = createCraftingNode(1, "Iron Gear", false, undefined, __sampleRecipeBooks);
+ var furnaceNode = createCraftingNode(1, "Furnace", false, undefined, __sampleRecipeBooks);
ironGearNode.setNodeAt([1, 0, 0], furnaceNode);
deepEqual(ironGearNode.children[1].children[0].children[0].name, "Furnace");
@@ -443,7 +468,7 @@ test("setNodeAt", function() {
module("CraftingPlan"); ///////////////////////////////////////////////////////////////////////////////////////////////
test("create: single complex plan", function() {
- var plan = createCraftingPlan(1, "Electronic Circuit", __sampleRecipeBooks);
+ var plan = createCraftingPlan(1, "Electronic Circuit", false, __sampleRecipeBooks);
deepEqual(plan.count, 1);
deepEqual(plan.recipeName, "Electronic Circuit");
deepEqual(plan.alternatives.length, 1);
@@ -451,7 +476,7 @@ test("create: single complex plan", function() {
});
test("create: multiple simple plans", function() {
- var plan = createCraftingPlan(1, "Stick", __sampleRecipeBooks);
+ var plan = createCraftingPlan(1, "Stick", false, __sampleRecipeBooks);
deepEqual(plan.count, 1);
deepEqual(plan.recipeName, "Stick");
deepEqual(plan.alternatives[0].recipe.input[0].name, "Birch Plank");
@@ -461,7 +486,7 @@ test("create: multiple simple plans", function() {
});
test("create: multiple complex plans", function() {
- var plan = createCraftingPlan(1, "Iron Gear", __sampleRecipeBooks);
+ var plan = createCraftingPlan(1, "Iron Gear", false, __sampleRecipeBooks);
var firstResult = plan.alternatives[0].craft();
var secondResult = plan.alternatives[1].craft();
var thirdResult = plan.alternatives[2].craft();