Initial version of the new crafting table

This commit is contained in:
Andrew Miner
2015-01-08 11:03:43 -08:00
parent 9f79722378
commit 9424af9d84
26 changed files with 280 additions and 228 deletions
+1
View File
@@ -32,6 +32,7 @@ $color-footer: #3D1D09;
$color-footer-text: white; $color-footer-text: white;
$color-gray-faint: #F2F2F2; $color-gray-faint: #F2F2F2;
$color-gray-light: #CCCCCC; $color-gray-light: #CCCCCC;
$color-gray-medium: #A6A6A6;
$color-table-background: white; $color-table-background: white;
$color-toolbar-background: rgba(255, 255, 255, 0.75); $color-toolbar-background: rgba(255, 255, 255, 0.75);
+17
View File
@@ -0,0 +1,17 @@
/*
Crafting Table - crafting_grid.scss
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
*/
.view__crafting_grid {
img {
position: relative; height:4.8em; width: 4.8em;
}
td {
border: 1px solid $color-gray-light;
}
}
+7 -40
View File
@@ -6,49 +6,16 @@ All rights reserved.
*/ */
.view__crafting_table { .view__crafting_table {
min-height: 14em;
width: 100%;
.recipe_selector { .panel {
position: absolute; top: 5em; right: 2em; bottom: 0; left: 2em;
background: $color-table-background; background: $color-table-background;
padding: 1em;
position: relative; width: 100%;
& > * { .view__crafting_grid {
display: inline; position: absolute; top: 50%; left: 33%;
margin-left: 0.5em; @include transform(translate(-50%, -50%));
&:first-child { margin-left: 0; }
}
input[type="checkbox"] + label { margin-left: 0; }
input[name="name"] { width: 60%; }
}
h3 {
margin-bottom: 0.5em;
}
table.main {
background: $color-table-background; width: 100%;
td.list {
position: relative;
border-left: 0.1em solid $color-gray-light;
min-height: 12em;
padding: 0 1em 1em 1em;
width: 25%;
&:first-child { border-left: 0; }
} }
} }
textarea, table.list {
position: relative; height: 100%; width: 100%;
font-size: $font-size-normal;
padding: 0.2em;
}
textarea { font-family: $font-family-input; resize: vertical; }
ul { font-family: $font-family-normal; }
} }
+1
View File
@@ -5,6 +5,7 @@ Copyright (c) 2014-2015 by Redwood Labs
All rights reserved. All rights reserved.
*/ */
@import 'crafting_grid';
@import 'crafting_table'; @import 'crafting_table';
@import 'inventory'; @import 'inventory';
@import 'item_page'; @import 'item_page';
+6 -3
View File
@@ -44,11 +44,11 @@ All rights reserved.
} }
td { td {
height: 3.6em; height: 2.4em;
padding-bottom: 0.25em; padding-bottom: 0.25em;
&:nth-child(1) { &:nth-child(1) {
width: 3.6em; width: 2.4em;
input { input {
border-radius: 0.75em; border-radius: 0.75em;
@@ -75,7 +75,10 @@ All rights reserved.
} }
&:nth-child(3) { &:nth-child(3) {
width: 3.6em; width: 2.4em;
text-align: right;
img { width: 2.4em; height: 2.4em; }
button { button {
width: 100%; width: 100%;
+2
View File
@@ -17,5 +17,7 @@ All rights reserved.
.view__inventory { width: 50%; height: 26em; } .view__inventory { 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%; }
} }
+2 -2
View File
@@ -13,7 +13,7 @@ All rights reserved.
border-radius: 0.75em; border-radius: 0.75em;
background: $color-ice; background: $color-ice;
color: $color-table-background; color: $color-table-background;
font-size: $font-size-large; font-size: $font-size-normal;
font-weight: bold; font-weight: bold;
text-align: center; text-align: center;
min-width: 3em; min-width: 3em;
@@ -23,7 +23,7 @@ All rights reserved.
.name { .name {
display: inline; display: inline;
font-size: $font-size-large; font-size: $font-size-normal;
} }
img { img {
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

@@ -0,0 +1,52 @@
###
Crafting Guide - crafting_grid_controller.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
BaseController = require './base_controller'
ImageLoader = require './image_loader'
{ImageUrl} = require '../constants'
util = require 'util'
########################################################################################################################
module.exports = class CraftingGridController extends BaseController
@EMPTY_IMAGE = '/images/empty.png'
constructor: (options={})->
if not options.model? then throw new Error 'options.model is required'
options.imageLoader ?= new ImageLoader default:'/images/unknown.png'
options.templateName = 'crafting_grid'
super options
@_imageLoader = options.imageLoader
# BaseController Methods #######################################################################
onDidRender: ->
@slots = []
for el in @$('td')
$el = $(el)
@slots.push a:$el.find('a'), img:$el.find('img')
super
refresh: ->
for index in [0...@slots.length]
slot = @slots[index]
slot.a.addClass 'empty'
slot.a.removeAttr 'href'
slot.img.attr 'src', CraftingGridController.EMPTY_IMAGE
slot.img.removeAttr 'alt'
itemData = @model.getItemDataAt index
if itemData?
slot.a.removeClass 'empty'
slot.a.attr 'href', "/items/#{encodeURIComponent(itemData.name)}"
logger.debug "item data: #{util.inspect(itemData)}"
@_imageLoader.load ImageUrl(itemData), slot.img
slot.img.attr 'alt', itemData.name
super
@@ -5,14 +5,8 @@ Copyright (c) 2014-2015 by Redwood Labs
All rights reserved. All rights reserved.
### ###
BaseController = require './base_controller' BaseController = require './base_controller'
{Duration} = require '../constants' CraftingGridController = require './crafting_grid_controller'
{Event} = require '../constants'
InventoryParser = require '../models/inventory_parser'
{Key} = require '../constants'
StackController = require './stack_controller'
url = require 'url'
{UrlParam} = require '../constants'
######################################################################################################################## ########################################################################################################################
@@ -23,139 +17,11 @@ module.exports = class CraftingTableController extends BaseController
options.templateName = 'crafting_table' options.templateName = 'crafting_table'
super options super options
@_parser = new InventoryParser
@_resetStackControllers()
@model.modPack.on Event.change, => @onModPackChanged()
# Event Methods ################################################################################
onModPackChanged: ->
return unless @rendered
@model.modPack.enableModsForItem @$nameField.val()
@_updateNameAutocomplete()
@_craft()
onHaveFieldChanged: ->
return unless @rendered
@model.have.clear()
@_parser.parse @$haveField.val(), @model.have
@_craft()
onIncludingToolsFieldChanged: ->
return unless @rendered
@model.includingTools = @$('input[name="including_tools"]:checked').length > 0
@_craft()
onNameFieldChanged: ->
return unless @rendered
name = @$nameField.val()
@model.name = name
@_craft()
if name.length is 0
setTimeout (=> @$nameField.blur()), Duration.snap
onNameFieldFocused: ->
return unless @rendered
@$nameField.val ""
@$nameField.autocomplete 'search'
onNameFieldKeyPress: (event)->
if event.which is Key.Return
@$nameField.autocomplete('close')
onQuantityFieldChanged: ->
return unless @rendered
@model.quantity = parseInt @$quantityField.find(":selected").val()
@_craft()
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidRender: ->
@$haveField = @$('textarea[name="have"]') @gridController = @addChild CraftingGridController, '.view__crafting_grid', model:@model.grid
@$includingToolsField = @$('input[name="including_tools"]')
@$nameField = @$('input[name="name"]')
@$quantityField = @$('select[name="quantity"]')
@$needList = @$('td.need table')
@$makeList = @$('td.make table')
@$resultList = @$('td.result table')
@_updateNameAutocomplete()
@_craft()
@$nextButton = @$('button[name="next"]')
@$prevButton = @$('button[name="prev"]')
super super
refresh: ->
@$nameField.val @model.name
@$quantityField.val @model.quantity
if @model.includingTools
@$includingToolsField.attr 'checked', 'checked'
else
@$includingToolsField.removeAttr 'checked'
@$needList.empty()
@$makeList.empty()
@$resultList.empty()
makeController = (name, stack)=>
controller = new StackController model:stack, modPack:@model.modPack
controller.render()
this["$#{name}List"].append controller.$el
this["_#{name}Controllers"].push controller
if @model.plan?
@_resetStackControllers()
@model.plan.need.each (stack)=> makeController 'need', stack
slugs = {}
for recipe in @model.plan.steps
slug = recipe.item.slug
if not slugs[slug]?
slugs[slug] = true
stack = @model.plan.make.getStack slug
makeController 'make', stack
@model.plan.result.each (stack)=> makeController 'result', stack
super
# Backbone.View Overrides ######################################################################
events:
'input textarea[name="have"]': 'onHaveFieldChanged'
'focus input[name="name"]': 'onNameFieldFocused'
'input input[name="name"]': 'onNameFieldChanged'
'keypress input[name="name"]': 'onNameFieldKeyPress'
'input select[name="quantity"]': 'onQuantityFieldChanged'
'change input[name="including_tools"]': 'onIncludingToolsFieldChanged'
# Private Methods ##############################################################################
_craft: ->
if @model.modPack.hasRecipe @model.name
router.navigate "/item/#{encodeURIComponent(@model.name)}"
else
router.navigate "/item"
@model.craft()
@refresh()
_resetStackControllers: ->
@_needControllers = []
@_makeControllers = []
@_resultControllers = []
_updateNameAutocomplete: ->
onChanged = => @onNameFieldChanged()
@$nameField.autocomplete
source: @model.modPack.gatherRecipeNames()
delay: 0
minLength: 0
change: onChanged
close: onChanged
select: onChanged
+2 -1
View File
@@ -38,7 +38,8 @@ module.exports = class ImageLoader
load: (imageUrl, $el)-> load: (imageUrl, $el)->
data = @preload imageUrl data = @preload imageUrl
return if $el.attr('src').indexOf(imageUrl) isnt -1 if $el.attr('src')?
return if $el.attr('src').indexOf(imageUrl) isnt -1
if @onLoading? then @onLoading.call $el if @onLoading? then @onLoading.call $el
$el.data 'isLoading', true $el.data 'isLoading', true
@@ -62,5 +62,6 @@ module.exports = class ItemPageController extends BaseController
title: "Items you'll need" title: "Items you'll need"
@needController = @addChild InventoryController, '.need', options @needController = @addChild InventoryController, '.need', options
@craftingTableController = @addChild CraftingTableController, '.view__crafting_table', model:@model.table
@modPackController = @addChild ModPackController, '.view__mod_pack', model:@model.modPack @modPackController = @addChild ModPackController, '.view__mod_pack', model:@model.modPack
super super
@@ -0,0 +1,27 @@
###
Crafting Guide - recipe_step_controller.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
BaseController = require './base_controller'
########################################################################################################################
module.exports = class RecipeStepController extends BaseController
constructor: (options={})->
if not options.model? then throw new Error 'options.model is required'
if not options.modPack? then throw new Error 'options.modPack is required'
options.templateName = 'recipe_step'
super options
# BaseController Overrides #####################################################################
onDidRender: ->
@$slotImages = (@$slots.push $(el) for el in @$('.table-slot img'))
@$output = @$('.output')
super
refresh: ->
+4
View File
@@ -22,6 +22,10 @@ module.exports = class BaseModel extends Backbone.Model
sync: -> # do nothing sync: -> # do nothing
trigger: (name)->
logger.trace "#{@constructor.name}.#{@cid} triggered a \"#{name}\" event"
super
# Object Overrides ############################################################################# # Object Overrides #############################################################################
toString: -> toString: ->
+41
View File
@@ -0,0 +1,41 @@
###
Crafting Guide - crafting_grid.coffee
Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
BaseModel = require './base_model'
util = require 'util'
########################################################################################################################
module.exports = class CraftingGrid extends BaseModel
@SLOT_COUNT = 9
constructor: (attributes={}, options={})->
if not attributes.modPack? then throw new Error 'attributes.modPack is required'
attributes.recipe ?= null
super attributes, options
Object.defineProperty @prototype, 'slotCount', get:-> CraftingGrid.SLOT_COUNT
# Public Methods ###############################################################################
getItemDataAt: (index)->
if index >= @slotCount then throw new Error "index (#{index}) must be less than #{@slotCount}"
return null unless @recipe?
logger.debug "recipe: #{@recipe}"
itemSlug = @recipe.getItemSlugAt index
return null unless itemSlug?
item = @modPack.findItem itemSlug
if item?
itemData = item.pathSlugs
itemData.name = item.name
return itemData
else
return modSlug:'minecraft', itemSlug:itemSlug, name:@modPack.findName(itemSlug)
+9 -4
View File
@@ -5,15 +5,17 @@ Copyright (c) 2014-2015 by Redwood Labs
All rights reserved. All rights reserved.
### ###
BaseModel = require './base_model'
Inventory = require './inventory' Inventory = require './inventory'
######################################################################################################################## ########################################################################################################################
module.exports = class CraftingPlan module.exports = class CraftingPlan extends BaseModel
constructor: (@modPack, includingTools)-> constructor: (attributes={}, options={})->
if not @modPack then throw new Error 'modPack is required' if not attributes.modPack then throw new Error 'modPack is required'
@includingTools = if includingTools then true else false attributes.includingTools ?= false
super attributes, options
@have = new Inventory @have = new Inventory
@want = new Inventory @want = new Inventory
@@ -35,6 +37,7 @@ module.exports = class CraftingPlan
@need.clear() @need.clear()
@result.clear() @result.clear()
@trigger 'change', this
return this return this
craft: -> craft: ->
@@ -55,6 +58,8 @@ module.exports = class CraftingPlan
@need.addInventory @_need @need.addInventory @_need
@steps.reverse() @steps.reverse()
@trigger 'change', this
# Object Overrides ############################################################################# # Object Overrides #############################################################################
toString: -> toString: ->
+15 -3
View File
@@ -6,9 +6,7 @@ All rights reserved.
### ###
BaseModel = require './base_model' BaseModel = require './base_model'
CraftingPlan = require './crafting_plan' CraftingGrid = require './crafting_grid'
{Event} = require '../constants'
Inventory = require './inventory'
######################################################################################################################## ########################################################################################################################
@@ -16,9 +14,23 @@ module.exports = class CraftingTable extends BaseModel
constructor: (attributes={}, options={})-> constructor: (attributes={}, options={})->
if not attributes.plan? then throw new Error "attributes.plan is required" if not attributes.plan? then throw new Error "attributes.plan is required"
attributes.grid ?= new CraftingGrid modPack:attributes.plan.modPack
attributes.step ?= 0 attributes.step ?= 0
super attributes, options super attributes, options
@plan.on 'change', => @reset()
# Public Methods ###############################################################################
reset: ->
logger.trace "CraftingTable.reset()"
@step = 0
@grid.recipe = @plan.steps[0]
@trigger 'change', this
return this
# Object Overrides ############################################################################# # Object Overrides #############################################################################
toString: -> toString: ->
+5
View File
@@ -25,6 +25,8 @@ module.exports = class Item extends BaseModel
Object.defineProperty @prototype, 'isCraftable', get:-> @recipes.length > 0 Object.defineProperty @prototype, 'isCraftable', get:-> @recipes.length > 0
Object.defineProperty @prototype, 'pathSlugs', get:-> @getPathSlugs()
# Public Methods ############################################################################### # Public Methods ###############################################################################
addRecipe: (recipe)-> addRecipe: (recipe)->
@@ -38,6 +40,9 @@ module.exports = class Item extends BaseModel
return if this.name < that.name then -1 else +1 return if this.name < that.name then -1 else +1
return 0 return 0
getPathSlugs: ->
return modSlug:@modVersion.slug, itemSlug:@slug
# Object Overrides ############################################################################# # Object Overrides #############################################################################
toString: -> toString: ->
+6 -4
View File
@@ -5,9 +5,10 @@ Copyright (c) 2014-2015 by Redwood Labs
All rights reserved. All rights reserved.
### ###
BaseModel = require './base_model' BaseModel = require './base_model'
CraftingPlan = require './crafting_plan' CraftingPlan = require './crafting_plan'
ModPack = require './mod_pack' CraftingTable = require './crafting_table'
ModPack = require './mod_pack'
######################################################################################################################## ########################################################################################################################
@@ -15,5 +16,6 @@ module.exports = class ItemPage extends BaseModel
constructor: (attributes={}, options={})-> constructor: (attributes={}, options={})->
attributes.modPack ?= new ModPack attributes.modPack ?= new ModPack
attributes.plan ?= new CraftingPlan attributes.modPack attributes.plan ?= new CraftingPlan modPack:attributes.modPack
attributes.table ?= new CraftingTable plan:attributes.plan
super attributes, options super attributes, options
+7 -1
View File
@@ -6,6 +6,7 @@ All rights reserved.
### ###
Item = require './item' Item = require './item'
Logger = require '../logger'
ModVersion = require './mod_version' ModVersion = require './mod_version'
Recipe = require './recipe' Recipe = require './recipe'
Stack = require './stack' Stack = require './stack'
@@ -28,7 +29,12 @@ module.exports = class ModVersionParser
parser = @_parsers["#{data.dataVersion}"] parser = @_parsers["#{data.dataVersion}"]
if not parser? then throw new Error "cannot parse version #{data.dataVersion} mod descriptions" if not parser? then throw new Error "cannot parse version #{data.dataVersion} mod descriptions"
return parser.parse data oldLevel = logger.level
logger.level = Logger.WARNING
result = parser.parse data
logger.level = oldLevel
return result
unparse: (modVersion, dataVersion=ModVersionParser.CURRENT_VERSION)-> unparse: (modVersion, dataVersion=ModVersionParser.CURRENT_VERSION)->
if not modVersion? then throw new Error 'modVersion is required' if not modVersion? then throw new Error 'modVersion is required'
+20 -1
View File
@@ -16,7 +16,7 @@ module.exports = class Recipe extends BaseModel
if not attributes.input? then throw new Error 'attributes.input is required' if not attributes.input? then throw new Error 'attributes.input is required'
if not attributes.output? then throw new Error 'attributes.output is required' if not attributes.output? then throw new Error 'attributes.output is required'
attributes.pattern ?= (i for i in [0...attributes.input.length]).join('') attributes.pattern ?= @_computeShapelessPattern attributes.input
attributes.tools ?= [] attributes.tools ?= []
super attributes, options super attributes, options
@@ -24,6 +24,15 @@ module.exports = class Recipe extends BaseModel
# Public Methods ############################################################################### # Public Methods ###############################################################################
getItemSlugAt: (index)->
patternDigit = @pattern[index]
return null unless patternDigit?
stack = @input[parseInt(patternDigit)]
return null unless stack?
return stack.itemSlug
make: (inventory, missing)-> make: (inventory, missing)->
for stack in @input for stack in @input
itemSlug = stack.itemSlug itemSlug = stack.itemSlug
@@ -71,3 +80,13 @@ module.exports = class Recipe extends BaseModel
result.push '}' result.push '}'
return result.join '' return result.join ''
# Private Methods ##############################################################################
_computeShapelessPattern: (input)->
result = []
for i in [0...input.length]
stack = input[i]
for j in [0...stack.quantity]
result.push "#{i}"
return result.join ''
+26
View File
@@ -0,0 +1,26 @@
###
Crafting Guide - recipe_step.coffee
Copyright (c) 2014 by Redwood Labs
All rights reserved.
###
BaseModel = require './base_model'
########################################################################################################################
module.exports = class RecipeStep extends BaseModel
constructor: (attributes={}, options={})->
if not attributes.recipe? then throw new Error 'attributes.recipe is required'
attributes.multiple ?= 1
super attributes, options
@recipe.on 'change', =>
@trigger 'change:recipe'
@trigger 'change'
# Public Methods ###############################################################################
getItemAt: (index)->
return @recipe.getItemAt index
-2
View File
@@ -13,6 +13,4 @@ _.mixin
result = text.toLowerCase() result = text.toLowerCase()
result = result.replace /[^a-zA-Z0-9_]/g, '_' result = result.replace /[^a-zA-Z0-9_]/g, '_'
result = result.replace /__+/, '_' result = result.replace /__+/, '_'
result = result.replace /_$/, ''
result = result.replace /^_/, ''
return result return result
+20
View File
@@ -0,0 +1,20 @@
//-
//- Crafting Guide - crafting_grid.jade
//-
//- Copyright (c) 2015 by Redwood Labs
//- All rights reserved.
//-
table.view__crafting_grid
tr
td: a: img(src="/images/empty.png")
td: a: img(src="/images/empty.png")
td: a: img(src="/images/empty.png")
tr
td: a: img(src="/images/empty.png")
td: a: img(src="/images/empty.png")
td: a: img(src="/images/empty.png")
tr
td: a: img(src="/images/empty.png")
td: a: img(src="/images/empty.png")
td: a: img(src="/images/empty.png")
+2 -28
View File
@@ -10,31 +10,5 @@
img(src="/images/workbench_top.png") img(src="/images/workbench_top.png")
p Crafting Table p Crafting Table
.recipe_selector .panel
p I want to make table.view__crafting_grid
select(name="quantity")
option(value="1") 1
option(value="2") 2
option(value="4") 4
option(value="8") 8
option(value="16") 16
option(value="64") 64
input(name="name", placeholder="enter an item name")
label
input(name="including_tools", type="checkbox")
| including tools
table.main
tr
td.have.list
h3: p You have...
textarea(name="have", placeholder="For example:\n\n3 wool\n4 iron ingot", rows="12")
td.need.list
h3: p You'll need...
table.list
td.make.list
h3: p You'll make...
table.list
td.result.list
h3: p You'll get...
table.list
+2
View File
@@ -10,4 +10,6 @@
.view__inventory.want .view__inventory.want
.view__inventory.need .view__inventory.need
.view__crafting_table
.view__mod_pack .view__mod_pack