Add support for conditional recipes

This commit is contained in:
Andrew Miner
2015-05-20 18:07:39 -07:00
parent c41d531d57
commit 06eea0aa48
5 changed files with 87 additions and 4 deletions
+2
View File
@@ -144,6 +144,8 @@ module.exports = class ModVersion extends BaseModel
otherRecipes = []
for recipe in _.values @_recipes
continue unless recipe.isConditionSatisfied()
if recipe.itemSlug.matches itemSlug
primaryRecipes.push recipe
else if recipe.produces itemSlug
@@ -70,6 +70,21 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
for name in inputNames
@_recipeData.input.push @_parseStack name
_command_onlyIf: (condition)->
words = condition.split ' '
if words.length < 2 then throw new Error 'condition must include a verb followed by a noun'
inverted = false
if words[0] is 'not'
inverted = true
words.shift()
verb = words[0]
noun = words[1..].join ' '
if not (verb in ['item', 'mod']) then throw new Error "unknown verb: #{verb}"
@_recipeData.condition = verb:verb, noun:noun, inverted:inverted
_command_pattern: (pattern='')->
if not @_recipeData? then throw new Error 'cannot declare "pattern" before "recipe"'
if @_recipeData.pattern? then throw new Error 'duplicate declaration of "pattern"'
@@ -155,10 +170,11 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
if not recipeData.pattern? then throw new Error 'the "pattern" declaration is required'
recipe = new Recipe
input: @_buildStackList modVersion, recipeData.input, recipeData.pattern
output: @_buildStackList modVersion, recipeData.output
pattern: recipeData.pattern
tools: @_buildStackList modVersion, recipeData.tools
condition: recipeData.condition
input: @_buildStackList modVersion, recipeData.input, recipeData.pattern
output: @_buildStackList modVersion, recipeData.output
pattern: recipeData.pattern
tools: @_buildStackList modVersion, recipeData.tools
modVersion.addRecipe recipe
return recipe
@@ -274,6 +290,10 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
builder
.line 'recipe:'
.indent()
.onlyIf recipe.condition?, =>
builder.push 'onlyIf: '
.onlyIf recipe.condition.inverted, -> builder.push 'not '
.line recipe.condition.verb, ' ', recipe.condition.noun
.onlyIf extraOutputs.length > 0, =>
builder
.push 'extras: '
+17
View File
@@ -28,6 +28,7 @@ module.exports = class Recipe extends BaseModel
attributes.pattern = @_parsePattern attributes.pattern
attributes.condition ?= null
attributes.modVersion ?= null
attributes.tools ?= []
options.logEvents ?= false
@@ -114,6 +115,22 @@ module.exports = class Recipe extends BaseModel
return total
isConditionSatisfied: (modPack)->
return true unless @condition
modPack ?= @modVersion?.mod?.modPack
result = false
if @condition.verb is 'item'
if modPack?.findItemByName(@condition.noun)?
result = true
else if @condition.verb is 'mod'
modPack.eachMod (mod)->
if mod.name is @condition.noun
result = true
if @condition.inverted then result = not result
return result
isPassThroughFor: (itemSlug)->
amountCreated = 0
for stack in @output
+5
View File
@@ -87,6 +87,7 @@ describe 'mod_version.coffee', ->
item: Cake
recipe:; input: Milk, Sugar, Egg, Wheat; pattern: 000 121 333; extras: 3 Bucket
recipe:; input: Milk, Cocoa Beans, Egg, Wheat; pattern: 000 121 333; extras: 3 Bucket
recipe:; input: Cake Slice; pattern: 000 000 000; onlyIf: item Cake Slice
item: Bucket
recipe:; input: Iron Ingot; pattern: ... 0.0 .0.
"""
@@ -94,3 +95,7 @@ describe 'mod_version.coffee', ->
it 'finds all recipes which list item as output', ->
recipes = modVersion.findRecipes ItemSlug.slugify('test__bucket')
(r.output[0].itemSlug.item for r in recipes).sort().should.eql ['bucket', 'cake', 'cake']
it 'skip recipes whose conditions are not met', ->
recipes = modVersion.findRecipes ItemSlug.slugify 'test__cake'
recipes.length.should.equal 2
@@ -158,6 +158,40 @@ describe 'mod_version_parser_v1.coffee', ->
func = -> parser.parse 'item:Bravo; quantity:12; recipe:;'
expect(func).to.throw Error, 'cannot declare "quantity" before "recipe"'
describe 'onlyIf', ->
beforeEach ->
baseText = 'item: Charlie; recipe:; input:Alpha; pattern:...0.0...; '
it 'understands the "item" verb', ->
modVersion = parser.parse baseText + 'onlyIf: item Iron Ingot'
recipes = []
modVersion.eachRecipe (recipe)-> recipes.push recipe
recipe = recipes[0]
recipe.condition.should.eql verb:'item', noun:'Iron Ingot', inverted:false
it 'understands the "mod" verb', ->
modVersion = parser.parse baseText + 'onlyIf: mod BuildCraft'
recipes = []
modVersion.eachRecipe (recipe)-> recipes.push recipe
recipe = recipes[0]
recipe.condition.should.eql verb:'mod', noun:'BuildCraft', inverted:false
it 'understands inverting verbs', ->
modVersion = parser.parse baseText + 'onlyIf: not item Iron Ingot'
recipes = []
modVersion.eachRecipe (recipe)-> recipes.push recipe
recipe = recipes[0]
recipe.condition.should.eql verb:'item', noun:'Iron Ingot', inverted:true
it 'requires at least two words', ->
func = -> parser.parse baseText + 'onlyIf: item'
expect(func).to.throw Error, 'verb followed by a noun'
it 'only allows known verbs', ->
func = -> parser.parse baseText + 'onlyIf: foo Iron Ingot'
expect(func).to.throw Error, 'unknown verb'
describe 'output', ->
beforeEach ->
@@ -250,6 +284,11 @@ describe 'mod_version_parser_v1.coffee', ->
input: furnace fuel, Iron Dust
pattern: .1. ... .0.
tools: Furnace
recipe:
onlyIf: item Redstone Furnace
input: Iron Ore
pattern: ... .0. ...
tools: Redstone Furnace
"""
it 'can round-trip a data file', ->