diff --git a/src/data/industrial_craft_2/experimental-2.2.663/mod-version.cg b/src/data/industrial_craft_2/experimental-2.2.663/mod-version.cg index 63313e747..0b9efb492 100644 --- a/src/data/industrial_craft_2/experimental-2.2.663/mod-version.cg +++ b/src/data/industrial_craft_2/experimental-2.2.663/mod-version.cg @@ -3259,3 +3259,16 @@ group: Tools: Painters input: Dandelion Yellow, Painter pattern: ... 10. ... +update: Iron Ingot + recipe: + input: Crushed Iron Ore, furnace fuel + pattern: .0. ... .1. + tools: Furnace + recipe: + input: Purified Crushed Iron Ore, furnace fuel + pattern: .0. ... .1. + tools: Furnace + recipe: + input: Iron Dust, furnace fuel + pattern: .0. ... .1. + tools: Furnace diff --git a/src/scripts/item_slug.coffee b/src/scripts/item_slug.coffee new file mode 100644 index 000000000..31bf2ba5f --- /dev/null +++ b/src/scripts/item_slug.coffee @@ -0,0 +1,74 @@ +### +Crafting Guide - item_slug.coffee + +Copyright (c) 2015 by Redwood Labs +All rights reserved. +### + +######################################################################################################################## + +module.exports = class ItemSlug + + constructor: -> + @_item = @_mod = null + if arguments.length is 1 + @item = arguments[0] + else if arguments.length is 2 + @_mod = arguments[0] + @item = arguments[1] + else + throw new Error 'expected arguments to be "modSlug, itemSlug" or just "itemSlug"' + + # Class Methods ################################################################################ + + DELIMITER = '__' + + @compare: (a, b)-> + if a.isQualified isnt b.isQualified + return -1 if a.isQualified + return +1 if b.isQualified + else if a.mod isnt b.mod + return if a.mod < b.mod then -1 else +1 + else if a.item isnt b.item + return if a.item < b.item then -1 else +1 + + return 0 + + @equals: (a, b)-> + return false unless a.mod is b.mod + return false unless a.item is b.item + return true + + # Property Methods ############################################################################# + + Object.defineProperties @prototype, + isQualified: { get:@prototype.isQualified } + mod: { get:@prototype.getMod, set:@prototype.setMod } + item: { get:@prototype.getItem, set:@prototype.setItem } + qualified: { get:@prototype.getQualified set:@prototype.setQualified } + + getItem: -> + return @_item + + setItem: (item)-> + if not item? then throw new Error 'item is required' + @_item = item + @mod = mod + + getMod: -> + return @_mod + + setMod: (mod)-> + @_qualified = if mod? then "#{@mod}#{ItemSlug.DELIMITER}#{@item}" else @item + @_mod = mod + + isQualified: -> + return @_mod? + + # Object Overrides ############################################################################# + + toString: -> + return @_qualified + + valueOf: -> + return @_qualified.valueOf() diff --git a/src/scripts/models/item_page.coffee b/src/scripts/models/item_page.coffee index 7709099b7..3b8266a13 100644 --- a/src/scripts/models/item_page.coffee +++ b/src/scripts/models/item_page.coffee @@ -56,9 +56,7 @@ module.exports = class ItemPage extends BaseModel return result findRecipes: -> - result = @modPack.findRecipes @item?.qualifiedSlug - return null unless result.length > 0 - return result + return @modPack.findRecipes @item?.slug # Private Methods ############################################################################## diff --git a/src/scripts/models/mod_version.coffee b/src/scripts/models/mod_version.coffee index 7d91ca634..1d1bab95a 100644 --- a/src/scripts/models/mod_version.coffee +++ b/src/scripts/models/mod_version.coffee @@ -101,7 +101,8 @@ module.exports = class ModVersion extends BaseModel return this findName: (slug)-> - return @_names[slug] + [modSlug, itemSlug] = _.decomposeSlug slug + return @_names[itemSlug] registerName: (slug, name)-> hasSlug = @_names[slug]? @@ -127,14 +128,24 @@ module.exports = class ModVersion extends BaseModel return this - findRecipes: (itemSlug, result=[])-> - recipeList = @_recipes[itemSlug] + findRecipes: (slug, result=[])-> + recipeList = @_recipes[slug] if recipeList? for recipe in recipeList result.push recipe return result + findExternalRecipes: -> + result = {} + for slug, recipeList of @_recipes + [modSlug, itemSlug] = _.decomposeSlug slug + logger.debug "checking: #{modSlug}, #{itemSlug}" + continue if @_items[itemSlug]? + logger.debug "external: #{recipeList}" + result[itemSlug] = recipeList[..] + return result + hasRecipes: (itemSlug)-> recipeList = @_recipes[itemSlug] return true if recipeList? and recipeList.length > 0 diff --git a/src/scripts/models/parser_versions/command_parser_version_base.coffee b/src/scripts/models/parser_versions/command_parser_version_base.coffee index acb0afa66..94b81c8f4 100644 --- a/src/scripts/models/parser_versions/command_parser_version_base.coffee +++ b/src/scripts/models/parser_versions/command_parser_version_base.coffee @@ -24,6 +24,15 @@ module.exports = class CommandParserVersionBase @COMMENT = /([^\\]?)#.*/ + @simplify: (text)-> + text = text.trim() + text = text.replace /\ */g , ' ' + text = text.replace /\n/g, ';' + text = text.replace /; */g, ';' + text = text.replace /;;*/g, ';' + text = text.replace /: /g, ':' + return text + # Public Methods ############################################################################### parse: (text)-> diff --git a/src/scripts/models/parser_versions/mod_version_parser_v1.coffee b/src/scripts/models/parser_versions/mod_version_parser_v1.coffee index 3cd7f22db..f6c4ca12f 100644 --- a/src/scripts/models/parser_versions/mod_version_parser_v1.coffee +++ b/src/scripts/models/parser_versions/mod_version_parser_v1.coffee @@ -60,7 +60,7 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase _command_item: (name='')-> if not name.length > 0 then throw new Error 'the item name cannot be empty' - @_itemData = name:name, line:@_lineNumber, group:@_rawData.group + @_itemData = name:name, line:@_lineNumber, group:@_rawData.group, type:'new' @_rawData.items ?= {} @_rawData.items[name] = @_itemData @@ -107,6 +107,15 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase if name.length is 0 then throw new Error 'tool names cannot be empty' @_recipeData.tools.push name + _command_update: (name='')-> + if not name.length > 0 then throw new 'the item name cannot be empty' + + @_itemData = name:name, line:@_lineNumber, type:'update' + @_recipeData = null + + @_rawData.items ?= {} + @_rawData.items[name] = @_itemData + # Object Creation Methods ###################################################################### _buildModVersion: (modVersionData, modVersion)-> @@ -122,24 +131,28 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase itemData.gatherable ?= false itemData.recipes ?= [] - item = new Item name:itemData.name, isGatherable:itemData.gatherable, group:itemData.group - modVersion.addItem item + if itemData.type is 'new' + item = new Item name:itemData.name, isGatherable:itemData.gatherable, group:itemData.group + modVersion.addItem item for recipeData in itemData.recipes - @_handleErrors @_buildRecipe, modVersion, item, recipeData + @_handleErrors @_buildRecipe, modVersion, itemData, recipeData return item - _buildRecipe: (modVersion, item, recipeData)-> + _buildRecipe: (modVersion, itemData, recipeData)-> @_lineNumber = recipeData.line if not recipeData.input? then throw new Error 'the "input" declaration is required' if not recipeData.pattern? then throw new Error 'the "pattern" declaration is required' + itemSlug = _.slugify itemData.name + modVersion.registerName itemSlug, itemData.name + if itemData.type is 'new' then itemSlug = _.composeSlugs modVersion.modSlug, itemSlug + qualifySlug = (name, slug)=> - if @_rawData.items[name]? - return _.composeSlugs modVersion.modSlug, slug - else - return slug + return slug unless itemData.type is 'new' + return slug unless @_rawData.items[name]? + return _.composeSlugs modVersion.modSlug, slug recipeData.quantity ?= 1 recipeData.extras ?= [] @@ -165,7 +178,8 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase name = modVersion.findName stack.slug throw new Error "#{name} is an input for this recipe, but it is not in the pattern" - outputStacks = [ new Stack slug:item.qualifiedSlug, quantity:recipeData.quantity ] + + outputStacks = [ new Stack slug:itemSlug, quantity:recipeData.quantity ] for extraData in recipeData.extras slug = _.slugify extraData.name modVersion.registerName slug, extraData.name @@ -179,22 +193,19 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase slug = qualifySlug name, slug toolStacks.push new Stack slug:slug, quantity:1 - attributes = + recipe = new Recipe input: inputStacks output: outputStacks pattern: recipeData.pattern tools: toolStacks - recipe = new Recipe attributes modVersion.addRecipe recipe + logger.debug "adding recipe: #{recipe}" return recipe # Un-parsing Methods ########################################################################### _unparseModVersion: (builder, modVersion)-> - itemList = [] - modVersion.eachItem (item)-> itemList.push item - builder .line 'schema: ', 1 .line() @@ -202,6 +213,13 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase modVersion.eachGroup (group)=> @_unparseGroup builder, modVersion, group + for itemSlug, recipeList of modVersion.findExternalRecipes() + builder + .line 'update: ', modVersion.findName itemSlug + .indent() + .loop(recipeList, delimiter:'\n\n', onEach:(b, r)=> @_unparseRecipe(b, r)) + .outdent() + _unparseGroup: (builder, modVersion, group)-> if group isnt Item.Group.Other builder @@ -210,15 +228,14 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase .indent() modVersion.eachItemInGroup group, (item)=> - @_unparseItem builder, item + @_unparseItem builder, modVersion, item builder.line() if group isnt Item.Group.Other builder.outdent() - _unparseItem: (builder, item)-> - recipes = [] - item.eachRecipe (recipe)-> recipes.push recipe + _unparseItem: (builder, modVersion, item)-> + recipes = modVersion.findRecipes item.qualifiedSlug builder .line 'item: ', item.name diff --git a/test/crafting_plan.test.coffee b/test/crafting_plan.test.coffee index 9fd899f93..5afe29cff 100644 --- a/test/crafting_plan.test.coffee +++ b/test/crafting_plan.test.coffee @@ -43,7 +43,6 @@ describe 'crafting_plan.coffee', -> it 'can craft a single step recipe', -> plan.want.add 'oak_plank' plan.craft() - logger.debug "plan: #{plan}" plan.need.toList().should.eql ['oak_log'] plan.result.toList().should.eql [[4, 'minecraft__oak_plank']] diff --git a/test/parser_versions/mod_version_parser_v1.test.coffee b/test/parser_versions/mod_version_parser_v1.test.coffee index ca522094e..3c40589b8 100644 --- a/test/parser_versions/mod_version_parser_v1.test.coffee +++ b/test/parser_versions/mod_version_parser_v1.test.coffee @@ -5,8 +5,9 @@ Copyright (c) 2015 by Redwood Labs All rights reserved. ### -ModVersion = require '../../src/scripts/models/mod_version' -ModVersionParserV1 = require '../../src/scripts/models/parser_versions/mod_version_parser_v1' +CommandParserVersionBase = require '../../src/scripts/models/parser_versions/command_parser_version_base' +ModVersion = require '../../src/scripts/models/mod_version' +ModVersionParserV1 = require '../../src/scripts/models/parser_versions/mod_version_parser_v1' ######################################################################################################################## @@ -28,7 +29,6 @@ describe 'mod_version_parser_v1.coffee', -> recipe:; input:Bravo; pattern:... 0.0 ...;" modVersion = parser.parse recipes recipes = modVersion.findRecipes 'test__charlie' - logger.debug "recipes: #{util.inspect(recipes)}" recipes[0].input[0].slug.should.equal 'alpha' recipes[1].input[0].slug.should.equal 'bravo' @@ -208,3 +208,43 @@ describe 'mod_version_parser_v1.coffee', -> it 'does not allow a duplicate "tools" declaration', -> func = -> parser.parse baseText + 'tools:Crafting Table; tools:Furnace' expect(func).to.throw Error, 'duplicate declaration of "tools"' + + describe "unparsing", -> + + beforeEach -> + baseText = """ + schema: 1 + + group: Agriculture + + item: Apple + + item: Baked Potato + recipe: + input: Potato, furnace fuel + pattern: .0. ... .1. + tools: Furnace + + group: Functional Blocks + + item: Furnace + recipe: + input: Cobblestone + pattern: 000 0.0 000 + tools: Crafting Table + + update: Iron Ingot + recipe: + input: Iron Dust, furnace fuel + pattern: .0. ... .1. + tools: Furnace + """ + + it 'can round-trip a data file', -> + text = parser.unparse parser.parse baseText + actual = CommandParserVersionBase.simplify text + expected = CommandParserVersionBase.simplify baseText + + logger.debug "actual:\n>>>#{actual}<<<\n\n\n" + logger.debug "expected:\n>>>#{expected}<<<" + actual.should.equal expected