Add back the "include tools" option
* Rewrite the crafting algorithm to recursively find all the steps involved and then resolve how many times each needs to be run. * Update the base controller to debounce calls to refresh * Fix a few erroneous recipes for IC2-Classic
This commit is contained in:
@@ -20,4 +20,9 @@ All rights reserved.
|
|||||||
.view__crafting_table { width: 50%; height: 26em; }
|
.view__crafting_table { width: 50%; height: 26em; }
|
||||||
|
|
||||||
.view__mod_pack { margin-top: 2em; width: 100%; }
|
.view__mod_pack { margin-top: 2em; width: 100%; }
|
||||||
|
|
||||||
|
.want label {
|
||||||
|
position: absolute; top: 50%; left: 0.5em;
|
||||||
|
@include transform(translateY(-50%));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -436,7 +436,7 @@
|
|||||||
"pattern": ".1. 020 .1."
|
"pattern": ".1. 020 .1."
|
||||||
}, {
|
}, {
|
||||||
"output": "Extractor",
|
"output": "Extractor",
|
||||||
"input": [[4, "Tree Tap"], "Electronic Circuit", "Machine Block"],
|
"input": [[4, "Treetap"], "Electronic Circuit", "Machine Block"],
|
||||||
"pattern": "... 020 010",
|
"pattern": "... 020 010",
|
||||||
"tools": "Crafting Table"
|
"tools": "Crafting Table"
|
||||||
}, {
|
}, {
|
||||||
@@ -1108,7 +1108,7 @@
|
|||||||
"tools": "Crafting Table"
|
"tools": "Crafting Table"
|
||||||
}, {
|
}, {
|
||||||
"output": "Wind Mill",
|
"output": "Wind Mill",
|
||||||
"input": [[4, "Iron"], "Generator"],
|
"input": [[4, "Iron Ingot"], "Generator"],
|
||||||
"pattern": "0.0 .1. 0.0",
|
"pattern": "0.0 .1. 0.0",
|
||||||
"tools": "Crafting Table"
|
"tools": "Crafting Table"
|
||||||
}, {
|
}, {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ module.exports = class BaseController extends Backbone.View
|
|||||||
@_loadTemplate options.templateName
|
@_loadTemplate options.templateName
|
||||||
super options
|
super options
|
||||||
|
|
||||||
|
@_tryRefresh = _.debounce @_tryRefresh, 100
|
||||||
|
|
||||||
# Public Methods ###############################################################################
|
# Public Methods ###############################################################################
|
||||||
|
|
||||||
addChild: (Controller, atSelector, options={})->
|
addChild: (Controller, atSelector, options={})->
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ module.exports = class ItemPageController extends BaseController
|
|||||||
options.templateName = 'item_page'
|
options.templateName = 'item_page'
|
||||||
super options
|
super options
|
||||||
|
|
||||||
|
# Event Methods ################################################################################
|
||||||
|
|
||||||
|
onToolsBoxToggled: ->
|
||||||
|
@model.plan.includingTools = @$('.includeTools:checked').length isnt 0
|
||||||
|
|
||||||
# BaseController Overrides #####################################################################
|
# BaseController Overrides #####################################################################
|
||||||
|
|
||||||
onDidRender: ->
|
onDidRender: ->
|
||||||
@@ -54,4 +59,19 @@ module.exports = class ItemPageController extends BaseController
|
|||||||
modPack: @model.modPack
|
modPack: @model.modPack
|
||||||
|
|
||||||
@modPackController = @addChild ModPackController, '.view__mod_pack', model:@model.modPack
|
@modPackController = @addChild ModPackController, '.view__mod_pack', model:@model.modPack
|
||||||
|
|
||||||
|
@$('.want .toolbar').append '<label><input class="includeTools" type="checkbox"> include tools</label'
|
||||||
|
@$includeToolsBox = @$('.includeTools')
|
||||||
|
|
||||||
super
|
super
|
||||||
|
|
||||||
|
refresh: ->
|
||||||
|
if @model.plan.includingTools
|
||||||
|
@$includeToolsBox.attr 'checked', 'checked'
|
||||||
|
else
|
||||||
|
@$includeToolsBox.removeAttr 'checked'
|
||||||
|
|
||||||
|
# Backbone.View Overrides ######################################################################
|
||||||
|
|
||||||
|
events:
|
||||||
|
'change .includeTools': 'onToolsBoxToggled'
|
||||||
|
|||||||
@@ -25,16 +25,14 @@ module.exports = class CraftingPlan extends BaseModel
|
|||||||
@have.on 'change', => @craft()
|
@have.on 'change', => @craft()
|
||||||
@want.on 'change', => @craft()
|
@want.on 'change', => @craft()
|
||||||
@modPack.on 'change', => @craft()
|
@modPack.on 'change', => @craft()
|
||||||
|
@on 'change:includingTools', => @craft()
|
||||||
|
|
||||||
@clear()
|
@clear()
|
||||||
|
|
||||||
# Public Methods ###############################################################################
|
# Public Methods ###############################################################################
|
||||||
|
|
||||||
clear: ->
|
clear: ->
|
||||||
@steps = []
|
@steps = []
|
||||||
@_expected = new Inventory
|
|
||||||
@_pending = null
|
|
||||||
|
|
||||||
@need.clear()
|
@need.clear()
|
||||||
@result.clear()
|
@result.clear()
|
||||||
|
|
||||||
@@ -42,22 +40,18 @@ module.exports = class CraftingPlan extends BaseModel
|
|||||||
return this
|
return this
|
||||||
|
|
||||||
craft: ->
|
craft: ->
|
||||||
logger.trace "starting crafting plan for: #{@want} starting with #{@have}"
|
|
||||||
@clear()
|
@clear()
|
||||||
return if @want.isEmpty
|
|
||||||
|
|
||||||
@want.each (stack)=>
|
|
||||||
@_expected = @want.clone()
|
|
||||||
@_pending = @want.clone()
|
|
||||||
|
|
||||||
@result.addInventory @have
|
@result.addInventory @have
|
||||||
|
|
||||||
@_need = new Inventory
|
@steps = {}
|
||||||
while not @_pending.isEmpty
|
@want.each (stack)=>
|
||||||
@_processPending()
|
@_findSteps stack.itemSlug
|
||||||
|
@need.add stack.itemSlug, stack.quantity
|
||||||
|
|
||||||
@need.addInventory @_need
|
@steps = _.values @steps
|
||||||
@steps.reverse()
|
@_resolveNeeds()
|
||||||
|
@_removeExtraSteps()
|
||||||
|
@result.addInventory @want
|
||||||
|
|
||||||
@trigger 'change', this
|
@trigger 'change', this
|
||||||
|
|
||||||
@@ -74,53 +68,67 @@ module.exports = class CraftingPlan extends BaseModel
|
|||||||
|
|
||||||
# Private Methods ##############################################################################
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
_processPending: ->
|
_addStep: (recipe)->
|
||||||
targetStack = @_pending.pop()
|
return if @_hasStep recipe.slug
|
||||||
targetItem = @modPack.findItem targetStack.itemSlug
|
logger.verbose "adding step: #{recipe.slug}"
|
||||||
logger.verbose "processing item: #{targetStack}"
|
@steps[recipe.slug] = recipe:recipe
|
||||||
return unless targetItem?
|
|
||||||
return if (not targetItem.isCraftable) or targetItem.isGatherable
|
|
||||||
|
|
||||||
recipe = targetItem.recipes[0]
|
_chooseRecipe: (item)->
|
||||||
logger.verbose "recipe: #{recipe}"
|
return item.recipes[0]
|
||||||
|
|
||||||
|
_findSteps: (itemSlug)->
|
||||||
|
item = @modPack.findItem itemSlug
|
||||||
|
return unless item?
|
||||||
|
return unless item.isCraftable
|
||||||
|
return if item.isGatherable
|
||||||
|
|
||||||
|
recipe = @_chooseRecipe item
|
||||||
|
|
||||||
if @includingTools
|
if @includingTools
|
||||||
for toolStack in recipe.tools
|
for toolStack in recipe.tools
|
||||||
slug = toolStack.itemSlug
|
if not @_hasStep toolStack.itemSlug
|
||||||
totalExpected = @result.quantityOf(slug) + @_expected.quantityOf(slug)
|
@_findSteps toolStack.itemSlug
|
||||||
if totalExpected < 1
|
|
||||||
@_pending.add slug
|
|
||||||
@_expected.add slug
|
|
||||||
|
|
||||||
while @_totalQuantityOf(targetItem.slug) < @_expected.quantityOf(targetItem.slug)
|
for inputStack in recipe.input
|
||||||
@steps.push recipe
|
@_findSteps inputStack.itemSlug
|
||||||
|
|
||||||
|
@_addStep recipe
|
||||||
|
|
||||||
|
_hasStep: (itemSlug)->
|
||||||
|
return @steps[itemSlug]?
|
||||||
|
|
||||||
|
_removeExtraSteps: ->
|
||||||
|
result = (step for step in @steps when step.multiplier > 0)
|
||||||
|
@steps = result
|
||||||
|
|
||||||
|
_resolveNeeds: ->
|
||||||
|
for i in [@steps.length-1..0] by -1
|
||||||
|
step = @steps[i]
|
||||||
|
recipe = step.recipe
|
||||||
|
|
||||||
|
step.multiplier = Math.ceil(@need.quantityOf(recipe.slug) / step.recipe.output[0].quantity)
|
||||||
|
|
||||||
|
if @includingTools
|
||||||
|
for stack in recipe.tools
|
||||||
|
slug = stack.itemSlug
|
||||||
|
available = @result.quantityOf(slug) + @need.quantityOf(slug)
|
||||||
|
needed = Math.max 0, stack.quantity - available
|
||||||
|
|
||||||
|
@need.add stack.itemSlug, needed
|
||||||
|
@result.add stack.itemSlug, needed
|
||||||
|
|
||||||
for stack in recipe.input
|
for stack in recipe.input
|
||||||
@_processInputStack stack
|
needed = step.multiplier * stack.quantity
|
||||||
|
consumed = Math.min needed, @result.quantityOf(stack.itemSlug)
|
||||||
|
remaining = needed - consumed
|
||||||
|
|
||||||
|
@result.remove stack.itemSlug, consumed
|
||||||
|
@need.add stack.itemSlug, remaining
|
||||||
|
|
||||||
for stack in recipe.output
|
for stack in recipe.output
|
||||||
@_processOutputStack stack
|
created = stack.quantity * step.multiplier
|
||||||
|
consumed = Math.min created, @need.quantityOf stack.itemSlug
|
||||||
|
remaining = created - consumed
|
||||||
|
|
||||||
_processInputStack: (stack)->
|
@result.add stack.itemSlug, remaining
|
||||||
quantityAvailable = @result.quantityOf stack.itemSlug
|
@need.remove stack.itemSlug, consumed
|
||||||
quantityUsed = Math.min quantityAvailable, stack.quantity
|
|
||||||
quantityNeeded = stack.quantity - quantityUsed
|
|
||||||
logger.trace "processing input:#{stack.itemSlug},
|
|
||||||
a:#{quantityAvailable}, u:#{quantityUsed}, n:#{quantityNeeded}"
|
|
||||||
|
|
||||||
@result.remove stack.itemSlug, quantityUsed
|
|
||||||
@_pending.add stack.itemSlug, quantityNeeded
|
|
||||||
@_need.add stack.itemSlug, quantityNeeded
|
|
||||||
|
|
||||||
_processOutputStack: (stack)->
|
|
||||||
quantityMissing = @_need.quantityOf stack.itemSlug
|
|
||||||
quantityUsed = Math.min quantityMissing, stack.quantity
|
|
||||||
quantityLeft = stack.quantity - quantityUsed
|
|
||||||
logger.trace "processing output:#{stack.itemSlug},
|
|
||||||
m:#{quantityMissing}, u:#{quantityUsed}, l:#{quantityLeft}"
|
|
||||||
|
|
||||||
@_need.remove stack.itemSlug, quantityUsed
|
|
||||||
@result.add stack.itemSlug, quantityLeft
|
|
||||||
|
|
||||||
_totalQuantityOf: (itemSlug)->
|
|
||||||
return @result.quantityOf(itemSlug) - @_need.quantityOf(itemSlug)
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ module.exports = class CraftingTable extends BaseModel
|
|||||||
|
|
||||||
@plan.on 'change', => @reset()
|
@plan.on 'change', => @reset()
|
||||||
@_step = 0
|
@_step = 0
|
||||||
@_steps = []
|
|
||||||
|
|
||||||
Object.defineProperties this, {
|
Object.defineProperties this, {
|
||||||
hasNextStep: { get:@hasNextStep }
|
hasNextStep: { get:@hasNextStep }
|
||||||
@@ -36,29 +35,27 @@ module.exports = class CraftingTable extends BaseModel
|
|||||||
# Public Methods ###############################################################################
|
# Public Methods ###############################################################################
|
||||||
|
|
||||||
reset: ->
|
reset: ->
|
||||||
@_compactSteps()
|
|
||||||
@step = 0
|
@step = 0
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
|
||||||
# Property Methods #############################################################################
|
# Property Methods #############################################################################
|
||||||
|
|
||||||
hasNextStep: ->
|
hasNextStep: ->
|
||||||
return @_step + 1 < @_steps.length
|
return @_step + 1 < @plan.steps.length
|
||||||
|
|
||||||
hasPrevStep: ->
|
hasPrevStep: ->
|
||||||
return @_step > 0
|
return @_step > 0
|
||||||
|
|
||||||
hasSteps: ->
|
hasSteps: ->
|
||||||
return @_steps.length > 0
|
return @plan.steps.length > 0
|
||||||
|
|
||||||
getMultiplier: ->
|
getMultiplier: ->
|
||||||
step = @_steps[@_step]
|
step = @plan.steps[@_step]
|
||||||
return unless step?
|
return unless step?
|
||||||
return step.multiplier
|
return step.multiplier
|
||||||
|
|
||||||
getOutput: ->
|
getOutput: ->
|
||||||
step = @_steps[@_step]
|
step = @plan.steps[@_step]
|
||||||
return unless step?
|
return unless step?
|
||||||
return step.recipe.output[0]
|
return step.recipe.output[0]
|
||||||
|
|
||||||
@@ -66,20 +63,23 @@ module.exports = class CraftingTable extends BaseModel
|
|||||||
return @_step
|
return @_step
|
||||||
|
|
||||||
setStep: (newStep)->
|
setStep: (newStep)->
|
||||||
newStep = Math.max 0, Math.min @_steps.length - 1, newStep
|
oldStep = @_step
|
||||||
|
newStep = Math.max 0, Math.min @plan.steps.length - 1, newStep
|
||||||
|
|
||||||
@_step = newStep
|
@_step = newStep
|
||||||
@grid.recipe = @_steps[@_step]?.recipe
|
@grid.recipe = @plan.steps[@_step]?.recipe
|
||||||
|
|
||||||
|
@trigger 'change:step', this, oldStep, newStep
|
||||||
@trigger 'change', this
|
@trigger 'change', this
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
|
||||||
getStepCount: ->
|
getStepCount: ->
|
||||||
return 0 unless @_steps?
|
return 0 unless @plan.steps?
|
||||||
return @_steps.length
|
return @plan.steps.length
|
||||||
|
|
||||||
getToolNames: ->
|
getToolNames: ->
|
||||||
recipe = @_steps[@_step]?.recipe
|
recipe = @plan.steps[@_step]?.recipe
|
||||||
return '' unless recipe?
|
return '' unless recipe?
|
||||||
toolSlugs = (stack.itemSlug for stack in recipe.tools)
|
toolSlugs = (stack.itemSlug for stack in recipe.tools)
|
||||||
toolNames = (@modPack.findName(slug) for slug in toolSlugs).join ', '
|
toolNames = (@modPack.findName(slug) for slug in toolSlugs).join ', '
|
||||||
@@ -89,18 +89,3 @@ module.exports = class CraftingTable extends BaseModel
|
|||||||
|
|
||||||
toString: ->
|
toString: ->
|
||||||
return "#{@constructor.name} (#{@cid}) { plan:#{@plan}, step:#{@_step} }"
|
return "#{@constructor.name} (#{@cid}) { plan:#{@plan}, step:#{@_step} }"
|
||||||
|
|
||||||
# Private Methods ##############################################################################
|
|
||||||
|
|
||||||
_compactSteps: ->
|
|
||||||
steps = {}
|
|
||||||
|
|
||||||
for recipe in @plan.steps
|
|
||||||
step = steps[recipe.name]
|
|
||||||
if not step?
|
|
||||||
steps[recipe.name] = multiplier:1, recipe:recipe
|
|
||||||
else
|
|
||||||
step.multiplier += 1
|
|
||||||
|
|
||||||
@_steps = (step for name, step of steps)
|
|
||||||
return this
|
|
||||||
|
|||||||
@@ -22,23 +22,14 @@ module.exports = class Inventory extends BaseModel
|
|||||||
# Public Methods ###############################################################################
|
# Public Methods ###############################################################################
|
||||||
|
|
||||||
add: (itemSlug, quantity=1)->
|
add: (itemSlug, quantity=1)->
|
||||||
return if quantity is 0
|
@_add itemSlug, quantity
|
||||||
|
|
||||||
stack = @_stacks[itemSlug]
|
|
||||||
if not stack?
|
|
||||||
stack = new Stack itemSlug:itemSlug, quantity:quantity
|
|
||||||
@_stacks[itemSlug] = stack
|
|
||||||
@_slugs.push itemSlug
|
|
||||||
@_slugs.sort()
|
|
||||||
else
|
|
||||||
stack.quantity += quantity
|
|
||||||
|
|
||||||
@trigger Event.add, this, itemSlug, quantity
|
@trigger Event.add, this, itemSlug, quantity
|
||||||
@trigger Event.change, this
|
@trigger Event.change, this
|
||||||
return this
|
return this
|
||||||
|
|
||||||
addInventory: (inventory)->
|
addInventory: (inventory)->
|
||||||
inventory.each (stack)=> @add stack.itemSlug, stack.quantity
|
inventory.each (stack)=> @_add stack.itemSlug, stack.quantity
|
||||||
|
@trigger Event.change, this
|
||||||
return this
|
return this
|
||||||
|
|
||||||
clear: ->
|
clear: ->
|
||||||
@@ -122,3 +113,17 @@ module.exports = class Inventory extends BaseModel
|
|||||||
|
|
||||||
result.push '}'
|
result.push '}'
|
||||||
return result.join ''
|
return result.join ''
|
||||||
|
|
||||||
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
_add: (itemSlug, quantity=1)->
|
||||||
|
return if quantity is 0
|
||||||
|
|
||||||
|
stack = @_stacks[itemSlug]
|
||||||
|
if not stack?
|
||||||
|
stack = new Stack itemSlug:itemSlug, quantity:quantity
|
||||||
|
@_stacks[itemSlug] = stack
|
||||||
|
@_slugs.push itemSlug
|
||||||
|
@_slugs.sort()
|
||||||
|
else
|
||||||
|
stack.quantity += quantity
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ module.exports = class Recipe extends BaseModel
|
|||||||
attributes.tools ?= []
|
attributes.tools ?= []
|
||||||
super attributes, options
|
super attributes, options
|
||||||
|
|
||||||
Object.defineProperty @prototype, 'name', get:-> @item.name
|
Object.defineProperties this,
|
||||||
|
'name': { get: -> @item.name }
|
||||||
|
'slug': { get: -> @item.slug }
|
||||||
|
|
||||||
# Public Methods ###############################################################################
|
# Public Methods ###############################################################################
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user