Merged conflicts.

This commit is contained in:
Scott Erickson 2014-09-17 16:53:08 -07:00
commit 5af1741333
17 changed files with 172 additions and 57 deletions

View file

@ -202,7 +202,7 @@ module.exports = class LevelLoader extends CocoClass
thangsToLoad = _.uniq( (t.spriteName for t in @world.thangs when t.exists) )
nameModelTuples = ([thangType.get('name'), thangType] for thangType in @thangNames.models)
nameModelMap = _.zipObject nameModelTuples
@spriteSheetsToBuild = []
@spriteSheetsToBuild ?= []
for thangTypeName in thangsToLoad
thangType = nameModelMap[thangTypeName]
@ -230,7 +230,7 @@ module.exports = class LevelLoader extends CocoClass
buildLoop: =>
someLeft = false
for spriteSheetResource, i in @spriteSheetsToBuild
for spriteSheetResource, i in @spriteSheetsToBuild ? []
continue if spriteSheetResource.spriteSheetKeys
someLeft = true
thangType = spriteSheetResource.thangType

View file

@ -78,9 +78,20 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
@handledDisplayEvents = {}
@age = 0
@stillLoading = true
<<<<<<< HEAD
if @thangType.isFullyLoaded() then @onThangTypeLoaded() else @listenToOnce(@thangType, 'sync', @onThangTypeLoaded)
toString: -> "<CocoSprite: #{@thang?.id}>"
=======
@setNameLabel @thang.id if @thang?.showsName and not @thang.health <= 0
if @thangType.isFullyLoaded()
@setUpSprite()
else
@thangType.setProjection null
@thangType.fetch() unless @thangType.loading
@listenToOnce(@thangType, 'sync', @setUpSprite)
@setUpPlaceholder()
>>>>>>> master
onThangTypeLoaded: ->
@stillLoading = false
@ -438,6 +449,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
rotation = @getRotation()
if relatedActions['111111111111'] # has grid-surrounding-wall-based actions
if @wallGrid
@hadWallGrid = true
action = ''
tileSize = 4
[gx, gy] = [@thang.pos.x, @thang.pos.y]
@ -464,6 +476,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
break
#console.log 'returning', matchedAction, 'for', @thang.id, 'at', gx, gy
return relatedActions[matchedAction]
else if @hadWallGrid
return null
else
keys = _.keys relatedActions
index = Math.max 0, Math.floor((179 + rotation) / 360 * keys.length)
@ -477,13 +491,15 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
relatedActions[direction]
updateStats: ->
return unless @thang and @thang.health isnt @lastHealth
@lastHealth = @thang.health
if bar = @healthBar
return if @thang.health is @lastHealth
@lastHealth = @thang.health
healthPct = Math.max(@thang.health / @thang.maxHealth, 0)
bar.scaleX = healthPct / bar.baseScale
healthOffset = @getOffset 'aboveHead'
[bar.x, bar.y] = [healthOffset.x - bar.width / 2, healthOffset.y]
if @thang.showsName
@setNameLabel(if @thang.health <= 0 then '' else @thang.id)
configureMouse: ->
@imageObject.cursor = 'pointer' if @thang?.isSelectable

View file

@ -22,7 +22,7 @@ module.exports = class RegionChooser extends CocoClass
onMouseMove: (e) =>
return unless @firstPoint
@secondPoint = @options.camera.screenToWorld {x: e.stageX, y: e.stageY}
@restrictRegion() if @options.restrictRatio
@restrictRegion() if @options.restrictRatio or key.alt
@updateShape()
onMouseUp: (e) =>

View file

