Files
website/src/client/models/crafting/simple_inventory.coffee
T
2016-05-05 21:20:41 -07:00

213 lines
6.2 KiB
CoffeeScript

#
# Crafting Guide - simple_inventory.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
ItemSlug = require '../game/item_slug'
SimpleStack = require './simple_stack'
########################################################################################################################
module.exports = class SimpleInventory
constructor: (attributes={}, options={})->
@clear()
if options.modPack?
@modPack = options.modPack
if options.clone?
@addInventory options.clone
# Class Methods ################################################################################
@Delimiters =
Item: '.'
Stack: ':'
# Public Methods ###############################################################################
add: (itemSlug, quantity=1)->
return this unless quantity > 0
@_add itemSlug, quantity
return this
addInventory: (inventory)->
inventory.each (stack)=> @_add stack.itemSlug, stack.quantity
return this
clear: (options={})->
@_stacks = {}
@_itemSlugs = []
clone: ->
inventory = new SimpleInventory
inventory.addInventory this
return inventory
each: (callback)->
for itemSlug in @_itemSlugs
callback @_stacks[itemSlug]
getSlugs: ->
return @_itemSlugs[..]
hasAtLeast: (itemSlug, quantity=1)->
if quantity is 0 then return true
stack = @_stacks[itemSlug]
return false unless stack?
return stack.quantity >= quantity
localize: ->
if not @modPack? then throw new Error 'localize requires @modPack'
changed = false
newSlugs = []
newStacks = []
for itemSlug in @_itemSlugs
stack = @_stacks[itemSlug]
continue unless stack?
qualifiedSlug = if itemSlug.isQualified then itemSlug else null
if not qualifiedSlug?
qualifiedSlug = @modPack.findItem(itemSlug)?.slug
changed = qualifiedSlug?
if qualifiedSlug?
newSlugs.push qualifiedSlug
newStacks.push new SimpleStack itemSlug:qualifiedSlug, quantity:stack.quantity
else
newSlugs.push itemSlug
newStacks.push stack
if changed
@_itemSlugs = newSlugs
@_stacks = {}
for stack in newStacks
@_stacks[stack.itemSlug] = stack
@_sort()
pop: ->
itemSlug = @_itemSlugs.pop()
return null unless itemSlug?
stack = @_stacks[itemSlug]
delete @_stacks[itemSlug]
return stack
quantityOf: (itemSlug)->
stack = @_stacks[itemSlug]
return stack.quantity if stack
return 0
remove: (itemSlug, quantity=null)->
stack = @_stacks[itemSlug]
return this unless stack?
quantity ?= stack.quantity
return this unless quantity > 0
if stack.quantity < quantity
throw new Error "cannot remove #{quantity}: only #{stack.quantity} #{itemSlug} in this inventory"
stack.quantity -= quantity
if stack.quantity is 0
for currentItemSlug, index in @_itemSlugs
if ItemSlug.equal itemSlug, currentItemSlug
@_itemSlugs.splice index, 1
break
return this
# Parsing Methods ##############################################################################
parse: (data)->
return this if not data? or data.length is 0
stacks = data.split SimpleInventory.Delimiters.Stack
for stackText in stacks
stackParts = stackText.split SimpleInventory.Delimiters.Item
if stackParts.length is 2
quantity = parseInt stackParts[0], 10
itemSlug = ItemSlug.slugify stackParts[1]
else if stackParts.length is 1
quantity = 1
itemSlug = ItemSlug.slugify stackParts[0]
else
throw new Error "expected #{stackText} to have 0 or 1 parts"
if itemSlug.qualified.length > 0
@add itemSlug, quantity
return this
unparse: (options={})->
parts = []
@each (stack)=>
slugText = stack.itemSlug.item
if @modPack?
item = @modPack.findItem ItemSlug.slugify slugText
if item? and item.slug.qualified isnt stack.itemSlug.qualified
slugText = stack.itemSlug.qualified
if stack.quantity is 1
parts.push slugText
else
parts.push "#{stack.quantity}#{SimpleInventory.Delimiters.Item}#{slugText}"
return parts.join SimpleInventory.Delimiters.Stack
# Property Methods #############################################################################
getIsEmpty: ->
return @_itemSlugs.length is 0
getTotalQuantity: ->
total = 0
@each (stack)->
total += stack.quantity
return total
Object.defineProperties @prototype,
isEmpty: { get:@prototype.getIsEmpty }
totalQuantity: { get:@prototype.getTotalQuantity }
# Object Overrides #############################################################################
toString: ->
result = [@constructor.name, " (", @cid, ") {items: ["]
needsDelimiter = false
@each (stack)->
if needsDelimiter then result.push ', '
result.push stack.toString()
needsDelimiter = true
result.push ']'
result.push '}'
return result.join ''
# Private Methods ##############################################################################
_add: (itemSlug, quantity=1)->
return unless itemSlug?
return unless quantity > 0
stack = @_stacks[itemSlug]
if not stack?
stack = new SimpleStack itemSlug:itemSlug, quantity:quantity
@_stacks[itemSlug] = stack
@_itemSlugs.push itemSlug
@_sort()
else
stack.quantity += quantity
_sort: ->
@_itemSlugs.sort (a, b)-> ItemSlug.compare a, b