Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-10-20 08:31:50 -07:00
commit 5f78f57c85
23 changed files with 99 additions and 185 deletions

View file

@ -37,18 +37,14 @@
<script src="/javascripts/aether.js"></script> <script src="/javascripts/aether.js"></script>
<script src="/javascripts/app.js"></script> <!-- it's all Backbone! --> <script src="/javascripts/app.js"></script> <!-- it's all Backbone! -->
<script> <!-- Can move to lib/services/linkedin.coffee instead somehow? Or just get rid of LinkedIn...
window.linkedInAsyncInit = function() {
console.log("Linkedin Async Init!");
Backbone.Mediator.publish('linkedin-loaded');
};
</script> </script>
<script type="text/javascript" async src="http://platform.linkedin.com/in.js"> <script type="text/javascript" async src="http://platform.linkedin.com/in.js">
api_key: 75v8mv4ictvmx6 api_key: 75v8mv4ictvmx6
onLoad: linkedInAsyncInit onLoad: linkedInAsyncInit
authorize: true authorize: true
</script> </script>
-->
<script> <script>
window.userObject = "userObjectTag"; window.userObject = "userObjectTag";

View file

@ -78,7 +78,6 @@ initializeUtilityServices = ->
services = [ services = [
'./lib/services/filepicker' './lib/services/filepicker'
'./lib/services/segmentio' './lib/services/segmentio'
'./lib/services/olark'
] ]
for service in services for service in services

View file

