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:
@@ -56,7 +56,7 @@ Text.title = 'Crafting Guide for Minecraft | The Ultimate Step-by-Step Tutorial
|
||||
exports.Url = Url = {}
|
||||
Url.crafting = _.template "/crafting/<%= inventoryText %>"
|
||||
Url.itemIcon = _.template "/data/<%= modSlug %>/<%= modVersion %>/images/<%= slug %>.png"
|
||||
Url.item = _.template "/item/<%= slug %>"
|
||||
Url.item = _.template "/mod/<%= modSlug %>/<%= slug %>"
|
||||
Url.mod = _.template "/mod/<%= modSlug %>"
|
||||
Url.modData = _.template "/data/<%= modSlug %>/mod.cg"
|
||||
Url.modVersion = _.template "/data/<%= modSlug %>/<%= modVersion %>/mod-version.cg"
|
||||
|
||||
@@ -68,8 +68,8 @@ module.exports = class FullRecipeController extends BaseController
|
||||
result = []
|
||||
if @model?
|
||||
for stack in @model.tools
|
||||
name = @modPack.findName stack.slug
|
||||
result.push name if name?
|
||||
item = @modPack.findItem stack.slug
|
||||
result.push item.name if item?
|
||||
return result
|
||||
|
||||
_refreshInputs: ->
|
||||
|
||||
@@ -28,7 +28,7 @@ module.exports = class ItemController extends BaseController
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
display = @_modPack.findItemDisplay @model.slug
|
||||
display = @_modPack.findItemDisplay @model.qualifiedSlug
|
||||
|
||||
@$icon.attr 'src', display.iconUrl
|
||||
@$name.html display.itemName
|
||||
|
||||
@@ -57,7 +57,7 @@ module.exports = class ItemPageController extends BaseController
|
||||
$('title').html if @model.item? then "#{@model.item.name} | #{Text.title}" else Text.title
|
||||
@_resolveItemSlug()
|
||||
|
||||
display = @_modPack.findItemDisplay @model.item?.slug
|
||||
display = @_modPack.findItemDisplay @model.item?.qualifiedSlug
|
||||
if display?
|
||||
@$craftingPlanLink.attr href:display.craftingUrl
|
||||
@$craftingPlanLink.fadeIn duration:Duration.normal
|
||||
@@ -143,6 +143,4 @@ module.exports = class ItemPageController extends BaseController
|
||||
@$similarContainer.fadeOut duration:Duration.normal
|
||||
|
||||
_resolveItemSlug: ->
|
||||
oldItem = @model.item
|
||||
@model.item = @_modPack.findItem @_itemSlug, includeDisabled:true
|
||||
newItem = @model.item
|
||||
|
||||
@@ -72,6 +72,6 @@ module.exports = class MinimalRecipeController extends BaseController
|
||||
result = []
|
||||
if @model?
|
||||
for stack in @model.tools
|
||||
name = @_modPack.findName stack.slug
|
||||
result.push name if name?
|
||||
item = @_modPack.findItem stack.slug
|
||||
result.push item.name if item?
|
||||
return result
|
||||
|
||||
@@ -57,10 +57,11 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
|
||||
@_recordPageView()
|
||||
|
||||
routes:
|
||||
'': 'root'
|
||||
'item/:itemSlug': 'item'
|
||||
'crafting/(:text)': 'crafting'
|
||||
'mod/:modSlug': 'mod'
|
||||
'': 'root'
|
||||
'item/:itemSlug': 'item'
|
||||
'crafting/(:text)': 'crafting'
|
||||
'mod/:modSlug': 'mod'
|
||||
'mod/:modSlug/:itemSlug': 'modItem'
|
||||
|
||||
# Route Methods ################################################################################
|
||||
|
||||
@@ -69,7 +70,12 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
|
||||
controller.model.params = inventoryText:text
|
||||
@_setPage 'crafting', controller
|
||||
|
||||
item: (slug)->
|
||||
item: (itemSlug)->
|
||||
controller = new ItemPageController _.extend {itemSlug:itemSlug}, @_defaultOptions
|
||||
@_setPage 'item', controller
|
||||
|
||||
modItem: (modSlug, itemSlug)->
|
||||
slug = _.composeSlugs modSlug, itemSlug
|
||||
controller = new ItemPageController _.extend {itemSlug:slug}, @_defaultOptions
|
||||
@_setPage 'item', controller
|
||||
|
||||
@@ -84,9 +90,9 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
|
||||
text = ''
|
||||
if params.recipeName?
|
||||
if params.count?
|
||||
text = "#{params.count}.#{params.recipeName}"
|
||||
text = "#{params.count}.#{_.slugify(params.recipeName)}"
|
||||
else
|
||||
text = "#{params.recipeName}"
|
||||
text = _.slugify params.recipeName
|
||||
|
||||
@navigate Url.crafting(inventoryText:text), trigger:true
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ global.logger = new Logger
|
||||
switch window.location.hostname
|
||||
when 'localhost'
|
||||
global.env = 'development'
|
||||
logger.level = Logger.INFO
|
||||
logger.level = Logger.DEBUG
|
||||
when 'new.crafting-guide.com'
|
||||
global.env = 'staging'
|
||||
logger.level = Logger.VERBOSE
|
||||
|
||||
@@ -25,10 +25,6 @@ module.exports = class BaseModel extends Backbone.Model
|
||||
@logEvents = options.logEvents or false
|
||||
@state = ModelState.unloaded
|
||||
|
||||
@on 'request', => @state = ModelState.loading
|
||||
@on 'sync', => @state = ModelState.loaded
|
||||
@on 'error', => @state = ModelState.error
|
||||
|
||||
@loading = null
|
||||
|
||||
Object.defineProperties this,
|
||||
@@ -42,6 +38,8 @@ module.exports = class BaseModel extends Backbone.Model
|
||||
onLoadSucceeded: (text, status, xhr)->
|
||||
try
|
||||
@set @parse text
|
||||
|
||||
@state = ModelState.loaded
|
||||
@trigger Event.change, this
|
||||
@trigger Event.sync, this
|
||||
logger.info => "#{@constructor.name}.#{@cid} loaded successfully"
|
||||
@@ -50,6 +48,7 @@ module.exports = class BaseModel extends Backbone.Model
|
||||
@onLoadFailed e.message, 'parsing failed', xhr
|
||||
|
||||
onLoadFailed: (error, status, xhr)->
|
||||
@state = ModelState.error
|
||||
logger.error => "#{@constructor.name}.#{@cid} failed to load: status:#{status}, message:#{error}"
|
||||
@trigger Event.error, this, error
|
||||
|
||||
@@ -62,6 +61,7 @@ module.exports = class BaseModel extends Backbone.Model
|
||||
url = @url()
|
||||
logger.info => "#{@constructor.name}.#{@cid} reading from url: #{url}"
|
||||
|
||||
@state = ModelState.loading
|
||||
@trigger Event.request, this
|
||||
@loading = w.promise (resolve, reject)=>
|
||||
$.ajax
|
||||
|
||||
@@ -14,7 +14,7 @@ ModPack = require './mod_pack'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class extends BaseModel
|
||||
module.exports = class CraftingPage extends BaseModel
|
||||
|
||||
constructor: (attributes={}, options={})->
|
||||
attributes.modPack ?= new ModPack
|
||||
@@ -40,7 +40,7 @@ module.exports = class extends BaseModel
|
||||
inventory = @_parser.parse @params.inventoryText
|
||||
|
||||
inventory.each (stack)=>
|
||||
item = @modPack.findItemByName stack.slug, enableAsNeeded:true
|
||||
item = @modPack.findItem stack.slug, enableAsNeeded:true
|
||||
return unless item? and item.isCraftable
|
||||
@plan.want.add stack.slug, stack.quantity
|
||||
inventory.remove stack.slug
|
||||
|
||||
@@ -23,14 +23,14 @@ module.exports = class CraftingPlan extends BaseModel
|
||||
@need = new Inventory
|
||||
@result = new Inventory
|
||||
|
||||
recraft = _.debounce (=> @craft()), 100
|
||||
for inventory in [@have, @want]
|
||||
inventory.on 'change', recraft
|
||||
|
||||
@on Event.change + ':includingTools', recraft
|
||||
|
||||
@clear()
|
||||
|
||||
@have.on Event.change, => @craft()
|
||||
@want.on Event.change, => @craft()
|
||||
@modPack.on Event.change, => @craft()
|
||||
|
||||
@on Event.change + ':includingTools', => @craft()
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
clear: (options={})->
|
||||
@@ -42,7 +42,12 @@ module.exports = class CraftingPlan extends BaseModel
|
||||
return this
|
||||
|
||||
craft: ->
|
||||
toolsMessage = if @includingTools then ' (including tools)' else ''
|
||||
logger.info => "crafting #{@want}#{toolsMessage} starting with #{@have}"
|
||||
|
||||
@clear()
|
||||
@have.localizeTo @modPack
|
||||
@want.localizeTo @modPack
|
||||
|
||||
@result.addInventory @have
|
||||
|
||||
@@ -50,12 +55,14 @@ module.exports = class CraftingPlan extends BaseModel
|
||||
@_reservedSteps = {}
|
||||
@want.each (stack)=>
|
||||
@_findSteps stack.slug
|
||||
@need.add stack.slug, stack.quantity
|
||||
item = @modPack.findItem stack.slug
|
||||
@need.add item.qualifiedSlug, stack.quantity
|
||||
@_reservedSteps = null
|
||||
|
||||
@steps = _.values @steps
|
||||
@_resolveNeeds()
|
||||
@_removeExtraSteps()
|
||||
|
||||
@result.addInventory @want
|
||||
|
||||
@need.trigger 'change', @need
|
||||
@@ -91,14 +98,13 @@ module.exports = class CraftingPlan extends BaseModel
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_addStep: (recipe)->
|
||||
logger.verbose -> "adding step: #{recipe.slug}"
|
||||
@steps[recipe.slug] = recipe:recipe
|
||||
logger.verbose -> "adding step: #{recipe.item.qualifiedSlug}"
|
||||
@steps[recipe.item.qualifiedSlug] = recipe:recipe
|
||||
|
||||
_chooseRecipe: (item)->
|
||||
return item.getPrimaryRecipe()
|
||||
|
||||
_findSteps: (slug)->
|
||||
logger.debug -> "finding steps for #{slug}"
|
||||
item = @modPack.findItem slug
|
||||
return unless item?
|
||||
return unless item.isCraftable
|
||||
@@ -111,9 +117,8 @@ module.exports = class CraftingPlan extends BaseModel
|
||||
if not @_hasStep toolStack.slug
|
||||
@_findSteps toolStack.slug
|
||||
|
||||
return if @_hasStep item.slug
|
||||
logger.debug -> "reserving: #{item.slug}"
|
||||
@_reservedSteps[item.slug] = recipe
|
||||
return if @_hasStep item.qualifiedSlug
|
||||
@_reservedSteps[item.qualifiedSlug] = recipe
|
||||
|
||||
for inputStack in recipe.input
|
||||
@_findSteps inputStack.slug
|
||||
@@ -125,6 +130,11 @@ module.exports = class CraftingPlan extends BaseModel
|
||||
return true if @_reservedSteps[slug]?
|
||||
return false
|
||||
|
||||
_qualifyItemSlug: (slug)->
|
||||
item = @modPack.findItem slug
|
||||
return item.qualifiedSlug if item?
|
||||
return slug
|
||||
|
||||
_removeExtraSteps: ->
|
||||
result = (step for step in @steps when step.multiplier > 0)
|
||||
@steps = result
|
||||
@@ -134,29 +144,31 @@ module.exports = class CraftingPlan extends BaseModel
|
||||
step = @steps[i]
|
||||
recipe = step.recipe
|
||||
|
||||
step.multiplier = Math.ceil(@need.quantityOf(recipe.slug) / step.recipe.output[0].quantity)
|
||||
step.multiplier = Math.ceil(@need.quantityOf(recipe.slug) / recipe.output[0].quantity)
|
||||
|
||||
if @includingTools
|
||||
for stack in recipe.tools
|
||||
slug = stack.slug
|
||||
slug = @_qualifyItemSlug stack.slug
|
||||
available = @result.quantityOf(slug) + @need.quantityOf(slug)
|
||||
needed = Math.max 0, stack.quantity - available
|
||||
|
||||
@need.add stack.slug, needed
|
||||
@result.add stack.slug, needed
|
||||
@need.add slug, needed
|
||||
@result.add slug, needed
|
||||
|
||||
for stack in recipe.input
|
||||
slug = @_qualifyItemSlug stack.slug
|
||||
needed = step.multiplier * stack.quantity
|
||||
consumed = Math.min needed, @result.quantityOf(stack.slug)
|
||||
consumed = Math.min needed, @result.quantityOf slug
|
||||
remaining = needed - consumed
|
||||
|
||||
@result.remove stack.slug, consumed
|
||||
@need.add stack.slug, remaining
|
||||
@result.remove slug, consumed
|
||||
@need.add slug, remaining
|
||||
|
||||
for stack in recipe.output
|
||||
slug = @_qualifyItemSlug stack.slug
|
||||
created = stack.quantity * step.multiplier
|
||||
consumed = Math.min created, @need.quantityOf stack.slug
|
||||
consumed = Math.min created, @need.quantityOf slug
|
||||
remaining = created - consumed
|
||||
|
||||
@result.add stack.slug, remaining
|
||||
@need.remove stack.slug, consumed
|
||||
@result.add slug, remaining
|
||||
@need.remove slug, consumed
|
||||
|
||||
@@ -5,9 +5,10 @@ Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseModel = require './base_model'
|
||||
{Event} = require '../constants'
|
||||
Stack = require './stack'
|
||||
BaseModel = require './base_model'
|
||||
{Event} = require '../constants'
|
||||
{RequiredMods} = require '../constants'
|
||||
Stack = require './stack'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -59,6 +60,22 @@ module.exports = class Inventory extends BaseModel
|
||||
return false unless stack?
|
||||
return stack.quantity >= quantity
|
||||
|
||||
localizeTo: (modPack)->
|
||||
newSlugs = []
|
||||
for slug in @_slugs
|
||||
stack = @_stacks[slug]
|
||||
qualifiedSlug = modPack.findItem(slug)?.qualifiedSlug
|
||||
if qualifiedSlug?
|
||||
delete @_stacks[slug]
|
||||
newSlugs.push qualifiedSlug
|
||||
@_stacks[qualifiedSlug] = stack
|
||||
stack.slug = qualifiedSlug
|
||||
else
|
||||
throw new Error "could not find an item for: #{slug}"
|
||||
|
||||
@_slugs = newSlugs
|
||||
@_sort()
|
||||
|
||||
pop: ->
|
||||
slug = @_slugs.pop()
|
||||
return null unless slug?
|
||||
@@ -129,6 +146,22 @@ module.exports = class Inventory extends BaseModel
|
||||
stack = new Stack slug:slug, quantity:quantity
|
||||
@_stacks[slug] = stack
|
||||
@_slugs.push slug
|
||||
@_slugs.sort()
|
||||
@_sort()
|
||||
else
|
||||
stack.quantity += quantity
|
||||
|
||||
_sort: ->
|
||||
@_slugs.sort (a, b)->
|
||||
[modSlugA, itemSlugA] = _.decomposeSlug a
|
||||
[modSlugB, itemSlugB] = _.decomposeSlug b
|
||||
isRequiredA = modSlugA in RequiredMods
|
||||
isRequiredB = modSlugB in RequiredMods
|
||||
|
||||
if isRequiredA isnt isRequiredB
|
||||
return -1 if isRequiredA
|
||||
return +1 if isRequiredB
|
||||
else if modSlugA isnt modSlugB
|
||||
return if modSlugA < modSlugB then -1 else +1
|
||||
else if itemSlugA isnt itemSlugB
|
||||
return if itemSlugA < itemSlugB then -1 else +1
|
||||
return 0
|
||||
|
||||
@@ -33,10 +33,10 @@ module.exports = class InventoryParser
|
||||
stackParts = stackText.split InventoryParser.ITEM_DELIMITER
|
||||
if stackParts.length is 2
|
||||
quantity = parseInt stackParts[0]
|
||||
slug = _.slugify stackParts[1]
|
||||
slug = stackParts[1]
|
||||
else if stackParts.length is 1
|
||||
quantity = 1
|
||||
slug = _.slugify stackParts[0]
|
||||
slug = stackParts[0]
|
||||
else
|
||||
throw new Error "expected #{stackText} to have 0 or 1 parts"
|
||||
|
||||
|
||||
@@ -21,28 +21,33 @@ module.exports = class Item extends BaseModel
|
||||
|
||||
attributes.group ?= Item.Group.Other
|
||||
attributes.isGatherable ?= false
|
||||
attributes.modVersion ?= null
|
||||
attributes.slug ?= _.slugify attributes.name
|
||||
|
||||
options.logEvents ?= false
|
||||
super attributes, options
|
||||
|
||||
@_recipes = []
|
||||
|
||||
Object.defineProperties this,
|
||||
isCraftable: { get:-> @_recipes.length > 0 }
|
||||
qualifiedSlug: { get:@getQualifiedSlug }
|
||||
primaryRecipe: { get:@getPrimaryRecipe }
|
||||
|
||||
@on Event.change + ':modVersion', => @_qualifiedSlug = null
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
addRecipe: (recipe)->
|
||||
if recipe.slug isnt @slug then throw new Error "cannot add a recipe for #{recipe.slug} to #{@slug}"
|
||||
[modSlug, itemSlug] = _.decomposeSlug recipe.slug
|
||||
if itemSlug isnt @slug then throw new Error "cannot add a recipe for #{recipe.slug} to #{@slug}"
|
||||
recipe.item = this
|
||||
@_recipes.push recipe
|
||||
|
||||
eachRecipe: (callback)->
|
||||
for recipe in @_recipes
|
||||
callback recipe
|
||||
|
||||
getPrimaryRecipe: ->
|
||||
return @_recipes[0]
|
||||
|
||||
compareTo: (that)->
|
||||
if this.slug isnt that.slug
|
||||
return if this.slug < that.slug then -1 else +1
|
||||
@@ -50,6 +55,19 @@ module.exports = class Item extends BaseModel
|
||||
return if this.name < that.name then -1 else +1
|
||||
return 0
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
getQualifiedSlug: ->
|
||||
return @slug if not @modVersion?
|
||||
|
||||
if not @_qualifiedSlug?
|
||||
@_qualifiedSlug = _.composeSlugs @modVersion.modSlug, @slug
|
||||
|
||||
return @_qualifiedSlug
|
||||
|
||||
getPrimaryRecipe: ->
|
||||
return @_recipes[0]
|
||||
|
||||
# Object Overrides #############################################################################
|
||||
|
||||
toString: ->
|
||||
|
||||
@@ -31,14 +31,14 @@ module.exports = class ItemPage extends BaseModel
|
||||
findComponentInItems: ->
|
||||
return null unless @item?
|
||||
|
||||
itemSlug = @item.slug
|
||||
itemSlug = @item.qualifiedSlug
|
||||
result = {}
|
||||
@modPack.eachMod (mod)->
|
||||
mod.eachItem (item)->
|
||||
item.eachRecipe (recipe)->
|
||||
for stack in recipe.input
|
||||
if stack.slug is itemSlug
|
||||
result[item.slug] = item
|
||||
result[item.qualifiedSlug] = item
|
||||
|
||||
result = _.values(result).sort (a, b)-> a.compareTo b
|
||||
return null unless result.length > 0
|
||||
@@ -56,7 +56,7 @@ module.exports = class ItemPage extends BaseModel
|
||||
return result
|
||||
|
||||
findRecipes: ->
|
||||
result = @modPack.findRecipes @item?.slug
|
||||
result = @modPack.findRecipes @item?.qualifiedSlug
|
||||
return null unless result.length > 0
|
||||
return result
|
||||
|
||||
@@ -66,7 +66,7 @@ module.exports = class ItemPage extends BaseModel
|
||||
@_plan.clear()
|
||||
|
||||
if @item?
|
||||
@_plan.want.add @item.slug
|
||||
@_plan.want.add @item.qualifiedSlug
|
||||
@_plan.craft()
|
||||
|
||||
if @_plan.steps.length > 0
|
||||
|
||||
@@ -21,6 +21,7 @@ module.exports = class Mod extends BaseModel
|
||||
attributes.documentationUrl ?= null
|
||||
attributes.downloadUrl ?= null
|
||||
attributes.homePageUrl ?= null
|
||||
attributes.modPack ?= null
|
||||
attributes.name ?= ''
|
||||
super attributes, options
|
||||
|
||||
|
||||
@@ -25,9 +25,16 @@ module.exports = class ModPack extends BaseModel
|
||||
findItem: (slug, options={})->
|
||||
options.includeDisabled ?= false
|
||||
|
||||
[modSlug, itemSlug] = _.decomposeSlug slug
|
||||
if modSlug?
|
||||
mod = @getMod modSlug
|
||||
if mod?
|
||||
item = mod.findItem itemSlug, options
|
||||
return item if item?
|
||||
|
||||
for mod in @_mods
|
||||
continue unless mod.enabled or options.includeDisabled
|
||||
item = mod.findItem slug, options
|
||||
item = mod.findItem itemSlug, options
|
||||
return item if item?
|
||||
|
||||
return null
|
||||
@@ -36,10 +43,9 @@ module.exports = class ModPack extends BaseModel
|
||||
options.enableAsNeeded ?= false
|
||||
options.includeDisabled = true if options.enableAsNeeded
|
||||
|
||||
slug = _.slugify name
|
||||
for mod in @_mods
|
||||
continue unless mod.enabled or options.includeDisabled
|
||||
item = mod.findItem slug, options
|
||||
item = mod.findItemByName name, options
|
||||
return item if item?
|
||||
|
||||
return null
|
||||
@@ -74,6 +80,14 @@ module.exports = class ModPack extends BaseModel
|
||||
return null
|
||||
|
||||
findRecipes: (slug, result=[])->
|
||||
[modSlug, itemSlug] = _.decomposeSlug slug
|
||||
|
||||
if modSlug?
|
||||
mod = @getMod modSlug
|
||||
if mod?
|
||||
mod.findRecipes slug, result
|
||||
return result if result.length > 0
|
||||
|
||||
for mod in @_mods
|
||||
continue unless mod.enabled
|
||||
mod.findRecipes slug, result
|
||||
@@ -88,12 +102,9 @@ module.exports = class ModPack extends BaseModel
|
||||
|
||||
isValidName: (name)->
|
||||
slug = _.slugify name
|
||||
for mod in @_mods
|
||||
continue unless mod.enabled
|
||||
name = mod.findName slug
|
||||
return true if name
|
||||
existingName = @findName slug
|
||||
|
||||
return false
|
||||
return name is existingName
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
@@ -101,6 +112,7 @@ module.exports = class ModPack extends BaseModel
|
||||
if not mod? then throw new Error 'mod is required'
|
||||
return if @_mods.indexOf(mod) isnt -1
|
||||
|
||||
mod.modPack = this
|
||||
@_mods.push mod
|
||||
@listenTo mod, Event.change, => @trigger Event.change, this
|
||||
@trigger Event.add + ':mod', mod, this
|
||||
|
||||
@@ -19,6 +19,7 @@ module.exports = class ModVersion extends BaseModel
|
||||
constructor: (attributes={}, options={})->
|
||||
if not attributes.modSlug? then throw new Error 'attributes.modSlug is required'
|
||||
if not attributes.version? then throw new Error 'attributes.version is required'
|
||||
attributes.mod ?= null
|
||||
super attributes, options
|
||||
|
||||
@_groups = {}
|
||||
|
||||
@@ -67,7 +67,7 @@ module.exports = class NameFinder
|
||||
|
||||
item = mod.findItem slug
|
||||
if not @includeGatherable
|
||||
return unless item? and (not item.isGatherable)
|
||||
return unless item? and item.isCraftable
|
||||
|
||||
scanName = "#{mod.name} : #{name}"
|
||||
if nameHint?
|
||||
|
||||
@@ -61,8 +61,8 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
|
||||
if not name.length > 0 then throw new Error 'the item name cannot be empty'
|
||||
|
||||
@_itemData = name:name, line:@_lineNumber, group:@_rawData.group
|
||||
@_rawData.items ?= []
|
||||
@_rawData.items.push @_itemData
|
||||
@_rawData.items ?= {}
|
||||
@_rawData.items[name] = @_itemData
|
||||
|
||||
@_recipeData = null
|
||||
|
||||
@@ -112,7 +112,7 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
|
||||
_buildModVersion: (modVersionData, modVersion)->
|
||||
modVersionData.items ?= []
|
||||
|
||||
for itemData in modVersionData.items
|
||||
for itemName, itemData of modVersionData.items
|
||||
@_handleErrors @_buildItem, modVersion, itemData
|
||||
|
||||
return modVersion
|
||||
@@ -135,6 +135,12 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
|
||||
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'
|
||||
|
||||
localizeSlug = (name, slug)=>
|
||||
if @_rawData.items[name]?
|
||||
return _.composeSlugs modVersion.modSlug, slug
|
||||
else
|
||||
return slug
|
||||
|
||||
recipeData.quantity ?= 1
|
||||
recipeData.extras ?= []
|
||||
recipeData.tools ?= []
|
||||
@@ -143,6 +149,7 @@ module.exports = class ModVersionParserV1 extends CommandParserVersionBase
|
||||
for name in recipeData.input
|
||||
slug = _.slugify name
|
||||
modVersion.registerSlug slug, name
|
||||
slug = localizeSlug name, slug
|
||||
inputStacks.push new Stack slug:slug, quantity:0
|
||||
|
||||
for c in recipeData.pattern
|
||||
@@ -158,16 +165,18 @@ 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.slug, quantity:recipeData.quantity ]
|
||||
outputStacks = [ new Stack slug:item.qualifiedSlug, quantity:recipeData.quantity ]
|
||||
for extraData in recipeData.extras
|
||||
slug = _.slugify extraData.name
|
||||
modVersion.registerSlug slug, extraData.name
|
||||
slug = localizeSlug extraData.name, slug
|
||||
outputStacks.push new Stack slug:slug, quantity:extraData.quantity
|
||||
|
||||
toolStacks = []
|
||||
for name in recipeData.tools
|
||||
slug = _.slugify name
|
||||
modVersion.registerSlug slug, name
|
||||
slug = localizeSlug name, slug
|
||||
toolStacks.push new Stack slug:slug, quantity:1
|
||||
|
||||
attributes =
|
||||
|
||||
@@ -15,8 +15,7 @@ module.exports = class Recipe extends BaseModel
|
||||
constructor: (attributes={}, options={})->
|
||||
if attributes.item?
|
||||
attributes.name = attributes.item.name
|
||||
attributes.slug = attributes.item.slug
|
||||
attributes.output ?= [new Stack slug:attributes.item.slug, quantity:1]
|
||||
attributes.output ?= [new Stack slug:attributes.item.qualifiedSlug, quantity:1]
|
||||
|
||||
if not attributes.name? then throw new Error 'attributes.name is required'
|
||||
if not attributes.input? then throw new Error 'attributes.input is required'
|
||||
@@ -25,11 +24,13 @@ module.exports = class Recipe extends BaseModel
|
||||
attributes.item ?= null
|
||||
attributes.output ?= [new Stack slug:_.slugify(attributes.name), quantity:1]
|
||||
attributes.pattern = @_parsePattern attributes.pattern
|
||||
attributes.slug ?= attributes.output[0].slug
|
||||
attributes.tools ?= []
|
||||
options.logEvents ?= false
|
||||
super attributes, options
|
||||
|
||||
Object.defineProperties this,
|
||||
slug: {get:@getSlug}
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
getItemSlugAt: (patternSlot)->
|
||||
@@ -48,6 +49,12 @@ module.exports = class Recipe extends BaseModel
|
||||
return true if stack.slug is itemSlug
|
||||
return false
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
getSlug: ->
|
||||
return @item.qualifiedSlug if @item?
|
||||
return @output[0].slug
|
||||
|
||||
# Object Overrides #############################################################################
|
||||
|
||||
toString: ->
|
||||
|
||||
@@ -16,3 +16,15 @@ _.mixin
|
||||
result = result.replace /^_/, ''
|
||||
result = result.replace /_$/, ''
|
||||
return result
|
||||
|
||||
composeSlugs: (part1, part2)->
|
||||
return "#{part1}__#{part2}"
|
||||
|
||||
decomposeSlug: (slug)->
|
||||
return [null, null] unless slug?
|
||||
|
||||
parts = slug.split '__'
|
||||
if parts.length is 1
|
||||
parts = [ null, parts[0] ]
|
||||
|
||||
return parts
|
||||
|
||||
Reference in New Issue
Block a user