Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Barney 2015-02-13 12:34:37 +08:00
commit 295ecf53c2
24 changed files with 159 additions and 112 deletions

View file

@ -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) {

View file

@ -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")

View file

@ -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?

View file

@ -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 =

View file

@ -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

View file

@ -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

View file

@ -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: ->

View file

@ -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()

View file

@ -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"

View file

@ -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

View file

@ -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'

View file

@ -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

View file

@ -35,7 +35,7 @@
width: 300px
h1
font-size: 29px
font-size: 28px
font-weight: bold
color: black

View file

@ -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

View file

@ -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

View file

@ -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'

View file

@ -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: ->

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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;

View file

@ -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",

View file

@ -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