@ -185,12 +185,17 @@ module.exports = class SpriteBoss extends CocoClass
@adjustSpriteExistence() if frameChanged
sprite.update frameChanged for sprite in @spriteArray
@updateSelection()
<<<<<<< HEAD
@spriteLayers['Default'].spriteContainer.updateLayerOrder()
@cache()
=======
@spriteLayers['Default'].updateLayerOrder()
@cacheObstacles()
>>>>>>> master
adjustSpriteExistence: ->
# Add anything new, remove anything old, update everything current
updateCache = false
updatedObstacles = []
itemsJustEquipped = []
for thang in @world.thangs when thang.exists and thang.pos
itemsJustEquipped = itemsJustEquipped.concat @equipNewItems thang
@ -199,16 +204,16 @@ module.exports = class SpriteBoss extends CocoClass
else
sprite = @addThangToSprites(thang)
Backbone.Mediator.publish 'surface:new-thang-added', thang: thang, sprite: sprite
updateCache = updateCache or sprite.imageObject.parent is @spriteLayers['Obstacle']
updatedObstacles.push sprite if sprite.imageObject.parent is @spriteLayers['Obstacle']
sprite.playSounds()
item.modifyStats() for item in itemsJustEquipped
for thangID, sprite of @sprites
missing = not (sprite.notOfThisWorld or @world.thangMap[thangID]?.exists)
isObstacle = sprite.imageObject.parent is @spriteLayers['Obstacle']
updateCache = updateCache or (isObstacle and (missing or sprite.hasMoved))
updatedObstacles.push sprite if isObstacle and (missing or sprite.hasMoved)
sprite.hasMoved = false
@removeSprite sprite if missing
@cache true if updateCache and @cached
@cacheObstacles updatedObstacles if updatedObstacles.length and @cachedObstacles
# mainly for handling selecting thangs from session when the thang is not always in existence
if @willSelectThang and @sprites[@willSelectThang[0]]
@ -229,8 +234,31 @@ module.exports = class SpriteBoss extends CocoClass
itemsJustEquipped.push item
return itemsJustEquipped
<<<<<<< HEAD
cache: (update=false) ->
# TODO: remove caching
=======
cacheObstacles: (updatedObstacles=null) ->
return if @cachedObstacles and not updatedObstacles
wallSprites = (sprite for sprite in @spriteArray when sprite.thangType?.get('name').search(/(dungeon|indoor).wall/i) isnt -1)
return if _.any (s.stillLoading for s in wallSprites)
walls = (sprite.thang for sprite in wallSprites)
@world.calculateBounds()
wallGrid = new Grid walls, @world.size()...
if updatedObstacles
possiblyUpdatedWallSprites = (sprite for sprite in wallSprites when _.find updatedObstacles, (w2) -> sprite is w2 or (Math.abs(sprite.thang.pos.x - w2.thang.pos.x) + Math.abs(sprite.thang.pos.y - w2.thang.pos.y)) <= 16)
else
possiblyUpdatedWallSprites = wallSprites
#console.log 'updating up to', possiblyUpdatedWallSprites.length, 'of', wallSprites.length, 'wall sprites from updatedObstacles', updatedObstacles
for wallSprite in possiblyUpdatedWallSprites
wallSprite.updateActionDirection wallGrid
wallSprite.updateScale()
wallSprite.updatePosition()
#console.log @wallGrid.toString()
@spriteLayers['Obstacle'].uncache() if @spriteLayers['Obstacle'].cacheID # might have changed sizes
@spriteLayers['Obstacle'].cache()
@cachedObstacles = true
>>>>>>> master
spriteFor: (thangID) -> @sprites[thangID]

View file

@ -488,7 +488,7 @@ module.exports = Surface = class Surface extends CocoClass
#- Canvas callbacks
onResize: (e) =>
return if @destroyed
return if @destroyed or @options.choosing
oldWidth = parseInt @canvas.attr('width'), 10
oldHeight = parseInt @canvas.attr('height'), 10
aspectRatio = oldWidth / oldHeight

View file

