Qualify all item slugs to the mod which adds them #53
* Change default item URL to fall under /mod/<mod slug>/<item slug> but kept the old URL pattern around with the old behavior (i.e., find the first item with that slug) * Update Item to have a `qualifiedSlug` property which combines the item's own slug with its Mod's slug. Updated a lot of code all over to use this in preference to the plain slug. * Add a `localizeTo` method to Inventory to allow non-qualified slugs to be converted into qualified slugs within the inventory's stacks * Update ModPack to work with either qualified or unqualified slugs for relevant methods * Fix model state changes to happen before related events are triggered * Add a debounce to the CraftingPlan object when triggering a recraft due to changes in related objects (esp. its inventories) * Update the Inventory's sort to keep items sorted by mod before name with the Minecraft items sorted to the top * Fix `ModPack.findItemByName` to actually recursively use the Mod's method instead of slugifying the given name and looking for the slug (since this won't necessarily work anymore). * Ensure each Mod is assigned a reference to its containing ModPack * Fix NameFinder to only consider an item non-gatherable if it is also craftable * Update ModVersionParserV1 to assign qualified slugs to recipes for any items which are in the same mod (leaving any other slugs unqualified) * Add Underscore mixins for composing and decomposing slugs * Update old tests for the use of qualified slugs, and some new tests for the new methods added
This commit is contained in:
@@ -44,25 +44,29 @@ describe 'crafting_plan.coffee', ->
|
||||
plan.want.add 'oak_plank'
|
||||
plan.craft()
|
||||
plan.need.toList().should.eql ['oak_log']
|
||||
plan.result.toList().should.eql [[4, 'oak_plank']]
|
||||
plan.result.toList().should.eql [[4, 'minecraft__oak_plank']]
|
||||
|
||||
it 'can craft a multi-step recipe', ->
|
||||
plan.want.add 'crafting_table'
|
||||
plan.craft()
|
||||
plan.need.toList().should.eql ['oak_log']
|
||||
plan.result.toList().should.eql ['crafting_table']
|
||||
plan.result.toList().should.eql ['minecraft__crafting_table']
|
||||
|
||||
it 'can craft a multi-step recipe using tools', ->
|
||||
plan.want.add 'furnace'
|
||||
plan.craft()
|
||||
plan.need.toList().should.eql [[8, 'cobblestone']]
|
||||
plan.result.toList().should.eql ['furnace']
|
||||
plan.result.toList().should.eql ['minecraft__furnace']
|
||||
|
||||
it 'can craft a multi-step recipe re-using tools', ->
|
||||
plan.want.add 'iron_sword'
|
||||
plan.craft()
|
||||
plan.need.toList().should.eql [[2, 'furnace_fuel'], [2, 'iron_ore'], 'oak_log']
|
||||
plan.result.toList().should.eql ['iron_sword', [2, 'oak_plank'], [3, 'stick']]
|
||||
plan.result.toList().should.eql [
|
||||
'minecraft__iron_sword',
|
||||
[2, 'minecraft__oak_plank'],
|
||||
[3, 'minecraft__stick']
|
||||
]
|
||||
|
||||
describe 'with building tools', ->
|
||||
|
||||
@@ -71,7 +75,7 @@ describe 'crafting_plan.coffee', ->
|
||||
plan.want.add 'furnace'
|
||||
plan.craft()
|
||||
plan.need.toList().should.eql [[8, 'cobblestone'], 'oak_log']
|
||||
plan.result.toList().should.eql ['crafting_table', 'furnace']
|
||||
plan.result.toList().should.eql ['minecraft__crafting_table', 'minecraft__furnace']
|
||||
|
||||
it 'can craft a multi-step recipe re-using tools', ->
|
||||
plan.includingTools = true
|
||||
@@ -82,5 +86,9 @@ describe 'crafting_plan.coffee', ->
|
||||
[8, 'cobblestone'], [2, 'furnace_fuel'], [2, 'iron_ore'], [2, 'oak_log']
|
||||
]
|
||||
plan.result.toList().should.eql [
|
||||
'crafting_table', 'furnace', 'iron_sword', [2, 'oak_plank'], [3, 'stick']
|
||||
'minecraft__crafting_table',
|
||||
'minecraft__furnace',
|
||||
'minecraft__iron_sword',
|
||||
[2, 'minecraft__oak_plank'],
|
||||
[3, 'minecraft__stick']
|
||||
]
|
||||
|
||||
@@ -12,7 +12,7 @@ Item = require '../src/scripts/models/item'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
inventory = null
|
||||
inventory = modPack = null
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -107,6 +107,39 @@ describe 'inventory.coffee', ->
|
||||
inventory.hasAtLeast('wool', 4).should.be.true
|
||||
inventory.hasAtLeast('wool', 5).should.be.false
|
||||
|
||||
describe 'localizeTo', ->
|
||||
|
||||
before ->
|
||||
modPack =
|
||||
map:
|
||||
wool: 'minecraft__wool'
|
||||
string: 'minecraft__string'
|
||||
boat: 'minecraft__boat'
|
||||
stone_gear: 'buildcraft__stone_gear'
|
||||
findItem: (slug)->
|
||||
[modSlug, itemSlug] = _.decomposeSlug slug
|
||||
return slug:itemSlug, qualifiedSlug:@map[itemSlug]
|
||||
|
||||
it 'replaces item slugs with qualified slugs', ->
|
||||
inventory.add 'stone_gear'
|
||||
inventory.localizeTo modPack
|
||||
inventory.toList().should.eql [
|
||||
'minecraft__boat',
|
||||
[20, 'minecraft__string'],
|
||||
[4, 'minecraft__wool'],
|
||||
'buildcraft__stone_gear'
|
||||
]
|
||||
|
||||
it 'ignores qualified slugs', ->
|
||||
inventory.add 'buildcraft__stone_gear'
|
||||
inventory.localizeTo modPack
|
||||
inventory.toList().should.eql [
|
||||
'minecraft__boat',
|
||||
[20, 'minecraft__string'],
|
||||
[4, 'minecraft__wool'],
|
||||
'buildcraft__stone_gear'
|
||||
]
|
||||
|
||||
describe 'pop', ->
|
||||
|
||||
it 'returns null for an empty inventory', ->
|
||||
|
||||
@@ -24,7 +24,7 @@ describe 'inventory_parser.coffee', ->
|
||||
result.toList().should.eql []
|
||||
|
||||
it 'can parse a single item without quantity', ->
|
||||
result = parser.parse 'Wool'
|
||||
result = parser.parse 'wool'
|
||||
result.toList().should.eql ['wool']
|
||||
|
||||
it 'can parse a single item with quantity', ->
|
||||
@@ -32,11 +32,11 @@ describe 'inventory_parser.coffee', ->
|
||||
result.toList().should.eql [[4, 'wool']]
|
||||
|
||||
it 'can parse multiple mixed-type items', ->
|
||||
result = parser.parse '4.Wool:10.String:Boat'
|
||||
result = parser.parse '4.wool:10.string:boat'
|
||||
result.toList().should.eql ['boat', [10, 'string'], [4, 'wool']]
|
||||
|
||||
it 're-uses the given inventory object', ->
|
||||
inventory = new Inventory
|
||||
inventory.add 'string', 8
|
||||
result = parser.parse '4.Wool', inventory
|
||||
result = parser.parse '4.wool', inventory
|
||||
result.toList().should.eql [[8, 'string'], [4, 'wool']]
|
||||
|
||||
@@ -19,22 +19,23 @@ buildcraft = industrialCraft = minecraft = modPack = null
|
||||
describe 'mod_pack.coffee', ->
|
||||
|
||||
beforeEach ->
|
||||
minecraft = new Mod slug:'minecraft'
|
||||
minecraft = new Mod slug:'minecraft', name:'Minecraft'
|
||||
minecraft.addModVersion new ModVersion modSlug:minecraft.slug, version:'1.7.10'
|
||||
minecraft.activeModVersion.addItem new Item name:'Wool'
|
||||
minecraft.activeModVersion.addItem new Item name:'Bed', recipes:['']
|
||||
minecraft.activeModVersion.registerSlug 'iron_chestplate', 'Iron Chestplate'
|
||||
|
||||
buildcraft = new Mod slug:'buildcraft'
|
||||
buildcraft = new Mod slug:'buildcraft', name:'Buildcraft'
|
||||
buildcraft.addModVersion new ModVersion modSlug:buildcraft.slug, version:'6.2.6'
|
||||
buildcraft.activeModVersion.addItem new Item name:'Stone Gear', recipes:['']
|
||||
buildcraft.activeModVersion.addItem new Item name:'Bed', recipes:['']
|
||||
buildcraft.activeModVersion.addItem new Item name:'Wrench', recipes:['']
|
||||
buildcraft.activeVersion = Mod.Version.None
|
||||
|
||||
industrialCraft = new Mod slug:'industrial_craft'
|
||||
industrialCraft = new Mod slug:'industrial_craft', name:'Industrial Craft'
|
||||
industrialCraft.addModVersion new ModVersion modSlug:industrialCraft.slug, version:'2.0'
|
||||
industrialCraft.activeModVersion.addItem new Item name:'Resin'
|
||||
industrialCraft.activeModVersion.addItem new Item name:'Rubber'
|
||||
industrialCraft.activeModVersion.addItem new Item name:'Wrench', recipes:['']
|
||||
industrialCraft.activeVersion = Mod.Version.None
|
||||
|
||||
modPack = new ModPack
|
||||
@@ -42,6 +43,30 @@ describe 'mod_pack.coffee', ->
|
||||
modPack.addMod buildcraft
|
||||
modPack.addMod industrialCraft
|
||||
|
||||
describe 'findItem', ->
|
||||
|
||||
it 'can find an item by partial slug', ->
|
||||
item = modPack.findItem 'wool'
|
||||
item.qualifiedSlug.should.equal 'minecraft__wool'
|
||||
|
||||
it 'can find an item by full slug', ->
|
||||
item = modPack.findItem 'minecraft__wool'
|
||||
item.name.should.equal 'Wool'
|
||||
|
||||
it 'can find an ambiguous item by full slug', ->
|
||||
buildcraft.activeVersion = Mod.Version.Latest
|
||||
industrialCraft.activeVersion = Mod.Version.Latest
|
||||
item = modPack.findItem 'industrial_craft__wrench'
|
||||
item.name.should.equal 'Wrench'
|
||||
item.modVersion.mod.name.should.equal 'Industrial Craft'
|
||||
|
||||
it 'can find an ambiguous item by partial slug', ->
|
||||
buildcraft.activeVersion = Mod.Version.Latest
|
||||
industrialCraft.activeVersion = Mod.Version.Latest
|
||||
item = modPack.findItem 'wrench'
|
||||
item.name.should.equal 'Wrench'
|
||||
item.modVersion.mod.name.should.equal 'Buildcraft'
|
||||
|
||||
describe 'findItemByName', ->
|
||||
|
||||
it 'finds the requested item', ->
|
||||
@@ -57,7 +82,7 @@ describe 'mod_pack.coffee', ->
|
||||
it 'returns all data for a regular Minecraft item', ->
|
||||
display = modPack.findItemDisplay 'bed'
|
||||
display.iconUrl.should.equal '/data/minecraft/1.7.10/images/bed.png'
|
||||
display.itemUrl.should.equal '/item/bed'
|
||||
display.itemUrl.should.equal '/mod/minecraft/bed'
|
||||
display.itemName.should.equal 'Bed'
|
||||
display.modSlug.should.equal 'minecraft'
|
||||
|
||||
@@ -65,13 +90,13 @@ describe 'mod_pack.coffee', ->
|
||||
buildcraft.activeVersion = '6.2.6'
|
||||
display = modPack.findItemDisplay 'stone_gear'
|
||||
display.iconUrl.should.equal '/data/buildcraft/6.2.6/images/stone_gear.png'
|
||||
display.itemUrl.should.equal '/item/stone_gear'
|
||||
display.itemUrl.should.equal '/mod/buildcraft/stone_gear'
|
||||
display.itemName.should.equal 'Stone Gear'
|
||||
display.modSlug.should.equal 'buildcraft'
|
||||
|
||||
it 'assumes an unfound item is from Minecraft', ->
|
||||
display = modPack.findItemDisplay 'iron_chestplate'
|
||||
display.iconUrl.should.equal '/data/minecraft/1.7.10/images/iron_chestplate.png'
|
||||
display.itemUrl.should.equal '/item/iron_chestplate'
|
||||
display.itemUrl.should.equal '/mod/minecraft/iron_chestplate'
|
||||
display.itemName.should.equal 'Iron Chestplate'
|
||||
display.modSlug.should.equal 'minecraft'
|
||||
|
||||
@@ -91,5 +91,5 @@ describe 'mod_version.coffee', ->
|
||||
"""
|
||||
|
||||
it 'finds all recipes which list item as output', ->
|
||||
recipes = modVersion.findRecipes 'bucket'
|
||||
(r.output[0].slug for r in recipes).sort().should.eql ['bucket', 'cake', 'cake']
|
||||
recipes = modVersion.findRecipes 'test__bucket'
|
||||
(r.output[0].slug for r in recipes).sort().should.eql ['test__bucket', 'test__cake', 'test__cake']
|
||||
|
||||
@@ -68,7 +68,7 @@ describe 'mod_version_parser_v1.coffee', ->
|
||||
it 'adds "input" when present', ->
|
||||
modVersion = parser.parse baseText + 'recipe:; input:Alpha, Bravo, Charlie; pattern: ... 012 ...'
|
||||
slugs = (s.slug for s in modVersion._items.charlie._recipes[0].input)
|
||||
slugs.should.eql ['alpha', 'bravo', 'charlie']
|
||||
slugs.should.eql ['alpha', 'bravo', 'test__charlie']
|
||||
|
||||
it 'requires an "input" declaration', ->
|
||||
func = -> parser.parse baseText + 'recipe:; pattern: ... .0. ...'
|
||||
@@ -155,20 +155,20 @@ describe 'mod_version_parser_v1.coffee', ->
|
||||
describe 'output', ->
|
||||
|
||||
beforeEach ->
|
||||
baseText = 'item:Bravo; recipe:; input:Charlie; pattern:... .0. ...; '
|
||||
baseText = 'item: Delta; item:Bravo; recipe:; input:Charlie; pattern:... .0. ...; '
|
||||
|
||||
it 'adds a single item as the default output', ->
|
||||
modVersion = parser.parse baseText
|
||||
stack = modVersion._items.bravo._recipes[0].output[0]
|
||||
stack.slug.should.equal 'bravo'
|
||||
stack.slug.should.equal 'test__bravo'
|
||||
stack.quantity.should.equal 1
|
||||
|
||||
it 'can add multiple extras with quantities', ->
|
||||
modVersion = parser.parse baseText + 'extras:2 Delta, 4 Echo'
|
||||
output = modVersion._items.bravo._recipes[0].output
|
||||
output[0].slug.should.equal 'bravo'
|
||||
output[0].slug.should.equal 'test__bravo'
|
||||
output[0].quantity.should.equal 1
|
||||
output[1].slug.should.equal 'delta'
|
||||
output[1].slug.should.equal 'test__delta'
|
||||
output[1].quantity.should.equal 2
|
||||
output[2].slug.should.equal 'echo'
|
||||
output[2].quantity.should.equal 4
|
||||
|
||||
@@ -5,6 +5,7 @@ Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
Item = require '../src/scripts/models/item'
|
||||
Recipe = require '../src/scripts/models/recipe'
|
||||
Stack = require '../src/scripts/models/stack'
|
||||
|
||||
@@ -32,7 +33,8 @@ describe 'recipe.coffee', ->
|
||||
expect(-> new Recipe name:'Gold Gear', input:input).to.throw Error, 'attributes.pattern is required'
|
||||
|
||||
it 'allows an item to provide required attributes', ->
|
||||
recipe = new Recipe item:{name:'Gold Gear', slug:'gold_gear'}, input:input, pattern:pattern
|
||||
item = new Item name:'Gold Gear'
|
||||
recipe = new Recipe item:item, input:input, pattern:pattern
|
||||
recipe.name.should.equal 'Gold Gear'
|
||||
(o.slug for o in recipe.output).should.eql ['gold_gear']
|
||||
|
||||
|
||||
Reference in New Issue
Block a user