diff --git a/app/assets/javascripts/workers/worker_world.js b/app/assets/javascripts/workers/worker_world.js index 2ec1d73f8..7fa0d9794 100644 --- a/app/assets/javascripts/workers/worker_world.js +++ b/app/assets/javascripts/workers/worker_world.js @@ -363,7 +363,7 @@ self.runWorld = function runWorld(args) { for(var key in replacedLoDash) _[key] = replacedLoDash[key]; self.postMessage({type: 'start-load-frames'}); - self.world.loadFrames(self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress); + self.world.loadFrames(self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress, self.onWorldPreloaded); }; self.serializeFramesSoFar = function serializeFramesSoFar() { @@ -378,8 +378,9 @@ self.onWorldLoaded = function onWorldLoaded() { if(self.world.ended) self.goalManager.worldGenerationEnded(); var goalStates = self.goalManager.getGoalStates(); + var overallStatus = self.goalManager.checkOverallStatus(); if(self.world.ended) - self.postMessage({type: 'end-load-frames', goalStates: goalStates}); + self.postMessage({type: 'end-load-frames', goalStates: goalStates, overallStatus: overallStatus}); var t1 = new Date(); var diff = t1 - self.t0; if (self.world.headless) @@ -416,6 +417,13 @@ self.onWorldLoaded = function onWorldLoaded() { } }; +self.onWorldPreloaded = function onWorldPreloaded() { + self.goalManager.worldGenerationEnded(); + var goalStates = self.goalManager.getGoalStates(); + var overallStatus = self.goalManager.checkOverallStatus(); + self.postMessage({type: 'end-preload-frames', goalStates: goalStates, overallStatus: overallStatus}); +}; + self.onWorldError = function onWorldError(error) { if(error.isUserCodeProblem) { var errorKey = error.userInfo.key; diff --git a/app/lib/Angel.coffee b/app/lib/Angel.coffee index efa47c03b..94edc3088 100644 --- a/app/lib/Angel.coffee +++ b/app/lib/Angel.coffee @@ -66,7 +66,11 @@ module.exports = class Angel extends CocoClass clearTimeout @condemnTimeout when 'end-load-frames' clearTimeout @condemnTimeout - @beholdGoalStates event.data.goalStates # Work ends here if we're headless. + @beholdGoalStates event.data.goalStates, event.data.overallStatus # Work ends here if we're headless. + when 'end-preload-frames' + clearTimeout @condemnTimeout + @beholdGoalStates event.data.goalStates, event.data.overallStatus, true + # We have to abort like an infinite loop if we see one of these; they're not really recoverable when 'non-user-code-problem' @@ -105,9 +109,9 @@ module.exports = class Angel extends CocoClass else @log 'Received unsupported message:', event.data - beholdGoalStates: (goalStates) -> + beholdGoalStates: (goalStates, overallStatus, preload=false) -> return if @aborting - Backbone.Mediator.publish 'god:goals-calculated', goalStates: goalStates + Backbone.Mediator.publish 'god:goals-calculated', goalStates: goalStates, preload: preload, overallStatus: overallStatus @finishWork() if @shared.headless beholdWorld: (serialized, goalStates, startFrame, endFrame, streamingWorld) -> diff --git a/app/lib/world/world.coffee b/app/lib/world/world.coffee index 0cc3469de..43db43ca6 100644 --- a/app/lib/world/world.coffee +++ b/app/lib/world/world.coffee @@ -92,11 +92,11 @@ module.exports = class World (@runtimeErrors ?= []).push error (@unhandledRuntimeErrors ?= []).push error - loadFrames: (loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading, loadUntilFrame) -> + loadFrames: (loadedCallback, errorCallback, loadProgressCallback, preloadedCallback, skipDeferredLoading, loadUntilFrame) -> return if @aborted console.log 'Warning: loadFrames called on empty World (no thangs).' unless @thangs.length continueLaterFn = => - @loadFrames(loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading, loadUntilFrame) unless @destroyed + @loadFrames(loadedCallback, errorCallback, loadProgressCallback, preloadedCallback, skipDeferredLoading, loadUntilFrame) unless @destroyed if @realTime and not @countdownFinished return setTimeout @finishCountdown(continueLaterFn), REAL_TIME_COUNTDOWN_DELAY t1 = now() @@ -117,13 +117,15 @@ module.exports = class World for error in (@unhandledRuntimeErrors ? []) return unless errorCallback error # errorCallback tells us whether the error is recoverable @unhandledRuntimeErrors = [] - @finishLoadingFrames loadProgressCallback, loadedCallback + @finishLoadingFrames loadProgressCallback, loadedCallback, preloadedCallback - finishLoadingFrames: (loadProgressCallback, loadedCallback) -> + finishLoadingFrames: (loadProgressCallback, loadedCallback, preloadedCallback) -> unless @debugging @ended = true system.finish @thangs for system in @systems - unless @preloading + if @preloading + preloadedCallback() + else loadProgressCallback? 1 loadedCallback() diff --git a/app/schemas/subscriptions/god.coffee b/app/schemas/subscriptions/god.coffee index 6121b838d..014594893 100644 --- a/app/schemas/subscriptions/god.coffee +++ b/app/schemas/subscriptions/god.coffee @@ -1,6 +1,6 @@ c = require 'schemas/schemas' -goalStatesSchema = +goalStatesSchema = type: 'object' additionalProperties: type: 'object' @@ -41,6 +41,8 @@ module.exports = 'god:goals-calculated': c.object {required: ['goalStates']}, goalStates: goalStatesSchema + preload: {type: 'boolean'} + overallStatus: {type: ['string', 'null'], enum: ['success', 'failure', 'incomplete', null]} 'god:world-load-progress-changed': c.object {required: ['progress']}, progress: {type: 'number', minimum: 0, maximum: 1} diff --git a/app/styles/play/level/tome/cast_button.sass b/app/styles/play/level/tome/cast_button.sass index 1b1e2114f..5b50e7182 100644 --- a/app/styles/play/level/tome/cast_button.sass +++ b/app/styles/play/level/tome/cast_button.sass @@ -34,25 +34,37 @@ .btn padding: 3px 10px height: 40px + font-size: 22px .submit-button margin-left: 20px + min-width: 150px .cast-button margin-left: 10px + min-width: 150px @include opacity(0.77) &:hover, &.castable @include opacity(1) - &:not(.winnable) .cast-button.castable - font-weight: bold - -webkit-animation-name: castablePulse - -webkit-animation-duration: 3s - -webkit-animation-iteration-count: infinite + &:not(.winnable) - &.winnable .submit-button - font-weight: bold - -webkit-animation-name: winnablePulse - -webkit-animation-duration: 3s - -webkit-animation-iteration-count: infinite + .cast-button.castable + font-weight: bold + -webkit-animation-name: castablePulse + -webkit-animation-duration: 3s + -webkit-animation-iteration-count: infinite + + .submit-button + font-size: 16px + + &.winnable + .submit-button + font-weight: bold + -webkit-animation-name: winnablePulse + -webkit-animation-duration: 3s + -webkit-animation-iteration-count: infinite + + .cast-button + font-size: 16px diff --git a/app/views/play/level/tome/CastButtonView.coffee b/app/views/play/level/tome/CastButtonView.coffee index dafde5b0f..e30bac173 100644 --- a/app/views/play/level/tome/CastButtonView.coffee +++ b/app/views/play/level/tome/CastButtonView.coffee @@ -17,6 +17,7 @@ module.exports = class CastButtonView extends CocoView 'real-time-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame' 'real-time-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame' 'goal-manager:new-goal-states': 'onNewGoalStates' + 'god:goals-calculated': 'onGoalsCalculated' constructor: (options) -> super options @@ -85,6 +86,10 @@ module.exports = class CastButtonView extends CocoView if @winnable @$el.find('.submit-button').show() # In case we hid it, like on the first level. + onGoalsCalculated: (e) -> + return unless e.preload + @onNewGoalStates e + updateCastButton: -> return if _.some @spells, (spell) => not spell.loaded