@ -139,7 +139,7 @@ module.exports = class GoalManager extends CocoClass
@initGoalState(state, [[], keepFrom.keepFromLocation?.who], 'arrived')
@initGoalState(state, [goal.getToLocations?.who, goal.keepFromLocations?.who], 'arrived')
@initGoalState(state, [goal.leaveOffSides?.who, goal.keepFromLeavingOffSides?.who], 'left')
@initGoalState(state, [goal.collectThangs?.who, goal.keepFromCollectingThangs?.who], 'collected')
@initGoalState(state, [goal.collectThangs?.targets, goal.keepFromCollectingThangs?.targets], 'collected')
@goalStates[goal.id] = state
onThangDied: (e, frameNumber) ->
@ -169,23 +169,23 @@ module.exports = class GoalManager extends CocoClass
onThangLeftMap: (e, frameNumber) ->
for goal in @goals ? []
@checkLeft(goal.id, goal.leaveOffSides.who, goal.leaveOffSides.sides, e.thang.id, e.side, frameNumber) if goal.leaveOffSides?
@checkLeft(goal.id, goal.keepFromLeavingOffSides.who, goal.keepFromLeavingOffSides.sides, e.thang.id, e.side, frameNumber) if goal.keepFromLeavingOffSides?
@checkLeft(goal.id, goal.leaveOffSides.who, goal.leaveOffSides.sides, e.thang, e.side, frameNumber) if goal.leaveOffSides?
@checkLeft(goal.id, goal.keepFromLeavingOffSides.who, goal.keepFromLeavingOffSides.sides, e.thang, e.side, frameNumber) if goal.keepFromLeavingOffSides?
checkLeft: (goalID, who, sides, thangID, side, frameNumber) ->
checkLeft: (goalID, who, sides, thang, side, frameNumber) ->
return if sides and side and not (side in sides)
return unless thangID in who
@updateGoalState(goalID, thangID, 'left', frameNumber)
return unless thang.id in who or thang.team in who
@updateGoalState(goalID, thang.id, 'left', frameNumber)
onThangCollectedItem: (e, frameNumber) ->
for goal in @goals ? []
@checkCollected(goal.id, goal.collectThangs.who, goal.collectThangs.targets, e.actor.id, e.item.id, frameNumber) if goal.collectThangs?
@checkCollected(goal.id, goal.keepFromCollectingThangs.who, goal.keepFromCollectingThangs.targets, e.actor.id, e.item.id, frameNumber) if goal.keepFromCollectingThangs?
@checkCollected(goal.id, goal.collectThangs.who, goal.collectThangs.targets, e.actor, e.item.id, frameNumber) if goal.collectThangs?
@checkCollected(goal.id, goal.keepFromCollectingThangs.who, goal.keepFromCollectingThangs.targets, e.actor, e.item.id, frameNumber) if goal.keepFromCollectingThangs?
checkCollected: (goalID, who, targets, thangID, itemID, frameNumber) ->
checkCollected: (goalID, who, targets, thang, itemID, frameNumber) ->
return unless itemID in targets
return unless thangID in who
@updateGoalState(goalID, thangID, 'collected', frameNumber)
return unless thang.id in who or thang.team in who
@updateGoalState(goalID, itemID, 'collected', frameNumber)
wrapUpGoalStates: (finalFrame) ->
for goalID, state of @goalStates

View file

@ -62,7 +62,7 @@ class CocoModel extends Backbone.Model
super(attribute)
set: (attributes, options) ->
delete @attributesWithDefaults
delete @attributesWithDefaults unless attributes is 'thangs' # unless attributes is 'thangs': performance optimization for Levels keeping their cache.
inFlux = @loading or not @loaded
@markToRevert() unless inFlux or @_revertAttributes or @project or options?.fromMerge
res = super attributes, options
@ -125,8 +125,12 @@ class CocoModel extends Backbone.Model
error(@, res) if error
return unless @notyErrors
errorMessage = "Error saving #{@get('name') ? @type()}"
console.error errorMessage, res.responseJSON
noty text: "#{errorMessage}: #{res.status} #{res.statusText}", layout: 'topCenter', type: 'error', killer: false, timeout: 10000
console.log 'going to log an error message'
console.warn errorMessage, res.responseJSON
try
noty text: "#{errorMessage}: #{res.status} #{res.statusText}", layout: 'topCenter', type: 'error', killer: false, timeout: 10000
catch notyError
console.warn "Couldn't even show noty error for", error, "because", notyError
@trigger 'save', @
return super attrs, options

View file

