mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-24 08:08:15 -05:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
295ecf53c2
24 changed files with 159 additions and 112 deletions
|
@ -478,6 +478,7 @@ self.onWorldError = function onWorldError(error) {
|
|||
else {
|
||||
console.log("Non-UserCodeError:", error.toString() + "\n" + error.stack || error.stackTrace);
|
||||
self.postMessage({type: 'non-user-code-problem', problem: {message: error.toString()}});
|
||||
return false;
|
||||
}
|
||||
/* We don't actually have the recoverable property any more; hmm
|
||||
if(!error.recoverable) {
|
||||
|
|
|
@ -144,7 +144,7 @@ module.exports.getUTCDay = (offset=0) ->
|
|||
|
||||
# Fast, basic way to replace text in an element when you don't need much.
|
||||
# http://stackoverflow.com/a/4962398/540620
|
||||
if document?
|
||||
if document?.createElement
|
||||
dummy = document.createElement 'div'
|
||||
dummy.innerHTML = 'text'
|
||||
TEXT = if dummy.textContent is 'text' then 'textContent' else 'innerText'
|
||||
|
@ -155,7 +155,7 @@ if document?
|
|||
# Add a stylesheet rule
|
||||
# http://stackoverflow.com/questions/524696/how-to-create-a-style-tag-with-javascript/26230472#26230472
|
||||
# Don't use wantonly, or we'll have to implement a simple mechanism for clearing out old rules.
|
||||
if document?
|
||||
if document?.createElement
|
||||
module.exports.injectCSS = ((doc) ->
|
||||
# wrapper for all injected styles and temp el to create them
|
||||
wrap = doc.createElement("div")
|
||||
|
|
|
@ -91,18 +91,9 @@ module.exports = class LevelLoader extends CocoClass
|
|||
loadDependenciesForSession: (session) ->
|
||||
if me.id isnt session.get 'creator'
|
||||
session.patch = session.save = -> console.error "Not saving session, since we didn't create it."
|
||||
@loadCodeLanguagesForSession session
|
||||
if session is @session
|
||||
codeLanguage = session.get('codeLanguage') or me.get('aceConfig')?.language or 'python'
|
||||
modulePath = "vendor/aether-#{codeLanguage}"
|
||||
loading = application.moduleLoader.load(modulePath)
|
||||
if loading
|
||||
@languageModuleResource = @supermodel.addSomethingResource 'language_module'
|
||||
@listenTo application.moduleLoader, 'loaded', (e) ->
|
||||
if e.id is modulePath
|
||||
@languageModuleResource.markLoaded()
|
||||
@stopListening application.moduleLoader
|
||||
@addSessionBrowserInfo session
|
||||
|
||||
# hero-ladder games require the correct session team in level:loaded
|
||||
team = @team ? @session.get('team')
|
||||
Backbone.Mediator.publish 'level:loaded', level: @level, team: team
|
||||
|
@ -138,6 +129,19 @@ module.exports = class LevelLoader extends CocoClass
|
|||
if _.size(@sessionDependenciesRegistered) is 2 and @checkAllWorldNecessitiesRegisteredAndLoaded()
|
||||
@onWorldNecessitiesLoaded()
|
||||
|
||||
loadCodeLanguagesForSession: (session) ->
|
||||
codeLanguages = _.uniq _.filter [session.get('codeLanguage') or 'python', session.get('submittedCodeLanguage')]
|
||||
for codeLanguage in codeLanguages
|
||||
do (codeLanguage) =>
|
||||
modulePath = "vendor/aether-#{codeLanguage}"
|
||||
return unless application.moduleLoader?.load modulePath
|
||||
languageModuleResource = @supermodel.addSomethingResource 'language_module'
|
||||
onModuleLoaded = (e) ->
|
||||
return unless e.id is modulePath
|
||||
languageModuleResource.markLoaded()
|
||||
@stopListening application.moduleLoader, 'loaded', onModuleLoaded # listenToOnce might work here instead, haven't tried
|
||||
@listenTo application.moduleLoader, 'loaded', onModuleLoaded
|
||||
|
||||
addSessionBrowserInfo: (session) ->
|
||||
return unless me.id is session.get 'creator'
|
||||
return unless $.browser?
|
||||
|
|
|
@ -5,7 +5,7 @@ GoalManager = require 'lib/world/GoalManager'
|
|||
God = require 'lib/God'
|
||||
{createAetherOptions} = require 'lib/aether_utils'
|
||||
|
||||
SIMULATOR_VERSION = 1
|
||||
SIMULATOR_VERSION = 3
|
||||
|
||||
simulatorInfo = {}
|
||||
if $.browser
|
||||
|
@ -225,6 +225,12 @@ module.exports = class Simulator extends CocoClass
|
|||
@god.setLevelSessionIDs (session.sessionID for session in @task.getSessions())
|
||||
@god.setWorldClassMap @world.classMap
|
||||
@god.setGoalManager new GoalManager(@world, @level.get 'goals')
|
||||
humanFlagHistory = _.filter @session.get('state')?.flagHistory ? [], (event) => event.source isnt 'code' and event.team is (@session.get('team') ? 'humans')
|
||||
ogreFlagHistory = _.filter @otherSession.get('state')?.flagHistory ? [], (event) => event.source isnt 'code' and event.team is (@otherSession.get('team') ? 'ogres')
|
||||
@god.lastFlagHistory = humanFlagHistory.concat ogreFlagHistory
|
||||
#console.log 'got flag history', @god.lastFlagHistory, 'from', humanFlagHistory, ogreFlagHistory, @session.get('state'), @otherSession.get('state')
|
||||
@god.lastSubmissionCount = 0 # TODO: figure out how to combine submissionCounts from both players so we can use submissionCount random seeds again.
|
||||
@god.lastDifficulty = 0
|
||||
|
||||
commenceSimulationAndSetupCallback: ->
|
||||
Backbone.Mediator.subscribeOnce 'god:infinite-loop', @onInfiniteLoop, @
|
||||
|
@ -328,6 +334,7 @@ module.exports = class Simulator extends CocoClass
|
|||
calculationTime: 500
|
||||
sessions: []
|
||||
simulator: @simulator
|
||||
randomSeed: @task.world.randomSeed
|
||||
|
||||
for session in @task.getSessions()
|
||||
sessionResult =
|
||||
|
|
|
@ -474,6 +474,8 @@ module.exports = Lank = class Lank extends CocoClass
|
|||
bar.scaleX = healthPct / @options.floatingLayer.resolutionFactor
|
||||
if @thang.showsName
|
||||
@setNameLabel(if @thang.health <= 0 then '' else @thang.id)
|
||||
else if @options.playerName
|
||||
@setNameLabel @options.playerName
|
||||
|
||||
configureMouse: ->
|
||||
@sprite.cursor = 'pointer' if @thang?.isSelectable
|
||||
|
|
|
@ -163,6 +163,8 @@ module.exports = class LankBoss extends CocoClass
|
|||
|
||||
options = @createLankOptions thang: thang
|
||||
options.resolutionFactor = if thangType.get('kind') is 'Floor' then 2 else SPRITE_RESOLUTION_FACTOR
|
||||
if @options.playerNames and /Hero Placeholder/.test thang.id
|
||||
options.playerName = @options.playerNames[thang.team]
|
||||
lank = new Lank thangType, options
|
||||
@listenTo lank, 'sprite:mouse-up', @onLankMouseUp
|
||||
@addLank lank, null, layer
|
||||
|
|
|
@ -113,7 +113,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
canvasHeight = parseInt @normalCanvas.attr('height'), 10
|
||||
@screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight
|
||||
|
||||
@lankBoss = new LankBoss camera: @camera, webGLStage: @webGLStage, surfaceTextLayer: @surfaceTextLayer, world: @world, thangTypes: @options.thangTypes, choosing: @options.choosing, navigateToSelection: @options.navigateToSelection, showInvisible: @options.showInvisible
|
||||
@lankBoss = new LankBoss camera: @camera, webGLStage: @webGLStage, surfaceTextLayer: @surfaceTextLayer, world: @world, thangTypes: @options.thangTypes, choosing: @options.choosing, navigateToSelection: @options.navigateToSelection, showInvisible: @options.showInvisible, playerNames: @options.playerNames
|
||||
@countdownScreen = new CountdownScreen camera: @camera, layer: @screenLayer, showsCountdown: @world.showsCountdown
|
||||
@playbackOverScreen = new PlaybackOverScreen camera: @camera, layer: @screenLayer
|
||||
@normalStage.addChildAt @playbackOverScreen.dimLayer, 0 # Put this below the other layers, actually, so we can more easily read text on the screen.
|
||||
|
@ -549,8 +549,9 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@normalStage.scaleY *= newHeight / oldHeight
|
||||
@camera.onResize newWidth, newHeight
|
||||
if @options.spectateGame
|
||||
# Since normalCanvas is absolutely positioned, it needs help aligning with webGLCanvas. But not further than +149px (1920px screen).
|
||||
@normalCanvas.css 'left', Math.min 149, @webGLCanvas.offset().left
|
||||
# Since normalCanvas is absolutely positioned, it needs help aligning with webGLCanvas.
|
||||
offset = @webGLCanvas.offset().left - ($('#page-container').innerWidth() - $('#canvas-wrapper').innerWidth()) / 2
|
||||
@normalCanvas.css 'left', offset
|
||||
|
||||
#- Camera focus on hero
|
||||
focusOnHero: ->
|
||||
|
|
|
@ -360,7 +360,7 @@ module.exports = class World
|
|||
#console.log "... world serializing frames from", startFrame, "to", endFrame, "of", @totalFrames
|
||||
[transferableObjects, nontransferableObjects] = [0, 0]
|
||||
delete flag.processed for flag in @flagHistory
|
||||
o = {totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}, flagHistory: @flagHistory, difficulty: @difficulty, scores: @getScores()}
|
||||
o = {totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}, flagHistory: @flagHistory, difficulty: @difficulty, scores: @getScores(), randomSeed: @randomSeed}
|
||||
o.trackedProperties[prop] = @[prop] for prop in @trackedProperties or []
|
||||
|
||||
for thangID, methods of @userCodeMap
|
||||
|
@ -467,7 +467,7 @@ module.exports = class World
|
|||
w.userCodeMap[thangID][methodName][aetherStateKey] = serializedAether[aetherStateKey]
|
||||
else
|
||||
w = new World o.userCodeMap, classMap
|
||||
[w.totalFrames, w.maxTotalFrames, w.frameRate, w.dt, w.scriptNotes, w.victory, w.flagHistory, w.difficulty, w.scores] = [o.totalFrames, o.maxTotalFrames, o.frameRate, o.dt, o.scriptNotes ? [], o.victory, o.flagHistory, o.difficulty, o.scores]
|
||||
[w.totalFrames, w.maxTotalFrames, w.frameRate, w.dt, w.scriptNotes, w.victory, w.flagHistory, w.difficulty, w.scores, w.randomSeed] = [o.totalFrames, o.maxTotalFrames, o.frameRate, o.dt, o.scriptNotes ? [], o.victory, o.flagHistory, o.difficulty, o.scores, o.randomSeed]
|
||||
w[prop] = val for prop, val of o.trackedProperties
|
||||
|
||||
perf.t1 = now()
|
||||
|
|
|
@ -548,24 +548,24 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
# for_girls_1: "There are three game modes in CodeCombat: building, puzzles, and combat. We have intentionally designed each to appeal to both boys and girls and think that the building and puzzle levels especially differentiate the game from violent triple A titles that repel female players."
|
||||
what_cover_title: "O que abordamos?"
|
||||
# what_cover_1: "There are 20 levels in the Hour of Code tutorial that teach and reinforce 6 specific computer science concepts:"
|
||||
# what_cover_notation_1: "Formal notation"
|
||||
what_cover_notation_1: "Notação formal"
|
||||
# what_cover_notation_2: "- builds an understanding of the importance of syntax in programming."
|
||||
# what_cover_methods_1: "Calling methods"
|
||||
what_cover_methods_1: "Chamar métodos"
|
||||
# what_cover_methods_2: "- familiarizes students with the syntax of object-oriented method calls."
|
||||
# what_cover_parameters_1: "Parameters"
|
||||
what_cover_parameters_1: "Parâmetros"
|
||||
# what_cover_parameters_2: "- trains how to pass parameters to functions."
|
||||
# what_cover_strings_1: "Strings"
|
||||
what_cover_strings_1: "'Strings'"
|
||||
# what_cover_strings_2: "- teaches students about string notation and passing strings as parameters."
|
||||
# what_cover_loops_1: "Loops"
|
||||
what_cover_loops_1: "'Loops'"
|
||||
# what_cover_loops_2: "- develops the abstraction of designing short programs with loops."
|
||||
# what_cover_variables_1: "Variables"
|
||||
what_cover_variables_1: "Variáveis"
|
||||
# what_cover_variables_2: "- adds the skill of referencing values that change over time."
|
||||
# what_cover_2: "Students may continue past level 20, depending on their speed and interest, to learn two additional concepts in later levels:"
|
||||
# what_cover_logic_1: "Conditional logic"
|
||||
what_cover_logic_1: "Lógica condicional"
|
||||
# what_cover_logic_2: "- when and how to use if/else to control in-game outcomes."
|
||||
# what_cover_input_1: "Handling player input"
|
||||
# what_cover_input_2: "- responding to input events to create a user interface."
|
||||
# sys_requirements_title: "System Requirements"
|
||||
sys_requirements_title: "Requisitos do Sistema"
|
||||
# sys_requirements_1: "Because CodeCombat is a game, it is more intensive for computers to run smoothly than video or written tutorials. We have optimized it to run quickly on all modern browsers and on older machines so that everyone can play. That said, here are our suggestions for getting the most out of your Hour of Code experience:"
|
||||
# sys_requirements_2: "Use newer versions of Chrome or Firefox."
|
||||
# sys_requirements_3: "Although CodeCombat will work on browsers as old as IE9, the performance is not as good. Chrome is best."
|
||||
|
@ -769,8 +769,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
achievement_search_title: "Procurar Conquistas"
|
||||
read_only_warning2: "Nota: não podes guardar nenhuma edição feita aqui, porque não tens sessão iniciada."
|
||||
no_achievements: "Ainda não foram adicionadas conquistas a este nível."
|
||||
# achievement_query_misc: "Key achievement off of miscellanea"
|
||||
# achievement_query_goals: "Key achievement off of level goals"
|
||||
achievement_query_misc: "Conquista-chave de uma lista de variados"
|
||||
achievement_query_goals: "Conquista-chave dos objetivos do nível"
|
||||
level_completion: "Completação do Nível"
|
||||
pop_i18n: "Propagar I18N"
|
||||
tasks: "Tarefas"
|
||||
|
@ -794,7 +794,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
join_desc_2: "para começares, e assinalar a caixa abaixo para te declarares um bravo Arcomago e receberes as últimas notícias por e-mail. Queres falar sobre o que fazer ou como te envolveres mais profundamente no projeto? "
|
||||
join_desc_3: " ou encontra-nos na nossa "
|
||||
join_desc_4: "e começamos a partir daí!"
|
||||
join_url_email: "Envia-nos uma mensagem"
|
||||
join_url_email: "Contacta-nos"
|
||||
join_url_hipchat: "sala HipChat pública"
|
||||
archmage_subscribe_desc: "Receber e-mails relativos a novas oportunidades de programação e anúncios."
|
||||
artisan_introduction_pref: "Temos de construir mais níveis! As pessoas estão a pedir mais conteúdo, e nós mesmos só podemos construir estes tantos. Neste momento, a tua estação de trabalho é o nível um; o nosso editor de nível é pouco utilizável, até mesmo pelos seus criadores, por isso fica atento. Se tens visões de campanhas que abranjam 'for-loops' para o"
|
||||
|
|
|
@ -182,6 +182,7 @@ class CocoModel extends Backbone.Model
|
|||
options ?= {}
|
||||
options.data ?= {}
|
||||
options.data.project = @project.join(',') if @project
|
||||
#console.error @constructor.className, @, "fetching with cache?", options.cache, "options", options # Useful for debugging cached IE fetches
|
||||
@jqxhr = super(options)
|
||||
@loading = true
|
||||
@jqxhr
|
||||
|
@ -364,7 +365,7 @@ class CocoModel extends Backbone.Model
|
|||
achievements = new NewAchievementCollection
|
||||
achievements.fetch
|
||||
success: (collection) ->
|
||||
me.fetch (success: -> Backbone.Mediator.publish('achievements:new', earnedAchievements: collection)) unless _.isEmpty(collection.models)
|
||||
me.fetch (cache: false, success: -> Backbone.Mediator.publish('achievements:new', earnedAchievements: collection)) unless _.isEmpty(collection.models)
|
||||
error: ->
|
||||
console.error 'Miserably failed to fetch unnotified achievements', arguments
|
||||
cache: false
|
||||
|
|
|
@ -286,6 +286,7 @@ _.extend LevelSessionSchema.properties,
|
|||
type: ['string', 'null'] # 'null' in case an opponent session got corrupted, don't care much here
|
||||
description: 'What submittedCodeLanguage the opponent used during the match'
|
||||
simulator: {type: 'object', description: 'Holds info on who simulated the match, and with what tools.'}
|
||||
randomSeed: {description: 'Stores the random seed that was used during this match.'}
|
||||
|
||||
c.extendBasicProperties LevelSessionSchema, 'level.session'
|
||||
c.extendPermissionsProperties LevelSessionSchema, 'level.session'
|
||||
|
|
|
@ -63,7 +63,7 @@ $gameControlMargin: 30px
|
|||
height: 100%
|
||||
background-size: 100%
|
||||
@include user-select(none)
|
||||
|
||||
|
||||
.level, .level-shadow
|
||||
position: absolute
|
||||
border-radius: 50%
|
||||
|
@ -108,26 +108,26 @@ $gameControlMargin: 30px
|
|||
&.complete
|
||||
border: 3px solid gold
|
||||
@include box-shadow(0px 0px 35px skyblue)
|
||||
|
||||
|
||||
img.banner
|
||||
position: absolute
|
||||
bottom: 38%
|
||||
left: -50%
|
||||
width: 200%
|
||||
pointer-events: none
|
||||
|
||||
|
||||
img.star
|
||||
width: 100%
|
||||
bottom: 7%
|
||||
position: absolute
|
||||
pointer-events: none
|
||||
|
||||
|
||||
.glyphicon-star
|
||||
position: absolute
|
||||
color: lightblue
|
||||
font-size: 21px
|
||||
left: 1.5px
|
||||
|
||||
|
||||
&.started .glyphicon-star
|
||||
left: 0.5px
|
||||
|
||||
|
@ -138,7 +138,7 @@ $gameControlMargin: 30px
|
|||
left: 75%
|
||||
margin-left: 0
|
||||
margin-bottom: 0
|
||||
|
||||
|
||||
img.hero-portrait
|
||||
position: absolute
|
||||
border: 1px solid black
|
||||
|
@ -258,10 +258,10 @@ $gameControlMargin: 30px
|
|||
border-radius: 50%
|
||||
opacity: 1
|
||||
padding: 3px 9px
|
||||
|
||||
|
||||
&.complete
|
||||
.start-level, .view-solutions
|
||||
min-width: initial
|
||||
min-width: calc(50% - 5px)
|
||||
display: inline-block
|
||||
width: calc(50% - 5px)
|
||||
|
||||
|
@ -277,10 +277,10 @@ $gameControlMargin: 30px
|
|||
z-index: 1
|
||||
font-size: 2vw
|
||||
text-shadow: 0 0 0.3vw white, 0 0 0.3vw white
|
||||
|
||||
|
||||
&:hover
|
||||
text-decoration: none
|
||||
|
||||
|
||||
.next-level-line
|
||||
transform-origin: 0 100%
|
||||
height: 8px
|
||||
|
@ -314,9 +314,9 @@ $gameControlMargin: 30px
|
|||
margin-left: $gameControlMargin
|
||||
width: $gameControlSize
|
||||
height: $gameControlSize
|
||||
|
||||
|
||||
background: url(/images/pages/play/menu_icons.png) no-repeat
|
||||
|
||||
|
||||
position: relative
|
||||
img
|
||||
position: absolute
|
||||
|
@ -324,21 +324,21 @@ $gameControlMargin: 30px
|
|||
top: 0
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
|
||||
background-size: cover
|
||||
@include transition(0.5s ease)
|
||||
@include box-shadow(2px 2px 4px black)
|
||||
border: 0
|
||||
border-radius: 12px
|
||||
// IE9 shows a blank white button with this MS gradient filter in place
|
||||
filter: none
|
||||
|
||||
filter: none
|
||||
|
||||
&:hover
|
||||
@include box-shadow(0 0 12px #bbf)
|
||||
|
||||
&:active
|
||||
@include box-shadow(0 0 20px white)
|
||||
|
||||
|
||||
&.heroes
|
||||
background-position: (-1 * $gameControlSize) 0px
|
||||
&.achievements
|
||||
|
@ -369,7 +369,7 @@ $gameControlMargin: 30px
|
|||
|
||||
.user-status-line
|
||||
position: relative
|
||||
|
||||
|
||||
button.btn.btn-illustrated
|
||||
margin-left: 10px
|
||||
min-width: 90px
|
||||
|
@ -390,7 +390,7 @@ $gameControlMargin: 30px
|
|||
margin-left: 45px
|
||||
|
||||
$spriteSheetSize: 30px
|
||||
|
||||
|
||||
.player-level-icon, .player-hero-icon
|
||||
background: transparent url(/images/pages/play/play-spritesheet.png)
|
||||
background-size: cover
|
||||
|
@ -420,7 +420,7 @@ $gameControlMargin: 30px
|
|||
background-position: (-11 * $spriteSheetSize) 0
|
||||
&.sorcerer
|
||||
background-position: (-12 * $spriteSheetSize) 0
|
||||
|
||||
|
||||
|
||||
#volume-button
|
||||
position: absolute
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
width: 300px
|
||||
|
||||
h1
|
||||
font-size: 29px
|
||||
font-size: 28px
|
||||
font-weight: bold
|
||||
color: black
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ module.exports = class MyMatchesTabView extends CocoView
|
|||
stale: match.date < submitDate
|
||||
fresh: fresh
|
||||
codeLanguage: match.codeLanguage
|
||||
simulator: JSON.stringify(match.simulator)
|
||||
simulator: JSON.stringify(match.simulator) + ' | seed ' + match.randomSeed
|
||||
}
|
||||
|
||||
for team in @teams
|
||||
|
|
|
@ -187,13 +187,13 @@ module.exports = class SpectateLevelView extends RootView
|
|||
ctx.fillText("Loaded #{@modelsLoaded} thingies",50,50)
|
||||
|
||||
insertSubviews: ->
|
||||
@insertSubView @tome = new TomeView levelID: @levelID, session: @session, thangs: @world.thangs, supermodel: @supermodel, spectateView: true, spectateOpponentCodeLanguage: @otherSession?.get('submittedCodeLanguage'), level: @level
|
||||
@insertSubView new PlaybackView {}
|
||||
@insertSubView @tome = new TomeView levelID: @levelID, session: @session, otherSession: @otherSession, thangs: @world.thangs, supermodel: @supermodel, spectateView: true, spectateOpponentCodeLanguage: @otherSession?.get('submittedCodeLanguage'), level: @level
|
||||
@insertSubView new PlaybackView session: @session, level: @level
|
||||
|
||||
@insertSubView new GoldView {}
|
||||
@insertSubView new HUDView {}
|
||||
@insertSubView new HUDView {level: @level}
|
||||
worldName = utils.i18n @level.attributes, 'name'
|
||||
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, playableTeams: @world.playableTeams, spectateGame: true}
|
||||
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel, spectateGame: true}
|
||||
|
||||
# callbacks
|
||||
|
||||
|
@ -207,7 +207,7 @@ module.exports = class SpectateLevelView extends RootView
|
|||
initSurface: ->
|
||||
webGLSurface = $('canvas#webgl-surface', @$el)
|
||||
normalSurface = $('canvas#normal-surface', @$el)
|
||||
@surface = new Surface(@world, normalSurface, webGLSurface, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview, spectateGame: true, wizards: @level.get('type', true) isnt 'hero')
|
||||
@surface = new Surface @world, normalSurface, webGLSurface, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview, spectateGame: true, wizards: @level.get('type', true) is 'ladder', playerNames: @findPlayerNames()
|
||||
worldBounds = @world.getBounds()
|
||||
bounds = [{x:worldBounds.left, y:worldBounds.top}, {x:worldBounds.right, y:worldBounds.bottom}]
|
||||
@surface.camera.setBounds(bounds)
|
||||
|
@ -215,6 +215,12 @@ module.exports = class SpectateLevelView extends RootView
|
|||
@surface.camera.zoomTo({x: (worldBounds.right - worldBounds.left) / 2, y: (worldBounds.top - worldBounds.bottom) / 2}, 0.1, 0)
|
||||
_.delay zoom, 4000 # call it later for some reason (TODO: figure this out)
|
||||
|
||||
findPlayerNames: ->
|
||||
playerNames = {}
|
||||
for session in [@session, @otherSession] when session?.get('team')
|
||||
playerNames[session.get('team')] = session.get('creatorName') or 'Anoner'
|
||||
playerNames
|
||||
|
||||
initGoalManager: ->
|
||||
@goalManager = new GoalManager(@world, @level.get('goals'))
|
||||
@god.setGoalManager @goalManager
|
||||
|
|
|
@ -56,27 +56,26 @@ module.exports = class LadderSubmissionView extends CocoView
|
|||
failure = (jqxhr, textStatus, errorThrown) =>
|
||||
console.log jqxhr.responseText
|
||||
@setRankingButtonText 'failed' unless @destroyed
|
||||
transpiledCode = @transpileSession()
|
||||
@transpileSession (transpiledCode) =>
|
||||
|
||||
ajaxData =
|
||||
session: @session.id
|
||||
levelID: @level.id
|
||||
originalLevelID: @level.get('original')
|
||||
levelMajorVersion: @level.get('version').major
|
||||
transpiledCode: transpiledCode
|
||||
ajaxData =
|
||||
session: @session.id
|
||||
levelID: @level.id
|
||||
originalLevelID: @level.get('original')
|
||||
levelMajorVersion: @level.get('version').major
|
||||
transpiledCode: transpiledCode
|
||||
|
||||
$.ajax '/queue/scoring', {
|
||||
type: 'POST'
|
||||
data: ajaxData
|
||||
success: success
|
||||
error: failure
|
||||
}
|
||||
$.ajax '/queue/scoring', {
|
||||
type: 'POST'
|
||||
data: ajaxData
|
||||
success: success
|
||||
error: failure
|
||||
}
|
||||
|
||||
transpileSession: ->
|
||||
transpileSession: (callback) ->
|
||||
submittedCode = @session.get('code')
|
||||
codeLanguage = @session.get('codeLanguage') or 'javascript'
|
||||
@session.set('submittedCodeLanguage', codeLanguage)
|
||||
@session.save() # TODO: maybe actually use a callback to make sure this works?
|
||||
transpiledCode = {}
|
||||
for thang, spells of submittedCode
|
||||
transpiledCode[thang] = {}
|
||||
|
@ -85,7 +84,7 @@ module.exports = class LadderSubmissionView extends CocoView
|
|||
aetherOptions = createAetherOptions functionName: spellID, codeLanguage: codeLanguage
|
||||
aether = new Aether aetherOptions
|
||||
transpiledCode[thang][spellID] = aether.transpile spell
|
||||
transpiledCode
|
||||
@session.save null, success: -> callback transpiledCode
|
||||
|
||||
onHelpSimulate: ->
|
||||
@playSound 'menu-button-click'
|
||||
|
|
|
@ -305,12 +305,19 @@ module.exports = class PlayLevelView extends RootView
|
|||
initSurface: ->
|
||||
webGLSurface = $('canvas#webgl-surface', @$el)
|
||||
normalSurface = $('canvas#normal-surface', @$el)
|
||||
@surface = new Surface(@world, normalSurface, webGLSurface, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview, wizards: not (@level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']))
|
||||
@surface = new Surface(@world, normalSurface, webGLSurface, thangTypes: @supermodel.getModels(ThangType), playJingle: not @isEditorPreview, wizards: not (@level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']), observing: @observing, playerNames: @findPlayerNames())
|
||||
worldBounds = @world.getBounds()
|
||||
bounds = [{x: worldBounds.left, y: worldBounds.top}, {x: worldBounds.right, y: worldBounds.bottom}]
|
||||
@surface.camera.setBounds(bounds)
|
||||
@surface.camera.zoomTo({x: 0, y: 0}, 0.1, 0)
|
||||
|
||||
findPlayerNames: ->
|
||||
return {} unless @observing
|
||||
playerNames = {}
|
||||
for session in [@session, @otherSession] when session?.get('team')
|
||||
playerNames[session.get('team')] = session.get('creatorName') or 'Anoner'
|
||||
playerNames
|
||||
|
||||
# Once Surface is Loaded ####################################################
|
||||
|
||||
onLevelStarted: ->
|
||||
|
|
|
@ -206,7 +206,7 @@ module.exports = class Spell
|
|||
|
||||
@problemContext = { stringReferences: [], thisMethods: [], thisProperties: [] }
|
||||
# TODO: These should be read from the database
|
||||
@problemContext.commonThisMethods = ['moveRight', 'moveLeft', 'moveUp', 'moveDown', 'attack', 'findNearestEnemy', 'buildXY', 'moveXY', 'say', 'move', 'distance', 'findEnemies', 'getFriends', 'addFlag', 'getFlag', 'removeFlag', 'getFlags', 'attackRange', 'cast', 'buildTypes', 'jump', 'jumpTo', 'attackXY']
|
||||
@problemContext.commonThisMethods = ['moveRight', 'moveLeft', 'moveUp', 'moveDown', 'attack', 'findNearestEnemy', 'buildXY', 'moveXY', 'say', 'move', 'distance', 'findEnemies', 'findFriends', 'addFlag', 'findFlag', 'removeFlag', 'findFlags', 'attackRange', 'cast', 'buildTypes', 'jump', 'jumpTo', 'attackXY']
|
||||
return @problemContext unless thang?
|
||||
|
||||
# Populate stringReferences
|
||||
|
|
|
@ -22,7 +22,8 @@ options =
|
|||
simulateOnlyOneGame: simulateOneGame
|
||||
|
||||
options.heapdump = require('heapdump') if options.heapdump
|
||||
server = if options.testing then 'http://127.0.0.1:3000' else 'https://codecombat.com'
|
||||
server = if options.testing then 'http://127.0.0.1:3000' else 'http://direct.codecombat.com'
|
||||
# Use direct instead of live site because jQlone's requests proxy doesn't do caching properly and CloudFlare gets too aggressive.
|
||||
|
||||
# Disabled modules
|
||||
disable = [
|
||||
|
@ -62,12 +63,16 @@ hookedLoader = (request, parent, isMain) ->
|
|||
if request in disable or ~request.indexOf('templates')
|
||||
console.log 'Ignored ' + request if options.debug
|
||||
return class fake
|
||||
else if /node_modules[\\\/]aether[\\\/]/.test parent.id
|
||||
null # Let it through
|
||||
else if '/' in request and not (request[0] is '.') or request is 'application'
|
||||
#console.log 'making path', path + '/app/' + request, 'from', path, request, 'with parent', parent
|
||||
request = path + '/app/' + request
|
||||
else if request is 'underscore'
|
||||
request = 'lodash'
|
||||
console.log 'loading ' + request if options.debug
|
||||
originalLoader request, parent, isMain
|
||||
|
||||
unhook = () ->
|
||||
m._load = originalLoader
|
||||
hook = () ->
|
||||
|
@ -90,6 +95,7 @@ GLOBAL.Backbone = require bowerComponentsPath + 'backbone/backbone'
|
|||
unhook()
|
||||
Backbone.$ = $
|
||||
require bowerComponentsPath + 'validated-backbone-mediator/backbone-mediator'
|
||||
Backbone.Mediator.setValidationEnabled false
|
||||
GLOBAL.Aether = require 'aether'
|
||||
# Set up new loader. Again.
|
||||
hook()
|
||||
|
|
|
@ -9,7 +9,7 @@ module.exports = $ = (input) ->
|
|||
|
||||
# Non-standard jQuery stuff. Don't use outside of server.
|
||||
$._debug = false
|
||||
$._server = 'https://codecombat.com'
|
||||
$._server = 'http://direct.codecombat.com'
|
||||
$._cookies = request.jar()
|
||||
|
||||
$.when = Deferred.when
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -100,12 +100,12 @@ work = () ->
|
|||
|
||||
self.postMessage type: 'start-load-frames'
|
||||
|
||||
self.world.loadFrames self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress, true
|
||||
self.world.loadFrames self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress, null, true
|
||||
|
||||
self.onWorldLoaded = onWorldLoaded = ->
|
||||
self.goalManager.worldGenerationEnded()
|
||||
goalStates = self.goalManager.getGoalStates()
|
||||
self.postMessage type: 'end-load-frames', goalStates: goalStates
|
||||
self.postMessage type: 'end-load-frames', goalStates: goalStates, overallStatus: goalManager.checkOverallStatus()
|
||||
|
||||
t1 = new Date()
|
||||
diff = t1 - self.t0
|
||||
|
@ -148,7 +148,9 @@ work = () ->
|
|||
self.postedErrors[errorKey] = error
|
||||
else
|
||||
console.log 'Non-UserCodeError:', error.toString() + "\n" + error.stack or error.stackTrace
|
||||
self.postMessage type: 'non-user-code-problem', problem: {message: error.toString()}
|
||||
self.cleanUp()
|
||||
return false
|
||||
return true
|
||||
|
||||
self.onWorldLoadProgress = onWorldLoadProgress = (progress) ->
|
||||
|
@ -176,9 +178,19 @@ work = () ->
|
|||
|
||||
self.postMessage type: 'worker-initialized'
|
||||
|
||||
worldCode = fs.readFileSync './public/javascripts/world.js', 'utf8'
|
||||
lodashCode = fs.readFileSync './public/javascripts/lodash.js', 'utf8'
|
||||
aetherCode = fs.readFileSync './public/javascripts/aether.js', 'utf8'
|
||||
codeFileContents = []
|
||||
for codeFile in [
|
||||
'lodash.js'
|
||||
'world.js'
|
||||
'aether.js'
|
||||
'app/vendor/aether-clojure.js'
|
||||
'app/vendor/aether-coffeescript.js'
|
||||
'app/vendor/aether-io.js'
|
||||
'app/vendor/aether-javascript.js'
|
||||
'app/vendor/aether-lua.js'
|
||||
'app/vendor/aether-python.js'
|
||||
]
|
||||
codeFileContents.push fs.readFileSync("./public/javascripts/#{codeFile}", 'utf8')
|
||||
|
||||
#window.BOX2D_ENABLED = true;
|
||||
|
||||
|
@ -195,9 +207,7 @@ ret = """
|
|||
|
||||
try {
|
||||
// the world javascript file
|
||||
#{worldCode};
|
||||
#{lodashCode};
|
||||
#{aetherCode};
|
||||
#{codeFileContents.join(';\n ')};
|
||||
|
||||
// Don't let user generated code access stuff from our file system!
|
||||
self.importScripts = importScripts = null;
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
"aws-sdk": "~2.0.0",
|
||||
"bayesian-battle": "0.0.x",
|
||||
"redis": "",
|
||||
"webworker-threads": "~0.4.11",
|
||||
"webworker-threads": "~0.5.5",
|
||||
"node-gyp": "~0.13.0",
|
||||
"aether": "~0.3.0",
|
||||
"JASON": "~0.1.3",
|
||||
|
|
|
@ -15,7 +15,7 @@ bayes = new (require 'bayesian-battle')()
|
|||
scoringTaskQueue = undefined
|
||||
scoringTaskTimeoutInSeconds = 600
|
||||
|
||||
SIMULATOR_VERSION = 1
|
||||
SIMULATOR_VERSION = 3
|
||||
|
||||
module.exports.setup = (app) -> connectToScoringQueue()
|
||||
|
||||
|
@ -611,6 +611,7 @@ updateMatchesInSession = (matchObject, sessionID, callback) ->
|
|||
currentMatchObject.opponents = opponentsArray
|
||||
currentMatchObject.codeLanguage = matchObject.opponents[opponentsArray[0].sessionID].codeLanguage
|
||||
currentMatchObject.simulator = @clientResponseObject.simulator
|
||||
currentMatchObject.randomSeed = parseInt(@clientResponseObject.randomSeed or 0, 10)
|
||||
LevelSession.findOne {'_id': sessionID}, (err, session) ->
|
||||
session = session.toObject()
|
||||
currentMatchObject.playtime = session.playtime ? 0
|
||||
|
|
Loading…
Reference in a new issue