@ -61,7 +61,6 @@ module.exports = class LevelLoader extends CocoClass
# Session Loading # Session Loading
loadSession: -> loadSession: ->
return if @headless
if @sessionID if @sessionID
url = "/db/level.session/#{@sessionID}" url = "/db/level.session/#{@sessionID}"
else else
@ -71,6 +70,11 @@ module.exports = class LevelLoader extends CocoClass
session = new LevelSession().setURL url session = new LevelSession().setURL url
@sessionResource = @supermodel.loadModel(session, 'level_session', {cache: false}) @sessionResource = @supermodel.loadModel(session, 'level_session', {cache: false})
@session = @sessionResource.model @session = @sessionResource.model
if @opponentSessionID
opponentSession = new LevelSession().setURL "/db/level.session/#{@opponentSessionID}"
@opponentSessionResource = @supermodel.loadModel(opponentSession, 'opponent_session')
@opponentSession = @opponentSessionResource.model
if @session.loaded if @session.loaded
@session.setURL '/db/level.session/' + @session.id @session.setURL '/db/level.session/' + @session.id
@loadDependenciesForSession @session @loadDependenciesForSession @session
@ -78,11 +82,7 @@ module.exports = class LevelLoader extends CocoClass
@listenToOnce @session, 'sync', -> @listenToOnce @session, 'sync', ->
@session.setURL '/db/level.session/' + @session.id @session.setURL '/db/level.session/' + @session.id
@loadDependenciesForSession @session @loadDependenciesForSession @session
if @opponentSession
if @opponentSessionID
opponentSession = new LevelSession().setURL "/db/level.session/#{@opponentSessionID}"
@opponentSessionResource = @supermodel.loadModel(opponentSession, 'opponent_session')
@opponentSession = @opponentSessionResource.model
if @opponentSession.loaded if @opponentSession.loaded
@loadDependenciesForSession @opponentSession @loadDependenciesForSession @opponentSession
else else
@ -92,11 +92,13 @@ module.exports = class LevelLoader extends CocoClass
if session is @session if session is @session
Backbone.Mediator.publish 'level:session-loaded', level: @level, session: @session Backbone.Mediator.publish 'level:session-loaded', level: @level, session: @session
@consolidateFlagHistory() if @opponentSession?.loaded @consolidateFlagHistory() if @opponentSession?.loaded
else else if session is @opponentSession
@consolidateFlagHistory() if @session.loaded @consolidateFlagHistory() if @session.loaded
return unless @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] return unless @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']
@sessionDependenciesRegistered ?= {}
heroConfig = session.get('heroConfig') heroConfig = session.get('heroConfig')
heroConfig ?= me.get('heroConfig') if session is @session heroConfig ?= me.get('heroConfig') if session is @session and not @headless
console.error @level.get('name'), session.get('team'), session.get('creatorName'), 'had hero', heroConfig.thangType
heroConfig ?= {inventory: {}, thangType: '529ffbf1cf1818f2be000001'} # If all else fails, assign Tharin as the hero. heroConfig ?= {inventory: {}, thangType: '529ffbf1cf1818f2be000001'} # If all else fails, assign Tharin as the hero.
session.set 'heroConfig', heroConfig unless _.isEqual heroConfig, session.get('heroConfig') session.set 'heroConfig', heroConfig unless _.isEqual heroConfig, session.get('heroConfig')
url = "/db/thang.type/#{heroConfig.thangType}/version" url = "/db/thang.type/#{heroConfig.thangType}/version"
@ -108,13 +110,16 @@ module.exports = class LevelLoader extends CocoClass
@loadThangsRequiredByThangType heroThangType @loadThangsRequiredByThangType heroThangType
for itemThangType in _.values(heroConfig.inventory) for itemThangType in _.values(heroConfig.inventory)
url = "/db/thang.type/#{itemThangType}/version?project=name,components,original,rasterIcon" url = "/db/thang.type/#{itemThangType}/version?project=name,components,original,rasterIcon,kind"
if itemResource = @maybeLoadURL(url, ThangType, 'thang') if itemResource = @maybeLoadURL(url, ThangType, 'thang')
@worldNecessities.push itemResource @worldNecessities.push itemResource
else else
itemThangType = @supermodel.getModel url itemThangType = @supermodel.getModel url
@loadDefaultComponentsForThangType itemThangType @loadDefaultComponentsForThangType itemThangType
@loadThangsRequiredByThangType itemThangType @loadThangsRequiredByThangType itemThangType
@sessionDependenciesRegistered[session.id] = true
if _.size(@sessionDependenciesRegistered) is 2 and not (r for r in @worldNecessities when r?).length
@onWorldNecessitiesLoaded()
consolidateFlagHistory: -> consolidateFlagHistory: ->
state = @session.get('state') ? {} state = @session.get('state') ? {}
@ -172,7 +177,7 @@ module.exports = class LevelLoader extends CocoClass
url = "/db/level/#{obj.original}/version/#{obj.majorVersion}" url = "/db/level/#{obj.original}/version/#{obj.majorVersion}"
@maybeLoadURL url, Level, 'level' @maybeLoadURL url, Level, 'level'
unless @headless unless @headless or @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']
wizard = ThangType.loadUniversalWizard() wizard = ThangType.loadUniversalWizard()
@supermodel.loadModel wizard, 'thang' @supermodel.loadModel wizard, 'thang'
@ -193,7 +198,7 @@ module.exports = class LevelLoader extends CocoClass
else if component.config.requiredThangTypes else if component.config.requiredThangTypes
requiredThangTypes = requiredThangTypes.concat component.config.requiredThangTypes requiredThangTypes = requiredThangTypes.concat component.config.requiredThangTypes
for thangType in requiredThangTypes for thangType in requiredThangTypes
url = "/db/thang.type/#{thangType}/version?project=name,components,original,rasterIcon" url = "/db/thang.type/#{thangType}/version?project=name,components,original,rasterIcon,kind"
@worldNecessities.push @maybeLoadURL(url, ThangType, 'thang') @worldNecessities.push @maybeLoadURL(url, ThangType, 'thang')
onThangNamesLoaded: (thangNames) -> onThangNamesLoaded: (thangNames) ->
@ -216,9 +221,10 @@ module.exports = class LevelLoader extends CocoClass
return unless index >= 0 return unless index >= 0
@worldNecessities.splice(index, 1) @worldNecessities.splice(index, 1)
@worldNecessities = (r for r in @worldNecessities when r?) @worldNecessities = (r for r in @worldNecessities when r?)
@onWorldNecessitiesLoaded() if @worldNecessities.length is 0 if @worldNecessities.length is 0 and (not @sessionDependenciesRegistered or @sessionDependenciesRegistered[@session.id] and (not @opponentSession or @sessionDependenciesRegistered[@opponentSession.id]))
@onWorldNecessitiesLoaded()
onWorldNecessitiesLoaded: => onWorldNecessitiesLoaded: ->
@initWorld() @initWorld()
@supermodel.clearMaxProgress() @supermodel.clearMaxProgress()
@trigger 'world-necessities-loaded' @trigger 'world-necessities-loaded'
@ -250,7 +256,6 @@ module.exports = class LevelLoader extends CocoClass
console.log 'SuperModel for Level loaded in', new Date().getTime() - @t0, 'ms' console.log 'SuperModel for Level loaded in', new Date().getTime() - @t0, 'ms'
@loadLevelSounds() @loadLevelSounds()
@denormalizeSession() @denormalizeSession()
app.tracker.updatePlayState(@level, @session) unless @headless
buildLoop: => buildLoop: =>
someLeft = false someLeft = false

View file

@ -9,7 +9,6 @@ module.exports = class Tracker
window.tracker = @ window.tracker = @
@isProduction = document.location.href.search('codecombat.com') isnt -1 @isProduction = document.location.href.search('codecombat.com') isnt -1
@identify() @identify()
@updateOlark()
identify: (traits) -> identify: (traits) ->
console.log 'Would identify', traits if debugAnalytics console.log 'Would identify', traits if debugAnalytics
@ -20,24 +19,6 @@ module.exports = class Tracker
traits[userTrait] ?= me.get(userTrait) traits[userTrait] ?= me.get(userTrait)
analytics.identify me.id, traits analytics.identify me.id, traits
updateOlark: ->
return unless me and olark?
olark 'api.chat.updateVisitorStatus', snippet: ["User ID: #{me.id}"]
return if me.get('anonymous')
olark 'api.visitor.updateEmailAddress', emailAddress: me.get('email') if me.get('email')
olark 'api.chat.updateVisitorNickname', snippet: me.displayName()
updatePlayState: (level, session) ->
return unless olark?
link = "codecombat.com/play/level/#{level.get('slug') or level.id}?session=#{session.id}"
snippet = [
"#{link}"
"User ID: #{me.id}"
"Session ID: #{session.id}"
"Level: #{level.get('name')}"
]
olark 'api.chat.updateVisitorStatus', snippet: snippet
trackPageView: -> trackPageView: ->
return unless @isProduction and analytics? return unless @isProduction and analytics?
url = Backbone.history.getFragment() url = Backbone.history.getFragment()