@ -128,19 +128,27 @@ module.exports = class Level extends CocoModel
# Here we have to sort the Components by their dependencies.
# It's a bit tricky though, because we don't have either soft dependencies or priority levels.
# Example: Programmable must come last, since it has to override any Component-provided methods that any other Component might have created. Can't enumerate all soft dependencies.
# Example: Plans needs to come after everything except Programmable, since other Components that add plannable methods need to have done so by the time Plans is attached.
# Example: Collides doesn't depend on Allied, but if both exist, Collides must come after Allied. Soft dependency example. Can't just figure out a proper priority to take care of it.
# Decision? Just special case the sort logic in here until we have more examples than these two and decide how best to handle most of the cases then, since we don't really know the whole of the problem yet.
# TODO: anything that depends on Programmable will break right now.
for thang in thangs ? []
programmableLevelComponent = null
plansLevelComponent = null
sorted = []
visit = (c) ->
return if c in sorted
lc = _.find levelComponents, {original: c.original}
console.error thang.id or thang.name, 'couldn\'t find lc for', c, 'of', levelComponents unless lc
return unless lc
if lc.name is 'Programmable'
if lc.name is 'Plans'
# Plans always comes second-to-last, behind Programmable
plansLevelComponent = c
visit c2 for c2 in _.without thang.components, c, programmableLevelComponent
else if lc.name is 'Programmable'
# Programmable always comes last
programmableLevelComponent = c
visit c2 for c2 in _.without thang.components, c
else
for d in lc.dependencies or []
@ -162,14 +170,31 @@ module.exports = class Level extends CocoModel
thang.components = sorted
fillInDefaultComponentConfiguration: (thangs, levelComponents) ->
# This is slow, so I inserted some optimizations to speed it up by caching the eventual defaults of commonly-used Components.
@defaultComponentConfigurations ?= {}
cached = 0
missed = 0
cachedConfigs = 0
for thang in thangs ? []
for component in thang.components or []
isPhysical = component.original is LevelComponent.PhysicalID
if not isPhysical and defaultConfiguration = _.find @defaultComponentConfigurations[component.original], ((d) -> _.isEqual component, d.originalComponent)
component.config = defaultConfiguration.defaultedConfig
++cached
continue
continue unless lc = _.find levelComponents, {original: component.original}
unless isPhysical
originalComponent = $.extend true, {}, component
component.config ?= {}
TreemaUtils.populateDefaults(component.config, lc.configSchema, tv4)
TreemaUtils.populateDefaults(component.config, lc.configSchema ? {}, tv4)
@lastType = 'component'
@lastOriginal = component.original
@walkDefaults component.config, lc.configSchema.properties
unless isPhysical
@defaultComponentConfigurations[component.original] ?= []
@defaultComponentConfigurations[component.original].push originalComponent: originalComponent, defaultedConfig: component.config
++cachedConfigs
++missed
#console.log 'cached', cached, 'missed', missed
fillInDefaultSystemConfiguration: (levelSystems) ->
for system in levelSystems ? []
@ -177,21 +202,6 @@ module.exports = class Level extends CocoModel
TreemaUtils.populateDefaults(system.config, system.model.configSchema, tv4)
@lastType = 'system'
@lastOriginal = system.model.name
@walkDefaults system.config, system.model.configSchema.properties
walkDefaults: (config, properties) ->
# This function is redundant, but is the old implementation.
# Remove it and calls to it once we stop seeing these warnings.
return unless properties
for prop, schema of properties
if schema.default? and config[prop] is undefined
console.warn 'Setting default of', config, 'for', prop, 'to', schema.default, 'but this method is deprecated... check your config schema!', @lastType, @lastOriginal
config[prop] = schema.default
if schema.type is 'object' and config[prop]
@walkDefaults config[prop], schema.properties
else if schema.type is 'array' and config[prop]
for item in config[prop] or []
@walkDefaults item, schema.items
dimensions: ->
width = 0

View file

