diff --git a/app/lib/Angel.coffee b/app/lib/Angel.coffee index b4092c75f..efa47c03b 100644 --- a/app/lib/Angel.coffee +++ b/app/lib/Angel.coffee @@ -92,7 +92,7 @@ module.exports = class Angel extends CocoClass Backbone.Mediator.publish 'god:user-code-problem', problem: event.data.problem when 'world-load-progress-changed' Backbone.Mediator.publish 'god:world-load-progress-changed', progress: event.data.progress - unless event.data.progress is 1 or @work.preload or @work.headless or @work.synchronous or @deserializationQueue.length or @shared.firstWorld + unless event.data.progress is 1 or @work.preload or @work.headless or @work.synchronous or @deserializationQueue.length or (@shared.firstWorld and not @shared.spectate) @worker.postMessage func: 'serializeFramesSoFar' # Stream it! # We have some or all of the frames serialized, so let's send the (partially?) simulated world to the Surface. diff --git a/app/lib/God.coffee b/app/lib/God.coffee index 8574aff99..cf1631689 100644 --- a/app/lib/God.coffee +++ b/app/lib/God.coffee @@ -24,6 +24,7 @@ module.exports = class God extends CocoClass @angelsShare = workerCode: options.workerCode or '/javascripts/workers/worker_world.js' # Either path or function headless: options.headless # Whether to just simulate the goals, or to deserialize all simulation results + spectate: options.spectate godNick: @nick workQueue: [] firstWorld: true diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee index 2d8c45fb1..f2846c666 100644 --- a/app/lib/surface/Surface.coffee +++ b/app/lib/surface/Surface.coffee @@ -146,7 +146,6 @@ module.exports = Surface = class Surface extends CocoClass @showLevel() @updateState true if @loaded @onFrameChanged() - Backbone.Mediator.publish 'surface:world-set-up', {world: @world} showLevel: -> return if @destroyed diff --git a/app/locale/en.coffee b/app/locale/en.coffee index b1093ce0e..405ab7ec9 100644 --- a/app/locale/en.coffee +++ b/app/locale/en.coffee @@ -418,6 +418,7 @@ skip_tutorial: "Skip (esc)" keyboard_shortcuts: "Key Shortcuts" loading_ready: "Ready!" + loading_start: "Start Level" tip_insert_positions: "Shift+Click a point on the map to insert it into the spell editor." tip_toggle_play: "Toggle play/paused with Ctrl+P." tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward." diff --git a/app/models/Level.coffee b/app/models/Level.coffee index 2f1df8a50..348091b6a 100644 --- a/app/models/Level.coffee +++ b/app/models/Level.coffee @@ -108,7 +108,6 @@ module.exports = class Level extends CocoModel for original, placeholderComponent of placeholders when not placeholdersUsed[original] levelThang.components.push placeholderComponent - sortSystems: (levelSystems, systemModels) -> [sorted, originalsSeen] = [[], {}] visit = (system) -> diff --git a/app/schemas/subscriptions/surface.coffee b/app/schemas/subscriptions/surface.coffee index 0ca5a6a92..ba00491e5 100644 --- a/app/schemas/subscriptions/surface.coffee +++ b/app/schemas/subscriptions/surface.coffee @@ -121,9 +121,6 @@ module.exports = # /app/lib/surface 'sprite:dragged': spriteMouseEventSchema 'sprite:mouse-up': spriteMouseEventSchema - 'surface:world-set-up': c.object {}, - world: {type: 'object'} - 'surface:frame-changed': c.object {required: ['frame', 'world', 'progress']}, frame: {type: 'number', minimum: 0} world: {type: 'object'} diff --git a/app/styles/play/level/loading.sass b/app/styles/play/level/loading.sass index 3dac90ec8..697694ad7 100644 --- a/app/styles/play/level/loading.sass +++ b/app/styles/play/level/loading.sass @@ -56,6 +56,9 @@ position: relative z-index: 2 + .start-level-button + margin-top: 10px + .left-wing, .right-wing width: 100% height: 100% diff --git a/app/templates/play/level/level_loading.jade b/app/templates/play/level/level_loading.jade index 895524bce..23cc615ab 100644 --- a/app/templates/play/level/level_loading.jade +++ b/app/templates/play/level/level_loading.jade @@ -43,3 +43,4 @@ .errors + button.start-level-button.btn.btn-lg.btn-success.secret(data-i18n="play_level.loading_start") Start Level diff --git a/app/views/game-menu/InventoryView.coffee b/app/views/game-menu/InventoryView.coffee index 5b93864af..f59f8269f 100644 --- a/app/views/game-menu/InventoryView.coffee +++ b/app/views/game-menu/InventoryView.coffee @@ -310,7 +310,7 @@ module.exports = class InventoryView extends CocoView necessaryGear = gearByLevel[@options.levelID] for slot, item of necessaryGear ? {} @equipment[slot] ?= gear[item] - @allowedItems = _.values gear if necessaryGear # If it's one of these levels, don't show the extra items. + @allowedItems = _.union(_.values(gear), _.values(@equipment)) if necessaryGear # If it's one of these levels, don't show the extra items. onHeroSelectionUpdated: (e) -> @selectedHero = e.hero diff --git a/app/views/play/SpectateView.coffee b/app/views/play/SpectateView.coffee index 05f97f20e..68ad72d0e 100644 --- a/app/views/play/SpectateView.coffee +++ b/app/views/play/SpectateView.coffee @@ -44,7 +44,6 @@ module.exports = class SpectateLevelView extends RootView 'god:new-world-created': 'onNewWorld' 'god:streaming-world-updated': 'onNewWorld' 'god:infinite-loop': 'onInfiniteLoop' - 'surface:world-set-up': 'onSurfaceSetUpNewWorld' 'level:next-game-pressed': 'onNextGamePressed' 'level:started': 'onLevelStarted' 'level:loading-view-unveiled': 'onLoadingViewUnveiled' @@ -84,7 +83,7 @@ module.exports = class SpectateLevelView extends RootView opponentSessionID: @sessionTwo spectateMode: true team: @getQueryVariable('team') - @god = new God maxAngels: 1 + @god = new God maxAngels: 1, spectate: true getRenderData: -> c = super() @@ -161,12 +160,14 @@ module.exports = class SpectateLevelView extends RootView @session.set 'multiplayer', false onLevelStarted: (e) -> - @loadingView?.unveil() + go = => @loadingView?.unveil() + _.delay go, 1000 onLoadingViewUnveiled: (e) -> # Don't remove it; we want its decoration around on large screens. #@removeSubView @loadingView #@loadingView = null + Backbone.Mediator.publish 'level:set-playing', playing: true onSupermodelLoadedOne: => @modelsLoaded ?= 0 @@ -229,13 +230,6 @@ module.exports = class SpectateLevelView extends RootView volume = 1.0 unless volume? Backbone.Mediator.publish 'level:set-volume', volume: volume - onSurfaceSetUpNewWorld: -> - return if @alreadyLoadedState - @alreadyLoadedState = true - state = @originalSessionState - if state.playing? - Backbone.Mediator.publish 'level:set-playing', playing: state.playing - register: -> return onSessionWillSave: (e) -> @@ -259,6 +253,7 @@ module.exports = class SpectateLevelView extends RootView return if @headless scripts = @world.scripts # Since these worlds don't have scripts, preserve them. @world = e.world + @world.scripts = scripts thangTypes = @supermodel.getModels(ThangType) startFrame = @lastWorldFramesLoaded ? 0 if @world.frames.length is @world.totalFrames # Finished loading diff --git a/app/views/play/level/LevelLoadingView.coffee b/app/views/play/level/LevelLoadingView.coffee index 9d8ec311c..18e387d85 100644 --- a/app/views/play/level/LevelLoadingView.coffee +++ b/app/views/play/level/LevelLoadingView.coffee @@ -5,7 +5,11 @@ module.exports = class LevelLoadingView extends CocoView id: 'level-loading-view' template: template + events: + 'click .start-level-button': 'onClickStartLevel' + onLoaded: -> + afterRender: -> @$el.find('.tip.rare').remove() if _.random(1, 10) < 9 tips = @$el.find('.tip').addClass('to-remove') @@ -19,12 +23,12 @@ module.exports = class LevelLoadingView extends CocoView ready = $.i18n.t('play_level.loading_ready', defaultValue: 'Ready!') @$el.find('#tip-wrapper .tip').addClass('ready').text ready Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'level_loaded', volume: 0.75 # old: loading_ready + @$el.find('.start-level-button').removeClass 'secret' + + onClickStartLevel: (e) -> + @unveil() unveil: -> - _.delay @reallyUnveil, 1000 - - reallyUnveil: => - return if @destroyed @$el.addClass 'unveiled' loadingDetails = @$el.find('.loading-details') duration = parseFloat loadingDetails.css 'transition-duration' diff --git a/app/views/play/level/PlayLevelView.coffee b/app/views/play/level/PlayLevelView.coffee index 66aa6cd61..ad8842bcc 100644 --- a/app/views/play/level/PlayLevelView.coffee +++ b/app/views/play/level/PlayLevelView.coffee @@ -60,7 +60,6 @@ module.exports = class PlayLevelView extends RootView 'level:reload-thang-type': 'onLevelReloadThangType' 'level:play-next-level': 'onPlayNextLevel' 'level:edit-wizard-settings': 'showWizardSettingsModal' - 'surface:world-set-up': 'onSurfaceSetUpNewWorld' 'level:session-will-save': 'onSessionWillSave' 'level:started': 'onLevelStarted' 'level:loading-view-unveiled': 'onLoadingViewUnveiled' @@ -323,12 +322,12 @@ module.exports = class PlayLevelView extends RootView if @otherSession # TODO: colorize name and cloud by team, colorize wizard by user's color config @surface.createOpponentWizard id: @otherSession.get('creator'), name: @otherSession.get('creatorName'), team: @otherSession.get('team'), levelSlug: @level.get('slug'), codeLanguage: @otherSession.get('submittedCodeLanguage') - @loadingView?.unveil() onLoadingViewUnveiled: (e) -> @loadingView.$el.remove() @removeSubView @loadingView @loadingView = null + @restoreSessionState() unless @isEditorPreview @loadEndTime = new Date() loadDuration = @loadEndTime - @loadStartTime @@ -336,7 +335,7 @@ module.exports = class PlayLevelView extends RootView application.tracker?.trackEvent 'Finished Level Load', level: @levelID, label: @levelID, loadDuration: loadDuration, ['Google Analytics'] application.tracker?.trackTiming loadDuration, 'Level Load Time', @levelID, @levelID - onSurfaceSetUpNewWorld: -> + restoreSessionState: -> return if @alreadyLoadedState @alreadyLoadedState = true state = @originalSessionState