View file

@ -1,115 +0,0 @@
module.exports = initializeOlark = ->
window.olark or ((c) -> #<![CDATA[
f = window
d = document
l = (if f.location.protocol is 'https:' then 'https:' else 'http:')
z = c.name
r = 'load'
nt = ->
s = ->
a.P r
f[z] r
return
f[z] = ->
(a.s = a.s or []).push arguments
return
a = f[z]._ = {}
q = c.methods.length
while q--
((n) ->
f[z][n] = ->
f[z] 'call', n, arguments
return
return
) c.methods[q]
a.l = c.loader
a.i = nt
a.p = 0: +new Date
a.P = (u) ->
a.p[u] = new Date - a.p[0]
return
(if f.addEventListener then f.addEventListener(r, s, false) else f.attachEvent('on' + r, s))
ld = ->
p = (hd) ->
hd = 'head'
[
'<'
hd
'></'
hd
'><'
i
' onl' + 'oad=\"var d='
g
";d.getElementsByTagName('head')[0]."
j
'(d.'
h
"('script'))."
k
"='"
l
'//'
a.l
"'"
'\"'
'></'
i
'>'
].join ''
i = 'body'
m = d[i]
return setTimeout(ld, 100) unless m
a.P 1
j = 'appendChild'
h = 'createElement'
k = 'src'
n = d[h]('div')
v = n[j](d[h](z))
b = d[h]('iframe')
g = 'document'
e = 'domain'
o = undefined
n.style.display = 'none'
m.insertBefore(n, m.firstChild).id = z
b.frameBorder = '0'
b.id = z + '-loader'
b.src = 'javascript:false' if /MSIE[ ]+6/.test(navigator.userAgent)
b.allowTransparency = 'true'
v[j] b
try
b.contentWindow[g].open()
catch w
c[e] = d[e]
o = 'javascript:var d=' + g + ".open();d.domain='" + d.domain + "';"
b[k] = o + 'void(0);'
try
t = b.contentWindow[g]
t.write p()
t.close()
catch x
b[k] = o + 'd.write(\"' + p().replace(/"/g, String.fromCharCode(92) + '\"') + '\");d.close();'
a.P 2
return
ld()
return
nt()
return
)(
loader: 'static.olark.com/jsclient/loader0.js'
name: 'olark'
methods: [
'configure'
'extend'
'declare'
'identify'
]
)
# custom configuration goes here (www.olark.com/documentation)
olark.identify '1451-787-10-5544' #]]>

View file

@ -45,7 +45,7 @@ module.exports = class Simulator extends CocoClass
@supermodel ?= new SuperModel() @supermodel ?= new SuperModel()
@supermodel.resetProgress() @supermodel.resetProgress()
@stopListening @supermodel, 'loaded-all' @stopListening @supermodel, 'loaded-all'
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: @task.getLevelName(), sessionID: @task.getFirstSessionID(), headless: true @levelLoader = new LevelLoader supermodel: @supermodel, levelID: @task.getLevelName(), sessionID: @task.getFirstSessionID(), opponentSessionID: @task.getSecondSessionID(), headless: true
if @supermodel.finished() if @supermodel.finished()
@simulateSingleGame() @simulateSingleGame()
@ -165,7 +165,7 @@ module.exports = class Simulator extends CocoClass
@supermodel ?= new SuperModel() @supermodel ?= new SuperModel()
@supermodel.resetProgress() @supermodel.resetProgress()
@stopListening @supermodel, 'loaded-all' @stopListening @supermodel, 'loaded-all'
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: levelID, sessionID: @task.getFirstSessionID(), headless: true @levelLoader = new LevelLoader supermodel: @supermodel, levelID: levelID, sessionID: @task.getFirstSessionID(), opponentSessionID: @task.getSecondSessionID(), headless: true
if @supermodel.finished() if @supermodel.finished()
@simulateGame() @simulateGame()
else else
@ -189,11 +189,13 @@ module.exports = class Simulator extends CocoClass
@world = @levelLoader.world @world = @levelLoader.world
@task.setWorld(@world) @task.setWorld(@world)
@level = @levelLoader.level @level = @levelLoader.level
@session = @levelLoader.session
@otherSession = @levelLoader.opponentSession
@levelLoader.destroy() @levelLoader.destroy()
@levelLoader = null @levelLoader = null
setupGod: -> setupGod: ->
@god.setLevel @level.serialize @supermodel, @task.getSessions()[0], @task.getSessions()[1] @god.setLevel @level.serialize(@supermodel, @session, @otherSession)
@god.setLevelSessionIDs (session.sessionID for session in @task.getSessions()) @god.setLevelSessionIDs (session.sessionID for session in @task.getSessions())
@god.setWorldClassMap @world.classMap @god.setWorldClassMap @world.classMap
@god.setGoalManager new GoalManager(@world, @level.get 'goals') @god.setGoalManager new GoalManager(@world, @level.get 'goals')
@ -424,6 +426,8 @@ class SimulationTask
getFirstSessionID: -> @rawData.sessions[0].sessionID getFirstSessionID: -> @rawData.sessions[0].sessionID
getSecondSessionID: -> @rawData.sessions[1].sessionID
getTaskID: -> @rawData.taskID getTaskID: -> @rawData.taskID
getReceiptHandle: -> @rawData.receiptHandle getReceiptHandle: -> @rawData.receiptHandle

View file

@ -78,7 +78,8 @@ class CocoModel extends Backbone.Model
thisTV4.addSchema('metaschema', require('schemas/metaschema')) thisTV4.addSchema('metaschema', require('schemas/metaschema'))
TreemaNode.utils.populateDefaults(clone, @schema(), thisTV4) TreemaNode.utils.populateDefaults(clone, @schema(), thisTV4)
@attributesWithDefaults = clone @attributesWithDefaults = clone
console.debug "Populated defaults for #{@attributes.name or @type()} in #{new Date() - t0}ms" duration = new Date() - t0
console.debug "Populated defaults for #{@attributes.name or @type()} in #{duration}ms" if duration > 10
loadFromBackup: -> loadFromBackup: ->
return unless @saveBackups return unless @saveBackups

View file

@ -57,7 +57,7 @@ module.exports = class Level extends CocoModel
if isHero and otherSession if isHero and otherSession
# If it's a hero and there's another session, find the right session for it. # If it's a hero and there's another session, find the right session for it.
# If there is no other session (playing against default code, or on single player), clone all placeholders. # If there is no other session (playing against default code, or on single player), clone all placeholders.
# TODO: actually look at the teams on these things to determine which session should go with which placeholder. # TODO: actually look at the teams on these Thangs to determine which session should go with which placeholder.
if levelThang.id is 'Hero Placeholder 1' and session.get('team') is 'humans' if levelThang.id is 'Hero Placeholder 1' and session.get('team') is 'humans'
session = otherSession session = otherSession
else if levelThang.id is 'Hero Placeholder' and session.get('team') is 'ogres' else if levelThang.id is 'Hero Placeholder' and session.get('team') is 'ogres'

View file

@ -121,7 +121,7 @@ module.exports = class SuperModel extends Backbone.Model
if cachedModel if cachedModel
clone = $.extend true, {}, model.attributes clone = $.extend true, {}, model.attributes
cachedModel.set(clone, {silent: true, fromMerge: true}) cachedModel.set(clone, {silent: true, fromMerge: true})
console.debug "Updated cached model <#{cachedModel.get('name') or cachedModel.getURL()}> with new data" #console.debug "Updated cached model <#{cachedModel.get('name') or cachedModel.getURL()}> with new data"
else else
@registerModel(model) @registerModel(model)
collection collection

View file

@ -235,6 +235,7 @@ module.exports = class ThangType extends CocoModel
return if _.isString spriteSheet return if _.isString spriteSheet
return unless spriteSheet return unless spriteSheet
canvas = $("<canvas width='#{size}' height='#{size}'></canvas>") canvas = $("<canvas width='#{size}' height='#{size}'></canvas>")
console.log 'made canvas', canvas, 'with size', size unless canvas[0]
stage = new createjs.Stage(canvas[0]) stage = new createjs.Stage(canvas[0])
sprite = new createjs.Sprite(spriteSheet) sprite = new createjs.Sprite(spriteSheet)
pt = @actions.portrait?.positions?.registration pt = @actions.portrait?.positions?.registration

View file

@ -33,6 +33,7 @@
.modal-body .modal-body
padding: 0 20px padding: 0 20px
min-height: 30px
.achievement-panel .achievement-panel
background: url("/images/pages/play/level/modal/achievement_plate.png") background: url("/images/pages/play/level/modal/achievement_plate.png")
@ -184,6 +185,20 @@
float: right float: right
margin-left: 10px margin-left: 10px
.ladder-submission-view
display: inline-block
color: white
.rank-button.btn-block
display: inline-block
width: initial
padding-left: 19px
padding-right: 19px
.last-submitted
float: none
html.no-borderimage html.no-borderimage
#hero-victory-modal #hero-victory-modal
.background-wrapper .background-wrapper

View file

@ -51,9 +51,16 @@ block modal-footer-content
span#gem-total +0 span#gem-total +0
button.btn.btn-warning.hide#saving-progress-label(disabled, data-i18n="play_level.victory_saving_progress") Saving Progress button.btn.btn-warning.hide#saving-progress-label(disabled, data-i18n="play_level.victory_saving_progress") Saving Progress
a.btn.btn-success.world-map-button.hide#continue-button(href="/play-hero", data-dismiss="modal", data-i18n="play_level.victory_play_continue") Continue
if readyToRank
.ladder-submission-view
else if level.get('type') === 'hero-ladder'
a.btn.btn-primary(href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_return_to_ladder") Return to Ladder
else
a.btn.btn-success.world-map-button.hide#continue-button(href="/play-hero", data-dismiss="modal", data-i18n="play_level.victory_play_continue") Continue
if me.get('anonymous') if me.get('anonymous')
p.sign-up-poke p.sign-up-poke
button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="modal/SignupModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="modal/SignupModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress
span(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account! span(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account!

View file

@ -52,6 +52,7 @@ module.exports = class SaveLevelModal extends SaveVersionModal
console.log "Should we save", m.get('system'), m.get('name'), m, "? localChanges:", m.hasLocalChanges(), "version:", m.get('version'), 'isPublished:', m.isPublished(), 'collection:', m.collection console.log "Should we save", m.get('system'), m.get('name'), m, "? localChanges:", m.hasLocalChanges(), "version:", m.get('version'), 'isPublished:', m.isPublished(), 'collection:', m.collection
return false return false
return true if m.hasLocalChanges() return true if m.hasLocalChanges()
console.error "Trying to check major version of #{m.type()} #{m.get('name')}, but it doesn't have a version:", m unless m.get('version')
return true if (m.get('version').major is 0 and m.get('version').minor is 0) or not m.isPublished() and not m.collection return true if (m.get('version').major is 0 and m.get('version').minor is 0) or not m.isPublished() and not m.collection
# Sometimes we have two versions: one in a search collection and one with a URL. We only save changes to the latter. # Sometimes we have two versions: one in a search collection and one with a URL. We only save changes to the latter.
false false

View file

@ -484,7 +484,8 @@ module.exports = class ThangsTabView extends CocoView
folderForThang: (thang) -> folderForThang: (thang) ->
thangType = @supermodel.getModelByOriginal ThangType, thang.thangType thangType = @supermodel.getModelByOriginal ThangType, thang.thangType
[thangType.get('kind'), thangType.get('name')] console.error 'uhh, we had kind', thangType.get('kind', true), 'for', thangType unless thangType.get('kind', true)
[thangType.get('kind', true), thangType.get('name', true)]
pathForThang: (thang) -> pathForThang: (thang) ->
folder = @folderForThang(thang) folder = @folderForThang(thang)

View file

@ -77,7 +77,7 @@ module.exports = class ThangTypeEditView extends RootView
context context
getAnimationNames: -> _.keys(@thangType.get('actions') or {}) getAnimationNames: -> _.keys(@thangType.get('actions') or {})
afterRender: -> afterRender: ->
super() super()
return unless @supermodel.finished() return unless @supermodel.finished()
@ -119,7 +119,7 @@ module.exports = class ThangTypeEditView extends RootView
@stage = new createjs.Stage(canvas[0]) @stage = new createjs.Stage(canvas[0])
@layerAdapter = new LayerAdapter({name:'Default', webGL: true}) @layerAdapter = new LayerAdapter({name:'Default', webGL: true})
@topLayer = new createjs.Container() @topLayer = new createjs.Container()
@layerAdapter.container.x = @topLayer.x = CENTER.x @layerAdapter.container.x = @topLayer.x = CENTER.x
@layerAdapter.container.y = @topLayer.y = CENTER.y @layerAdapter.container.y = @topLayer.y = CENTER.y
@stage.addChild(@layerAdapter.container, @topLayer) @stage.addChild(@layerAdapter.container, @topLayer)
@ -135,7 +135,7 @@ module.exports = class ThangTypeEditView extends RootView
@updateGrid() @updateGrid()
_.defer @refreshAnimation _.defer @refreshAnimation
@toggleDots(false) @toggleDots(false)
createjs.Ticker.setFPS(30) createjs.Ticker.setFPS(30)
createjs.Ticker.addEventListener('tick', @stage) createjs.Ticker.addEventListener('tick', @stage)
@ -244,7 +244,7 @@ module.exports = class ThangTypeEditView extends RootView
lank = new Lank(@thangType, @getLankOptions()) lank = new Lank(@thangType, @getLankOptions())
@showLank(lank) @showLank(lank)
@updateScale() @updateScale()
onNewSpriteSheet: -> onNewSpriteSheet: ->
$('#spritesheets').empty() $('#spritesheets').empty()
for image in @layerAdapter.spriteSheet._images for image in @layerAdapter.spriteSheet._images
@ -260,7 +260,7 @@ module.exports = class ThangTypeEditView extends RootView
@showAction(animationName) @showAction(animationName)
@updateRotation() @updateRotation()
@updateScale() # must happen after update rotation, because updateRotation calls the sprite update() method. @updateScale() # must happen after update rotation, because updateRotation calls the sprite update() method.
showMovieClip: (animationName) -> showMovieClip: (animationName) ->
vectorParser = new SpriteBuilder(@thangType) vectorParser = new SpriteBuilder(@thangType)
movieClip = vectorParser.buildMovieClip(animationName) movieClip = vectorParser.buildMovieClip(animationName)
@ -289,7 +289,7 @@ module.exports = class ThangTypeEditView extends RootView
portrait?.attr('id', 'portrait').addClass('img-thumbnail') portrait?.attr('id', 'portrait').addClass('img-thumbnail')
portrait.addClass 'img-thumbnail' portrait.addClass 'img-thumbnail'
$('#portrait').replaceWith(portrait) $('#portrait').replaceWith(portrait)
showLank: (lank) -> showLank: (lank) ->
@clearDisplayObject() @clearDisplayObject()
@clearLank() @clearLank()
@ -306,7 +306,7 @@ module.exports = class ThangTypeEditView extends RootView
clearDisplayObject: -> clearDisplayObject: ->
@topLayer.removeChild(@currentObject) if @currentObject? @topLayer.removeChild(@currentObject) if @currentObject?
clearLank: -> clearLank: ->
@layerAdapter.removeLank(@currentLank) if @currentLank @layerAdapter.removeLank(@currentLank) if @currentLank
@currentLank?.destroy() @currentLank?.destroy()
@ -365,7 +365,8 @@ module.exports = class ThangTypeEditView extends RootView
url = "/editor/thang/#{newThangType.get('slug') or newThangType.id}" url = "/editor/thang/#{newThangType.get('slug') or newThangType.id}"
portraitSource = null portraitSource = null
if @thangType.get('raster') if @thangType.get('raster')
image = @currentLank.sprite.image #image = @currentLank.sprite.image # Doesn't work?
image = @currentLank.sprite.spriteSheet._images[0]
portraitSource = imageToPortrait image portraitSource = imageToPortrait image
# bit of a hacky way to get that portrait # bit of a hacky way to get that portrait
success = => success = =>
@ -429,7 +430,7 @@ module.exports = class ThangTypeEditView extends RootView
obj = vectorParser.buildMovieClip(key) if type is 'animations' obj = vectorParser.buildMovieClip(key) if type is 'animations'
obj = vectorParser.buildContainerFromStore(key) if type is 'containers' obj = vectorParser.buildContainerFromStore(key) if type is 'containers'
obj = vectorParser.buildShapeFromStore(key) if type is 'shapes' obj = vectorParser.buildShapeFromStore(key) if type is 'shapes'
bounds = obj?.bounds or obj?.nominalBounds bounds = obj?.bounds or obj?.nominalBounds
if bounds if bounds
@boundsBox = new createjs.Shape() @boundsBox = new createjs.Shape()
@ -437,7 +438,7 @@ module.exports = class ThangTypeEditView extends RootView
@topLayer.addChild(@boundsBox) @topLayer.addChild(@boundsBox)
obj.regX = @boundsBox.regX = bounds.x + bounds.width / 2 obj.regX = @boundsBox.regX = bounds.x + bounds.width / 2
obj.regY = @boundsBox.regY = bounds.y + bounds.height / 2 obj.regY = @boundsBox.regY = bounds.y + bounds.height / 2
@showSprite(obj) if obj @showSprite(obj) if obj
@showingSelectedNode = true @showingSelectedNode = true
@currentLank?.destroy() @currentLank?.destroy()

View file

@ -49,6 +49,7 @@ module.exports = class SimulateTabView extends CocoView
fetchAndSimulateTaskOriginal = @simulator.fetchAndSimulateTask fetchAndSimulateTaskOriginal = @simulator.fetchAndSimulateTask
@simulator.fetchAndSimulateTask = => @simulator.fetchAndSimulateTask = =>
if @simulator.simulatedByYou >= 5 if @simulator.simulatedByYou >= 5
console.log '------------------- Destroying Simulator and making a new one -----------------'
@simulator.destroy() @simulator.destroy()
@simulator = null @simulator = null
@simulateNextGame() @simulateNextGame()

View file

@ -455,8 +455,7 @@ module.exports = class PlayLevelView extends RootView
showVictory: -> showVictory: ->
options = {level: @level, supermodel: @supermodel, session: @session} options = {level: @level, supermodel: @supermodel, session: @session}
ModalClass = if @level.get('type', true) in ['hero', 'hero-coop'] then HeroVictoryModal else VictoryModal ModalClass = if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] then HeroVictoryModal else VictoryModal
# TODO: made HeroVictoryModal able to support hero-ladder and then switch over for that level type, too
victoryModal = new ModalClass(options) victoryModal = new ModalClass(options)
@openModalView(victoryModal) @openModalView(victoryModal)
if me.get('anonymous') if me.get('anonymous')

View file

@ -6,6 +6,7 @@ CocoCollection = require 'collections/CocoCollection'
LocalMongo = require 'lib/LocalMongo' LocalMongo = require 'lib/LocalMongo'
utils = require 'lib/utils' utils = require 'lib/utils'
ThangType = require 'models/ThangType' ThangType = require 'models/ThangType'
LadderSubmissionView = require 'views/play/common/LadderSubmissionView'
module.exports = class HeroVictoryModal extends ModalView module.exports = class HeroVictoryModal extends ModalView
id: 'hero-victory-modal' id: 'hero-victory-modal'
@ -13,6 +14,9 @@ module.exports = class HeroVictoryModal extends ModalView
closeButton: false closeButton: false
closesOnClickOutside: false closesOnClickOutside: false
subscriptions:
'ladder:game-submitted': 'onGameSubmitted'
constructor: (options) -> constructor: (options) ->
super(options) super(options)
@session = options.session @session = options.session
@ -88,6 +92,7 @@ module.exports = class HeroVictoryModal extends ModalView
c.thangTypes = @thangTypes c.thangTypes = @thangTypes
c.me = me c.me = me
c.readyToRank = @level.get('type', true) is 'hero-ladder' and @session.readyToRank()
return c return c
afterRender: -> afterRender: ->
@ -116,6 +121,9 @@ module.exports = class HeroVictoryModal extends ModalView
panel.delay(500) panel.delay(500)
panel.queue(-> complete()) panel.queue(-> complete())
@animationComplete = not @animatedPanels.length @animationComplete = not @animatedPanels.length
if @level.get('type', true) is 'hero-ladder'
@ladderSubmissionView = new LadderSubmissionView session: @session, level: @level
@insertSubView @ladderSubmissionView, @$el.find('.ladder-submission-view')
beginAnimateNumbers: -> beginAnimateNumbers: ->
@numericalItemPanels = _.map(@animatedPanels.find('.numerical'), (panel) -> { @numericalItemPanels = _.map(@animatedPanels.find('.numerical'), (panel) -> {
@ -186,6 +194,11 @@ module.exports = class HeroVictoryModal extends ModalView
@$el.find('#saving-progress-label').toggleClass('hide', @readyToContinue) @$el.find('#saving-progress-label').toggleClass('hide', @readyToContinue)
@$el.find('#continue-button').toggleClass('hide', not @readyToContinue) @$el.find('#continue-button').toggleClass('hide', not @readyToContinue)
onGameSubmitted: (e) ->
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
Backbone.Mediator.publish 'router:navigate', route: ladderURL
# TODO: award heroes/items and play an awesome sound when you get one # TODO: award heroes/items and play an awesome sound when you get one
destroy: -> destroy: ->

View file

@ -40,6 +40,8 @@ module.exports = class Spell
if @permissions.readwrite.length and sessionSource = @session.getSourceFor(@spellKey) if @permissions.readwrite.length and sessionSource = @session.getSourceFor(@spellKey)
if sessionSource isnt '// Should fill in some default source\n' # TODO: figure out why session is getting this default source in there and stop it if sessionSource isnt '// Should fill in some default source\n' # TODO: figure out why session is getting this default source in there and stop it
@source = sessionSource @source = sessionSource
if p.aiSource and not @otherSession and not @canWrite()
@source = @originalSource = p.aiSource
@thangs = {} @thangs = {}
if @canRead() # We can avoid creating these views if we'll never use them. if @canRead() # We can avoid creating these views if we'll never use them.
@view = new SpellView {spell: @, level: options.level, session: @session, worker: @worker} @view = new SpellView {spell: @, level: options.level, session: @session, worker: @worker}

View file

@ -17,7 +17,8 @@ transpileLevelSession = (sessionID, cb) ->
if err then return cb err if err then return cb err
submittedCode = session.submittedCode submittedCode = session.submittedCode
unless session.submittedCodeLanguage unless session.submittedCodeLanguage
throw 'SUBMITTED CODE LANGUAGE DOESN\'T EXIST' console.log '\n\n\n#{i++} SUBMITTED CODE LANGUAGE DOESN\'T EXIST\n', session, '\n\n'
return cb()
else else
console.log "Transpiling code for session #{i++} #{session._id} in language #{session.submittedCodeLanguage}" console.log "Transpiling code for session #{i++} #{session._id} in language #{session.submittedCodeLanguage}"
transpiledCode = {} transpiledCode = {}

View file

@ -124,7 +124,7 @@ module.exports.getTwoGames = (req, res) ->
#if userIsAnonymous req then return errors.unauthorized(res, 'You need to be logged in to get games.') #if userIsAnonymous req then return errors.unauthorized(res, 'You need to be logged in to get games.')
humansGameID = req.body.humansGameID humansGameID = req.body.humansGameID
ogresGameID = req.body.ogresGameID ogresGameID = req.body.ogresGameID
ladderGameIDs = ['greed', 'criss-cross', 'brawlwood', 'dungeon-arena', 'gold-rush', 'sky-span'] ladderGameIDs = ['greed', 'criss-cross', 'brawlwood', 'dungeon-arena', 'gold-rush', 'sky-span', 'dueling-grounds', 'cavern-survival']
levelID = _.sample ladderGameIDs levelID = _.sample ladderGameIDs
unless ogresGameID and humansGameID unless ogresGameID and humansGameID
#fetch random games here #fetch random games here

View file

@ -98,7 +98,7 @@ describe 'LevelLoader', ->
levelLoader.loadDependenciesForSession(session) levelLoader.loadDependenciesForSession(session)
requests = jasmine.Ajax.requests.all() requests = jasmine.Ajax.requests.all()
urls = (r.url for r in requests) urls = (r.url for r in requests)
expect('/db/thang.type/gloves/version?project=name,components,original' in urls).toBeTruthy() expect('/db/thang.type/gloves/version?project=name,components,original,rasterIcon,kind' in urls).toBeTruthy()
expect('/db/thang.type/anya/version' in urls).toBeTruthy() expect('/db/thang.type/anya/version' in urls).toBeTruthy()
it 'loads components for the hero in the heroConfig in the given session', -> it 'loads components for the hero in the heroConfig in the given session', ->
@ -141,7 +141,7 @@ describe 'LevelLoader', ->
jasmine.Ajax.requests.sendResponses(responses) jasmine.Ajax.requests.sendResponses(responses)
requests = jasmine.Ajax.requests.all() requests = jasmine.Ajax.requests.all()
urls = (r.url for r in requests) urls = (r.url for r in requests)
expect('/db/thang.type/mace/version?project=name,components,original' in urls).toBeTruthy() expect('/db/thang.type/mace/version?project=name,components,original,rasterIcon,kind' in urls).toBeTruthy()
it 'loads components which are inherited by level thangs from thang type default components', -> it 'loads components which are inherited by level thangs from thang type default components', ->
new LevelLoader({supermodel:new SuperModel(), sessionID: 'id', levelID: 'id'}) new LevelLoader({supermodel:new SuperModel(), sessionID: 'id', levelID: 'id'})
@ -165,7 +165,7 @@ describe 'LevelLoader', ->
jasmine.Ajax.requests.sendResponses(responses) jasmine.Ajax.requests.sendResponses(responses)
requests = jasmine.Ajax.requests.all() requests = jasmine.Ajax.requests.all()
urls = (r.url for r in requests) urls = (r.url for r in requests)
expect('/db/thang.type/wand/version?project=name,components,original' in urls).toBeTruthy() expect('/db/thang.type/wand/version?project=name,components,original,rasterIcon,kind' in urls).toBeTruthy()
it 'loads components for item thang types which are inherited by level thangs from thang type default equips component configs', -> it 'loads components for item thang types which are inherited by level thangs from thang type default equips component configs', ->
new LevelLoader({supermodel:new SuperModel(), sessionID: 'id', levelID: 'id'}) new LevelLoader({supermodel:new SuperModel(), sessionID: 'id', levelID: 'id'})
@ -173,7 +173,7 @@ describe 'LevelLoader', ->
responses = responses =
'/db/level/id': levelWithShaman '/db/level/id': levelWithShaman
'/db/thang.type/names': [thangTypeShamanWithWandEquipped] '/db/thang.type/names': [thangTypeShamanWithWandEquipped]
'/db/thang.type/wand/version?project=name,components,original': thangTypeWand '/db/thang.type/wand/version?project=name,components,original,rasterIcon,kind': thangTypeWand
jasmine.Ajax.requests.sendResponses(responses) jasmine.Ajax.requests.sendResponses(responses)
requests = jasmine.Ajax.requests.all() requests = jasmine.Ajax.requests.all()

View file

@ -10,7 +10,7 @@ describe 'Problem', ->
addMarker: -> addMarker: ->
} }
} }
aether = { aether = {
raw: "this.say('hi');\nthis.sad('bye');" raw: "this.say('hi');\nthis.sad('bye');"
language: { id: 'javascript' } language: { id: 'javascript' }
} }
@ -27,7 +27,8 @@ describe 'Problem', ->
} }
levelID = 'awesome' levelID = 'awesome'
it 'save user code problem', -> # TODO: Problems are no longer saved when creating Problems; instead it's in SpellView. Update tests?
xit 'save user code problem', ->
new Problem aether, aetherProblem, ace, false, true, levelID new Problem aether, aetherProblem, ace, false, true, levelID
expect(jasmine.Ajax.requests.count()).toBe(1) expect(jasmine.Ajax.requests.count()).toBe(1)
@ -46,7 +47,7 @@ describe 'Problem', ->
expect(params.language).toEqual(aether.language.id) expect(params.language).toEqual(aether.language.id)
expect(params.levelID).toEqual(levelID) expect(params.levelID).toEqual(levelID)
it 'save user code problem no range', -> xit 'save user code problem no range', ->
aetherProblem.range = null aetherProblem.range = null
new Problem aether, aetherProblem, ace, false, true, levelID new Problem aether, aetherProblem, ace, false, true, levelID
expect(jasmine.Ajax.requests.count()).toBe(1) expect(jasmine.Ajax.requests.count()).toBe(1)
@ -68,7 +69,7 @@ describe 'Problem', ->
expect(params.codeSnippet).toBeUndefined() expect(params.codeSnippet).toBeUndefined()
expect(params.errRange).toBeUndefined() expect(params.errRange).toBeUndefined()
it 'save user code problem multi-line snippet', -> xit 'save user code problem multi-line snippet', ->
aether.raw = "this.say('hi');\nthis.sad\n('bye');" aether.raw = "this.say('hi');\nthis.sad\n('bye');"
aetherProblem.range = [ { row: 1 }, { row: 2 } ] aetherProblem.range = [ { row: 1 }, { row: 2 } ]