@ -102,7 +102,7 @@ DependencySchema = c.object {
LevelComponentSchema = c.object {
title: 'Component'
description: 'A Component which can affect Thang behavior.'
required: ['system', 'name', 'description', 'code', 'dependencies', 'propertyDocumentation', 'codeLanguage']
required: ['system', 'name', 'code']
default:
system: 'ai'
name: 'AttacksSelf'

View file

@ -24,6 +24,10 @@ module.exports =
'editor:edit-level-thang': c.object {required: ['thangID']},
thangID: {type: 'string'}
'editor:level-thang-edited': c.object {required: ['thangData', 'oldPath']},
thangData: {type: 'object'}
oldPath: {type: 'string'}
'editor:level-thang-done-editing': c.object {required: ['thangData', 'oldPath']},
thangData: {type: 'object'}
oldPath: {type: 'string'}

View file

@ -177,7 +177,7 @@ block content
if !editing && !myProfile
button#contact-candidate.btn.btn-large.btn-inverse.flat-button
span(data-i18n="account_profile.contact") Contact
| #{profile.name.split(' ')[0]}
| #{(profile.name || user.get('name') || 'Anonymous').split(' ')[0]}
if me.isAdmin()
select#admin-contact.form-control
for contact in adminContacts

View file

@ -24,9 +24,14 @@ block modal-body-content
div.alert.alert-info
strong Shift-drag
| to select
div.alert.alert-info
strong Enter
| to confirm
if flexibleRegion
div.alert.alert-info
strong Alt-shift-drag
| to select ratio
else
div.alert.alert-info
strong Enter
| to confirm
canvas(width=924, height=589)
block modal-footer-content

View file

@ -26,7 +26,7 @@ module.exports = class NewLevelComponentModal extends ModalView
component = new LevelComponent()
component.set 'system', system
component.set 'name', name
component.set 'code', component.get('code').replace(/AttacksSelf/g, name)
component.set 'code', component.get('code', true).replace(/AttacksSelf/g, name)
component.set 'permissions', [{access: 'owner', target: me.id}] # Private until saved in a published Level
res = component.save()
return unless res

View file

@ -31,11 +31,11 @@ module.exports = class WorldSelectModal extends ModalView
getRenderData: (c={}) =>
c = super(c)
c.selectingPoint = @dataType is 'point'
c.flexibleRegion = @dataType is 'region'
c
afterInsert: ->
super()
window.e = @$el
@initSurface()
# surface setup
@ -54,7 +54,6 @@ module.exports = class WorldSelectModal extends ModalView
thangTypes: @supermodel.getModels(ThangType)
showInvisible: true
}
window.s = @surface
@surface.playing = false
@surface.setWorld @world
@surface.camera.zoomTo({x: 262, y: -164}, 1.66, 0)

View file

@ -19,6 +19,8 @@ module.exports = class LevelThangEditView extends CocoView
'click #thang-type-link span': 'toggleTypeEdit'
'blur #thang-name-link input': 'toggleNameEdit'
'blur #thang-type-link input': 'toggleTypeEdit'
'keydown #thang-name-link input': 'toggleNameEditIfReturn'
'keydown #thang-type-link input': 'toggleTypeEditIfReturn'
constructor: (options) ->
options ?= {}
@ -27,6 +29,7 @@ module.exports = class LevelThangEditView extends CocoView
@thangData = $.extend true, {}, options.thangData ? {}
@level = options.level
@oldPath = options.oldPath
@reportChanges = _.debounce @reportChanges, 1000
getRenderData: (context={}) ->
context = super(context)
@ -83,5 +86,16 @@ module.exports = class LevelThangEditView extends CocoView
if thangType and wasEditing
@thangData.thangType = thangType.get('original')
toggleNameEditIfReturn: (e) ->
@$el.find('#thang-name-link input').blur() if e.which is 13
toggleTypeEditIfReturn: (e) ->
@$el.find('#thang-type-link input').blur() if e.which is 13
onComponentsChanged: (components) =>
@thangData.components = components
@reportChanges()
reportChanges: =>
return if @destroyed
Backbone.Mediator.publish 'editor:level-thang-edited', {thangData: $.extend(true, {}, @thangData), oldPath: @oldPath}

View file

@ -16,7 +16,7 @@ MOVE_MARGIN = 0.15
MOVE_SPEED = 13
# Let us place these on top of other Thangs
overlappableThangTypeNames = ['Torch', 'Chains', 'Bird', 'Cloud 1', 'Cloud 2', 'Cloud 3', 'Waterfall', 'Obstacle']
overlappableThangTypeNames = ['Torch', 'Chains', 'Bird', 'Cloud 1', 'Cloud 2', 'Cloud 3', 'Waterfall', 'Obstacle', 'Electrowall']
class ThangTypeSearchCollection extends CocoCollection
url: '/db/thang.type?project=original,name,version,slug,kind,components'
@ -33,12 +33,14 @@ module.exports = class ThangsTabView extends CocoView
'surface:mouse-over': 'onSurfaceMouseOver'
'surface:mouse-out': 'onSurfaceMouseOut'
'editor:edit-level-thang': 'editThang'
'editor:level-thang-edited': 'onLevelThangEdited'
'editor:level-thang-done-editing': 'onLevelThangDoneEditing'
'editor:view-switched': 'onViewSwitched'
'sprite:dragged': 'onSpriteDragged'
'sprite:mouse-up': 'onSpriteMouseUp'
'sprite:mouse-down': 'onSpriteMouseDown'
'sprite:double-clicked': 'onSpriteDoubleClicked'
'surface:stage-mouse-down': 'onStageMouseDown'
'surface:stage-mouse-up': 'onStageMouseUp'
'editor:random-terrain-generated': 'onRandomTerrainGenerated'
@ -225,8 +227,17 @@ module.exports = class ThangsTabView extends CocoView
# if e.originalEvent.nativeEvent.button == 2
# @onSpriteContextMenu e
onStageMouseDown: (e) ->
return unless @addThangSprite?.thangType.get('kind') is 'Wall'
@surface.camera.dragDisabled = true
@paintingWalls = true
onStageMouseUp: (e) ->
if @addThangSprite
if @paintingWalls
# We need to stop painting walls, but we may also stop in onExtantThangSelected.
_.defer =>
@paintingWalls = @paintedWalls = @surface.camera.dragDisabled = false
else if @addThangSprite
@surface.camera.lock()
# If we click on the background, we need to add @addThangSprite, but not if onSpriteMouseUp will fire.
@backgroundAddClickTimeout = _.defer => @onExtantThangSelected {}
@ -295,7 +306,12 @@ module.exports = class ThangsTabView extends CocoView
@selectedExtantSprite?.setNameLabel? null unless @selectedExtantSprite is e.sprite
@selectedExtantThang = e.thang
@selectedExtantSprite = e.sprite
if e.thang and (key.alt or key.meta)
paintedAWall = @paintedWalls
@paintingWalls = @paintedWalls = @surface.camera.dragDisabled = false
if paintedAWall
# Skip adding a wall now, because we already dragged to add one
null
else if e.thang and (key.alt or key.meta)
# We alt-clicked, so create a clone addThang
@selectAddThangType e.thang.spriteName, @selectedExtantThang
else if @justAdded()
@ -389,6 +405,16 @@ module.exports = class ThangsTabView extends CocoView
wop = @surface.camera.screenToWorld x: e.x, y: e.y
wop.z = 0.5
@adjustThangPos @addThangSprite, @addThangSprite.thang, wop
if @paintingWalls
unless _.find @surface.spriteBoss.spriteArray, ((sprite) =>
sprite.thangType.get('kind') is 'Wall' and
Math.abs(sprite.thang.pos.x - @addThangSprite.thang.pos.x) < 2 and
Math.abs(sprite.thang.pos.y - @addThangSprite.thang.pos.y) < 2 and
sprite isnt @addThangSprite
)
@addThang @addThangType, @addThangSprite.thang.pos
@lastAddTime = new Date()
@paintedWalls = true
null
onSurfaceMouseOver: (e) ->
@ -427,6 +453,7 @@ module.exports = class ThangsTabView extends CocoView
deleteSelectedExtantThang: (e) =>
return if $(e.target).hasClass 'treema-node'
return unless @selectedExtantThang
thang = @getThangByID(@selectedExtantThang.id)
@thangsTreema.delete(@pathForThang(thang))
Thang.resetThangIDs() # TODO: find some way to do this when we delete from treema, too
@ -547,14 +574,19 @@ module.exports = class ThangsTabView extends CocoView
onLevelThangDoneEditing: (e) ->
@removeSubView @editThangView
@editThangView = null
newThang = e.thangData
@updateEditedThang e.thangData, e.oldPath
@$el.find('>').show()
onLevelThangEdited: (e) ->
@updateEditedThang e.thangData, e.oldPath
updateEditedThang: (newThang, oldPath) ->
@hush = true
@thangsTreema.delete e.oldPath
@thangsTreema.delete oldPath
@populateFoldersForThang(newThang)
@thangsTreema.set(@pathForThang(newThang), newThang)
@hush = false
@onThangsChanged()
@$el.find('>').show()
preventDefaultContextMenu: (e) ->
return unless $(e.target).closest('#canvas-wrapper').length

View file

@ -27,7 +27,10 @@ module.exports = class LevelChatView extends CocoView
updateMultiplayerVisibility: ->
return unless @$el?
@$el.toggle Boolean @session.get('multiplayer')
try
@$el.toggle Boolean @session.get('multiplayer')
catch e
console.error "Couldn't toggle the style on the LevelChatView to #{Boolean @session.get('multiplayer')} because of an error:", e
afterRender: ->
@chatTables = $('table', @$el)