Merge branch 'master' of https://github.com/codecombat/codecombat
This commit is contained in:
commit
c58a27fcbf
80 changed files with 1091 additions and 118 deletions
.gitignore.npmignoreheadless_client.coffee
app
lib
locale
ar.coffeebg.coffeeca.coffeecs.coffeeda.coffeede-AT.coffeede-CH.coffeede-DE.coffeede.coffeeel.coffeeen-AU.coffeeen-GB.coffeeen-US.coffeeen.coffeees-419.coffeees-ES.coffeees.coffeefa.coffeefi.coffeefr.coffeehe.coffeehi.coffeehu.coffeeid.coffeeit.coffeeja.coffeeko.coffeelt.coffeems.coffeenb.coffeenl-BE.coffeenl-NL.coffeenl.coffeenn.coffeeno.coffeepl.coffeept-BR.coffeept-PT.coffeept.coffeero.coffeeru.coffeesk.coffeesl.coffeesr.coffeesv.coffeeth.coffeetr.coffeeuk.coffeeur.coffeevi.coffeezh-HANS.coffeezh-HANT.coffeezh-WUU-HANS.coffeezh-WUU-HANT.coffeezh.coffee
models
schemas/models
templates/play/level/modal
views/play
headless_client
package.json
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -28,6 +28,9 @@ Thumbs.db
|
||||||
*.sublime-project
|
*.sublime-project
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IntelliJ/WebStorm
|
||||||
|
*.iml
|
||||||
|
|
||||||
# NPM packages folder.
|
# NPM packages folder.
|
||||||
node_modules/
|
node_modules/
|
||||||
bower_components/
|
bower_components/
|
||||||
|
@ -77,4 +80,10 @@ bin/mongo/
|
||||||
# windows
|
# windows
|
||||||
/SCOCODE.bat
|
/SCOCODE.bat
|
||||||
|
|
||||||
|
# local settings
|
||||||
|
login.coffee
|
||||||
|
|
||||||
|
# debugging
|
||||||
|
*.heapsnapshot
|
||||||
|
|
||||||
### If you add something here, copy it to the end of .npmignore, too. ###
|
### If you add something here, copy it to the end of .npmignore, too. ###
|
11
.npmignore
11
.npmignore
|
@ -53,6 +53,9 @@ Thumbs.db
|
||||||
*.sublime-project
|
*.sublime-project
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IntelliJ/WebStorm
|
||||||
|
*.iml
|
||||||
|
|
||||||
# NPM packages folder.
|
# NPM packages folder.
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
|
@ -89,6 +92,12 @@ mongo/
|
||||||
bin/node/
|
bin/node/
|
||||||
bin/mongo/
|
bin/mongo/
|
||||||
|
|
||||||
|
|
||||||
# Karma coverage
|
# Karma coverage
|
||||||
coverage/
|
coverage/
|
||||||
|
|
||||||
|
# local settings
|
||||||
|
login.coffee
|
||||||
|
|
||||||
|
# debugging
|
||||||
|
*.heapsnapshot
|
||||||
|
|
||||||
|
|
241
app/lib/Buddha.coffee
Normal file
241
app/lib/Buddha.coffee
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
#Sane rewrite of God (a thread pool)
|
||||||
|
{now} = require 'lib/world/world_utils'
|
||||||
|
World = require 'lib/world/world'
|
||||||
|
|
||||||
|
###
|
||||||
|
Every Angel has exactly one WebWorker attached to it.
|
||||||
|
It will call methods inside the webwrker and kill it if it times out.
|
||||||
|
###
|
||||||
|
class Angel
|
||||||
|
@cyanide: 0xDEADBEEF
|
||||||
|
|
||||||
|
infiniteLoopIntervalDuration: 7500 # check this often (must be more than the others added)
|
||||||
|
infiniteLoopTimeoutDuration: 10000 # wait this long when we check
|
||||||
|
abortTimeoutDuration: 500 # give in-process or dying workers this long to give up
|
||||||
|
|
||||||
|
constructor: (@id, @shared) ->
|
||||||
|
console.log @id + ": Creating Angel"
|
||||||
|
if (navigator.userAgent or navigator.vendor or window.opera).search("MSIE") isnt -1
|
||||||
|
@infiniteLoopIntervalDuration *= 20 # since it's so slow to serialize without transferable objects, we can't trust it
|
||||||
|
@infiniteLoopTimeoutDuration *= 20
|
||||||
|
@abortTimeoutDuration *= 10
|
||||||
|
@initialized = false
|
||||||
|
@running = false
|
||||||
|
@hireWorker()
|
||||||
|
@shared.angels.push @
|
||||||
|
|
||||||
|
testWorker: =>
|
||||||
|
if @initialized
|
||||||
|
@worker.postMessage {func: 'reportIn'}
|
||||||
|
# Are there any errors when webworker isn't loaded properly?
|
||||||
|
|
||||||
|
onWorkerMessage: (event) =>
|
||||||
|
#console.log JSON.stringify event
|
||||||
|
if @aborting and not
|
||||||
|
event.data.type is 'abort'
|
||||||
|
console.log id + " is currently aborting old work."
|
||||||
|
return
|
||||||
|
|
||||||
|
switch event.data.type
|
||||||
|
when 'start-load-frames'
|
||||||
|
clearTimeout(@condemnTimeout)
|
||||||
|
@condemnTimeout = _.delay @infinitelyLooped, @infiniteLoopTimeoutDuration
|
||||||
|
when 'end-load-frames'
|
||||||
|
console.log @id + ': No condemn this time.'
|
||||||
|
clearTimeout(@condemnTimeout)
|
||||||
|
when 'worker-initialized'
|
||||||
|
unless @initialized
|
||||||
|
console.log @id + ": Worker initialized after", ((new Date()) - @worker.creationTime), "ms"
|
||||||
|
@initialized = true
|
||||||
|
@doWork()
|
||||||
|
when 'new-world'
|
||||||
|
@beholdWorld event.data.serialized, event.data.goalStates
|
||||||
|
when 'world-load-progress-changed'
|
||||||
|
Backbone.Mediator.publish 'god:world-load-progress-changed', event.data
|
||||||
|
when 'console-log'
|
||||||
|
console.log "|" + @id + "|", event.data.args...
|
||||||
|
when 'user-code-problem'
|
||||||
|
Backbone.Mediator.publish 'god:user-code-problem', problem: event.data.problem
|
||||||
|
when 'abort'
|
||||||
|
console.log @id, "aborted."
|
||||||
|
clearTimeout @abortTimeout
|
||||||
|
@aborting = false
|
||||||
|
@running = false
|
||||||
|
@shared.busyAngels.pop @
|
||||||
|
@doWork()
|
||||||
|
when 'reportIn'
|
||||||
|
clearTimeout @condemnTimeout
|
||||||
|
else
|
||||||
|
console.log @id + " received unsupported message:", event.data
|
||||||
|
|
||||||
|
beholdWorld: (serialized, goalStates) ->
|
||||||
|
return if @aborting
|
||||||
|
unless serialized
|
||||||
|
# We're only interested in goalStates. (Simulator)
|
||||||
|
@latestGoalStates = goalStates
|
||||||
|
Backbone.Mediator.publish('god:goals-calculated', goalStates: goalStates)
|
||||||
|
@running = false
|
||||||
|
@shared.busyAngels.pop @
|
||||||
|
|
||||||
|
# console.warn "Goal states: " + JSON.stringify(goalStates)
|
||||||
|
|
||||||
|
window.BOX2D_ENABLED = false # Flip this off so that if we have box2d in the namespace, the Collides Components still don't try to create bodies for deserialized Thangs upon attachment
|
||||||
|
World.deserialize serialized, @shared.worldClassMap, @lastSerializedWorldFrames, @finishBeholdingWorld(goalStates)
|
||||||
|
window.BOX2D_ENABLED = true
|
||||||
|
@lastSerializedWorldFrames = serialized.frames
|
||||||
|
|
||||||
|
finishBeholdingWorld: (goalStates) => (world) =>
|
||||||
|
return if @aborting
|
||||||
|
world.findFirstChangedFrame @shared.world
|
||||||
|
@shared.world = world
|
||||||
|
errorCount = (t for t in @shared.world.thangs when t.errorsOut).length
|
||||||
|
Backbone.Mediator.publish('god:new-world-created', world: world, firstWorld: @shared.firstWorld, errorCount: errorCount, goalStates: goalStates)
|
||||||
|
for scriptNote in @shared.world.scriptNotes
|
||||||
|
Backbone.Mediator.publish scriptNote.channel, scriptNote.event
|
||||||
|
@shared.goalManager?.world = world
|
||||||
|
@running = false
|
||||||
|
@shared.busyAngels.pop @
|
||||||
|
@shared.firstWorld = false
|
||||||
|
@doWork()
|
||||||
|
|
||||||
|
infinitelyLooped: =>
|
||||||
|
unless @aborting
|
||||||
|
problem = type: "runtime", level: "error", id: "runtime_InfiniteLoop", message: "Code never finished. It's either really slow or has an infinite loop."
|
||||||
|
Backbone.Mediator.publish 'god:user-code-problem', problem: problem
|
||||||
|
Backbone.Mediator.publish 'god:infinite-loop', firstWorld: @shared.firstWorld
|
||||||
|
@fireWorker()
|
||||||
|
|
||||||
|
workIfIdle: ->
|
||||||
|
@doWork() unless @running
|
||||||
|
|
||||||
|
doWork: =>
|
||||||
|
#console.log "work."
|
||||||
|
return if @aborted
|
||||||
|
console.log @id + " ready and looking for work. WorkQueue length is " + @shared.workQueue.length
|
||||||
|
if @initialized and @shared.workQueue.length
|
||||||
|
work = @shared.workQueue.pop()
|
||||||
|
if work is Angel.cyanide # Kill all other Angels, too
|
||||||
|
console.log @id + ": 'work is poison'"
|
||||||
|
@shared.workQueue.push Angel.cyanide
|
||||||
|
@free()
|
||||||
|
else
|
||||||
|
console.log @id + ": Sending the worker to work."
|
||||||
|
@running = true
|
||||||
|
@shared.busyAngels.push @
|
||||||
|
|
||||||
|
console.log "Running world..."
|
||||||
|
#console.error "worker.postMessage: " + @worker.postMessage + ", work: " + work
|
||||||
|
@worker.postMessage func: 'runWorld', args: work
|
||||||
|
console.log @id + ": Setting interval."
|
||||||
|
clearTimeout @purgatoryTimer
|
||||||
|
@purgatoryTimer = setInterval @testWorker, @infiniteLoopIntervalDuration
|
||||||
|
else
|
||||||
|
console.log "No work for " + @id
|
||||||
|
@hireWorker()
|
||||||
|
|
||||||
|
abort: =>
|
||||||
|
if @worker and @running
|
||||||
|
console.log "Aborting " + @id
|
||||||
|
@running = false
|
||||||
|
@shared.busyAngels.pop @
|
||||||
|
@abortTimeout = _.delay @terminate, @fireWorker, @abortTimeoutDuration
|
||||||
|
@worker.postMessage func: 'abort'
|
||||||
|
@aborting = true
|
||||||
|
@work = null
|
||||||
|
|
||||||
|
fireWorker: (rehire=true) =>
|
||||||
|
@aborting = false
|
||||||
|
@running = false
|
||||||
|
@shared.busyAngels.pop @
|
||||||
|
@worker?.removeEventListener 'message', @onWorkerMessage
|
||||||
|
@worker?.terminate()
|
||||||
|
@worker = null
|
||||||
|
clearTimeout @condemnTimeout
|
||||||
|
clearInterval @purgatoryTimer
|
||||||
|
console.log "Fired worker."
|
||||||
|
@initialized = false
|
||||||
|
@work = null
|
||||||
|
@hireWorker() if rehire
|
||||||
|
|
||||||
|
hireWorker: ->
|
||||||
|
unless @worker
|
||||||
|
console.log @id + ": Hiring worker."
|
||||||
|
@worker = new Worker @shared.workerCode
|
||||||
|
@worker.addEventListener 'message', @onWorkerMessage
|
||||||
|
@worker.creationTime = new Date()
|
||||||
|
#@worker.postMessage func: 'initialized' else
|
||||||
|
|
||||||
|
kill: ->
|
||||||
|
@fireWorker false
|
||||||
|
@shared.angels.pop @
|
||||||
|
clearTimeout @condemnTimeout
|
||||||
|
clearTimeout @purgatoryTimer
|
||||||
|
@purgatoryTimer = null
|
||||||
|
@condemnTimeout = null
|
||||||
|
|
||||||
|
module.exports = class God
|
||||||
|
ids: ['Athena', 'Baldr', 'Crom', 'Dagr', 'Eris', 'Freyja', 'Great Gish', 'Hades', 'Ishtar', 'Janus', 'Khronos', 'Loki', 'Marduk', 'Negafook', 'Odin', 'Poseidon', 'Quetzalcoatl', 'Ra', 'Shiva', 'Thor', 'Umvelinqangi', 'Týr', 'Vishnu', 'Wepwawet', 'Xipe Totec', 'Yahweh', 'Zeus', '上帝', 'Tiamat', '盘古', 'Phoebe', 'Artemis', 'Osiris', "嫦娥", 'Anhur', 'Teshub', 'Enlil', 'Perkele', 'Chaos', 'Hera', 'Iris', 'Theia', 'Uranus', 'Stribog', 'Sabazios', 'Izanagi', 'Ao', 'Tāwhirimātea', 'Tengri', 'Inmar', 'Torngarsuk', 'Centzonhuitznahua', 'Hunab Ku', 'Apollo', 'Helios', 'Thoth', 'Hyperion', 'Alectrona', 'Eos', 'Mitra', 'Saranyu', 'Freyr', 'Koyash', 'Atropos', 'Clotho', 'Lachesis', 'Tyche', 'Skuld', 'Urðr', 'Verðandi', 'Camaxtli', 'Huhetotl', 'Set', 'Anu', 'Allah', 'Anshar', 'Hermes', 'Lugh', 'Brigit', 'Manannan Mac Lir', 'Persephone', 'Mercury', 'Venus', 'Mars', 'Azrael', 'He-Man', 'Anansi', 'Issek', 'Mog', 'Kos', 'Amaterasu Omikami', 'Raijin', 'Susanowo', 'Blind Io', 'The Lady', 'Offler', 'Ptah', 'Anubis', 'Ereshkigal', 'Nergal', 'Thanatos', 'Macaria', 'Angelos', 'Erebus', 'Hecate', 'Hel', 'Orcus', 'Ishtar-Deela Nakh', 'Prometheus', 'Hephaestos', 'Sekhmet', 'Ares', 'Enyo', 'Otrera', 'Pele', 'Hadúr', 'Hachiman', 'Dayisun Tngri', 'Ullr', 'Lua', 'Minerva']
|
||||||
|
nextID: ->
|
||||||
|
@lastID = (if @lastID? then @lastID + 1 else Math.floor(@ids.length * Math.random())) % @ids.length
|
||||||
|
@ids[@lastID]
|
||||||
|
|
||||||
|
# Charlie's Angels are all given access to this.
|
||||||
|
angelsShare: {
|
||||||
|
workerCode: '/javascripts/workers/worker_world.js' # Either path or function
|
||||||
|
workQueue: []
|
||||||
|
firstWorld: true
|
||||||
|
world: undefined
|
||||||
|
goalManager: undefined
|
||||||
|
worldClassMap: undefined
|
||||||
|
angels: []
|
||||||
|
busyAngels: [] # Busy angels will automatically register here.
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor: (options) ->
|
||||||
|
options ?= {}
|
||||||
|
|
||||||
|
@angelsShare.workerCode = options.workerCode if options.workerCode
|
||||||
|
|
||||||
|
# ~20MB per idle worker + angel overhead - in this implementation, every Angel maps to 1 worker
|
||||||
|
angelCount = options.maxAngels ? options.maxWorkerPoolSize ? 2 # How many concurrent Angels/web workers to use at a time
|
||||||
|
|
||||||
|
_.delay (=>new Angel @nextID(), @angelsShare), 250 * i for i in [0...angelCount] # Don't generate all Angels at once.
|
||||||
|
Backbone.Mediator.subscribe 'tome:cast-spells', @onTomeCast, @
|
||||||
|
|
||||||
|
onTomeCast: (e) ->
|
||||||
|
@createWorld e.spells
|
||||||
|
|
||||||
|
setGoalManager: (goalManager) =>
|
||||||
|
@angelsShare.goalManager = goalManager
|
||||||
|
|
||||||
|
setWorldClassMap: (worldClassMap) =>
|
||||||
|
@angelsShare.worldClassMap = worldClassMap
|
||||||
|
|
||||||
|
getUserCodeMap: (spells) ->
|
||||||
|
userCodeMap = {}
|
||||||
|
for spellKey, spell of spells
|
||||||
|
for thangID, spellThang of spell.thangs
|
||||||
|
(userCodeMap[thangID] ?= {})[spell.name] = spellThang.aether.serialize()
|
||||||
|
|
||||||
|
#console.log userCodeMap
|
||||||
|
userCodeMap
|
||||||
|
|
||||||
|
createWorld: (spells) =>
|
||||||
|
angel.abort() for angel in @angelsShare.busyAngels # We really only ever want one world calculated per God
|
||||||
|
#console.log "Level: " + @level
|
||||||
|
@angelsShare.workQueue.push
|
||||||
|
worldName: @level.name
|
||||||
|
userCodeMap: @getUserCodeMap(spells)
|
||||||
|
level: @level
|
||||||
|
goals: @angelsShare.goalManager?.getGoals()
|
||||||
|
angel.workIfIdle() for angel in @angelsShare.angels
|
||||||
|
|
||||||
|
destroy: =>
|
||||||
|
console.log "Destroying Buddha"
|
||||||
|
@createWorld = -> console.log "CreateWorld already gone."
|
||||||
|
@angelsShare.workQueue.push Angel.cyanide
|
||||||
|
angel.kill for angel in @angelsShare.busyAngels
|
||||||
|
Backbone.Mediator.unsubscribe('tome:cast-spells', @onTomeCast, @)
|
||||||
|
@angelsShare.goalManager?.destroy()
|
||||||
|
@angelsShare.goalManager = null
|
||||||
|
@angelsShare = null
|
|
@ -18,16 +18,18 @@ module.exports = class God
|
||||||
options ?= {}
|
options ?= {}
|
||||||
@maxAngels = options.maxAngels ? 2 # How many concurrent web workers to use; if set past 8, make up more names
|
@maxAngels = options.maxAngels ? 2 # How many concurrent web workers to use; if set past 8, make up more names
|
||||||
@maxWorkerPoolSize = options.maxWorkerPoolSize ? 2 # ~20MB per idle worker
|
@maxWorkerPoolSize = options.maxWorkerPoolSize ? 2 # ~20MB per idle worker
|
||||||
|
@workerCode = options.workerCode if options.workerCode?
|
||||||
@angels = []
|
@angels = []
|
||||||
@firstWorld = true
|
@firstWorld = true
|
||||||
Backbone.Mediator.subscribe 'tome:cast-spells', @onTomeCast, @
|
Backbone.Mediator.subscribe 'tome:cast-spells', @onTomeCast, @
|
||||||
@fillWorkerPool = _.throttle @fillWorkerPool, 3000, leading: false
|
@fillWorkerPool = _.throttle @fillWorkerPool, 3000, leading: false
|
||||||
@fillWorkerPool()
|
@fillWorkerPool()
|
||||||
|
|
||||||
|
workerCode: '/javascripts/workers/worker_world.js' #Can be a string or a function.
|
||||||
|
|
||||||
onTomeCast: (e) ->
|
onTomeCast: (e) ->
|
||||||
return if @dead
|
return if @dead
|
||||||
@spells = e.spells
|
@createWorld e.spells
|
||||||
@createWorld()
|
|
||||||
|
|
||||||
fillWorkerPool: =>
|
fillWorkerPool: =>
|
||||||
return unless Worker and not @dead
|
return unless Worker and not @dead
|
||||||
|
@ -44,17 +46,21 @@ module.exports = class God
|
||||||
@createWorker()
|
@createWorker()
|
||||||
|
|
||||||
createWorker: ->
|
createWorker: ->
|
||||||
worker = new Worker '/javascripts/workers/worker_world.js'
|
worker = new Worker @workerCode
|
||||||
worker.creationTime = new Date()
|
worker.creationTime = new Date()
|
||||||
worker.addEventListener 'message', @onWorkerMessage
|
worker.addEventListener 'message', @onWorkerMessage(worker)
|
||||||
worker
|
worker
|
||||||
|
|
||||||
onWorkerMessage: (event) =>
|
onWorkerMessage: (worker) =>
|
||||||
worker = event.target
|
unless worker.onMessage?
|
||||||
|
worker.onMessage = (event) =>
|
||||||
if event.data.type is 'worker-initialized'
|
if event.data.type is 'worker-initialized'
|
||||||
#console.log @id, "worker initialized after", ((new Date()) - worker.creationTime), "ms (before it was needed)"
|
console.log @id, "worker initialized after", ((new Date()) - worker.creationTime), "ms (before it was needed)"
|
||||||
worker.initialized = true
|
worker.initialized = true
|
||||||
worker.removeEventListener 'message', @onWorkerMessage
|
worker.removeEventListener 'message', worker.onMessage
|
||||||
|
else
|
||||||
|
console.warn "Received strange word from God: #{event.data.type}"
|
||||||
|
worker.onMessage
|
||||||
|
|
||||||
getAngel: ->
|
getAngel: ->
|
||||||
freeAngel = null
|
freeAngel = null
|
||||||
|
@ -86,7 +92,7 @@ module.exports = class God
|
||||||
#console.log "UserCodeProblem:", '"' + problem.message + '"', "for", problem.userInfo.thangID, "-", problem.userInfo.methodName, 'at line', problem.ranges?[0][0][0], 'column', problem.ranges?[0][0][1]
|
#console.log "UserCodeProblem:", '"' + problem.message + '"', "for", problem.userInfo.thangID, "-", problem.userInfo.methodName, 'at line', problem.ranges?[0][0][0], 'column', problem.ranges?[0][0][1]
|
||||||
Backbone.Mediator.publish 'god:user-code-problem', problem: problem
|
Backbone.Mediator.publish 'god:user-code-problem', problem: problem
|
||||||
|
|
||||||
createWorld: ->
|
createWorld: (@spells) ->
|
||||||
#console.log @id + ': "Let there be light upon', @world.name + '!"'
|
#console.log @id + ': "Let there be light upon', @world.name + '!"'
|
||||||
unless Worker? # profiling world simulation is easier on main thread, or we are IE9
|
unless Worker? # profiling world simulation is easier on main thread, or we are IE9
|
||||||
setTimeout @simulateWorld, 1
|
setTimeout @simulateWorld, 1
|
||||||
|
@ -101,20 +107,37 @@ module.exports = class God
|
||||||
#console.log "going to run world with code", @getUserCodeMap()
|
#console.log "going to run world with code", @getUserCodeMap()
|
||||||
angel.worker.postMessage {func: 'runWorld', args: {
|
angel.worker.postMessage {func: 'runWorld', args: {
|
||||||
worldName: @level.name
|
worldName: @level.name
|
||||||
userCodeMap: @getUserCodeMap()
|
userCodeMap: @getUserCodeMap(spells)
|
||||||
level: @level
|
level: @level
|
||||||
firstWorld: @firstWorld
|
firstWorld: @firstWorld
|
||||||
goals: @goalManager?.getGoals()
|
goals: @goalManager?.getGoals()
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
#Coffeescript needs getters and setters.
|
||||||
|
setGoalManager: (@goalManager) =>
|
||||||
|
|
||||||
|
setWorldClassMap: (@worldClassMap) =>
|
||||||
|
|
||||||
beholdWorld: (angel, serialized, goalStates) ->
|
beholdWorld: (angel, serialized, goalStates) ->
|
||||||
|
unless serialized
|
||||||
|
# We're only interested in goalStates.
|
||||||
|
@latestGoalStates = goalStates
|
||||||
|
Backbone.Mediator.publish('god:goals-calculated', goalStates: goalStates, team: me.team)
|
||||||
|
unless _.find @angels, 'busy'
|
||||||
|
@spells = null # Don't hold onto old spells; memory leaks
|
||||||
|
return
|
||||||
|
|
||||||
|
console.log "Beholding world."
|
||||||
worldCreation = angel.started
|
worldCreation = angel.started
|
||||||
angel.free()
|
angel.free()
|
||||||
return if @latestWorldCreation? and worldCreation < @latestWorldCreation
|
return if @latestWorldCreation? and worldCreation < @latestWorldCreation
|
||||||
@latestWorldCreation = worldCreation
|
@latestWorldCreation = worldCreation
|
||||||
@latestGoalStates = goalStates
|
@latestGoalStates = goalStates
|
||||||
|
|
||||||
|
console.warn "Goal states: " + JSON.stringify(goalStates)
|
||||||
|
|
||||||
window.BOX2D_ENABLED = false # Flip this off so that if we have box2d in the namespace, the Collides Components still don't try to create bodies for deserialized Thangs upon attachment
|
window.BOX2D_ENABLED = false # Flip this off so that if we have box2d in the namespace, the Collides Components still don't try to create bodies for deserialized Thangs upon attachment
|
||||||
World.deserialize serialized, @worldClassMap, @lastSerializedWorldFrames, worldCreation, @finishBeholdingWorld
|
World.deserialize serialized, @worldClassMap, @lastSerializedWorldFrames, @finishBeholdingWorld
|
||||||
window.BOX2D_ENABLED = true
|
window.BOX2D_ENABLED = true
|
||||||
@lastSerializedWorldFrames = serialized.frames
|
@lastSerializedWorldFrames = serialized.frames
|
||||||
|
|
||||||
|
@ -171,7 +194,7 @@ module.exports = class God
|
||||||
@latestGoalStates = @testGM?.getGoalStates()
|
@latestGoalStates = @testGM?.getGoalStates()
|
||||||
serialized = @testWorld.serialize().serializedWorld
|
serialized = @testWorld.serialize().serializedWorld
|
||||||
window.BOX2D_ENABLED = false
|
window.BOX2D_ENABLED = false
|
||||||
World.deserialize serialized, @worldClassMap, @lastSerializedWorldFrames, @t0, @finishBeholdingWorld
|
World.deserialize serialized, @worldClassMap, @lastSerializedWorldFrames, @finishBeholdingWorld
|
||||||
window.BOX2D_ENABLED = true
|
window.BOX2D_ENABLED = true
|
||||||
@lastSerializedWorldFrames = serialized.frames
|
@lastSerializedWorldFrames = serialized.frames
|
||||||
|
|
||||||
|
@ -271,6 +294,7 @@ class Angel
|
||||||
switch event.data.type
|
switch event.data.type
|
||||||
when 'worker-initialized'
|
when 'worker-initialized'
|
||||||
console.log "Worker", @id, "initialized after", ((new Date()) - @worker.creationTime), "ms (we had been waiting for it)"
|
console.log "Worker", @id, "initialized after", ((new Date()) - @worker.creationTime), "ms (we had been waiting for it)"
|
||||||
|
@worker.initialized = true
|
||||||
when 'new-world'
|
when 'new-world'
|
||||||
@god.beholdWorld @, event.data.serialized, event.data.goalStates
|
@god.beholdWorld @, event.data.serialized, event.data.goalStates
|
||||||
when 'world-load-progress-changed'
|
when 'world-load-progress-changed'
|
||||||
|
|
|
@ -155,6 +155,7 @@ module.exports = class LevelLoader extends CocoClass
|
||||||
# Building sprite sheets
|
# Building sprite sheets
|
||||||
|
|
||||||
buildSpriteSheetsForThangType: (thangType) ->
|
buildSpriteSheetsForThangType: (thangType) ->
|
||||||
|
return if @headless
|
||||||
@grabThangTypeTeams() unless @thangTypeTeams
|
@grabThangTypeTeams() unless @thangTypeTeams
|
||||||
for team in @thangTypeTeams[thangType.get('original')] ? [null]
|
for team in @thangTypeTeams[thangType.get('original')] ? [null]
|
||||||
spriteOptions = {resolutionFactor: 4, async: false}
|
spriteOptions = {resolutionFactor: 4, async: false}
|
||||||
|
|
|
@ -2,15 +2,18 @@ SuperModel = require 'models/SuperModel'
|
||||||
CocoClass = require 'lib/CocoClass'
|
CocoClass = require 'lib/CocoClass'
|
||||||
LevelLoader = require 'lib/LevelLoader'
|
LevelLoader = require 'lib/LevelLoader'
|
||||||
GoalManager = require 'lib/world/GoalManager'
|
GoalManager = require 'lib/world/GoalManager'
|
||||||
God = require 'lib/God'
|
God = require 'lib/Buddha'
|
||||||
|
|
||||||
module.exports = class Simulator extends CocoClass
|
module.exports = class Simulator extends CocoClass
|
||||||
|
|
||||||
constructor: ->
|
constructor: (@options) ->
|
||||||
|
@options ?= {}
|
||||||
_.extend @, Backbone.Events
|
_.extend @, Backbone.Events
|
||||||
@trigger 'statusUpdate', 'Starting simulation!'
|
@trigger 'statusUpdate', 'Starting simulation!'
|
||||||
@retryDelayInSeconds = 10
|
@retryDelayInSeconds = 10
|
||||||
@taskURL = '/queue/scoring'
|
@taskURL = '/queue/scoring'
|
||||||
|
@simulatedByYou = 0
|
||||||
|
@god = new God maxWorkerPoolSize: 1, maxAngels: 1, workerCode: @options.workerCode # Start loading worker.
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
@off()
|
@off()
|
||||||
|
@ -19,6 +22,17 @@ module.exports = class Simulator extends CocoClass
|
||||||
|
|
||||||
fetchAndSimulateTask: =>
|
fetchAndSimulateTask: =>
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
|
|
||||||
|
if @options.headlessClient
|
||||||
|
if @dumpThisTime # The first heapdump would be useless to find leaks.
|
||||||
|
console.log "Writing snapshot."
|
||||||
|
@options.heapdump.writeSnapshot()
|
||||||
|
@dumpThisTime = true if @options.heapdump
|
||||||
|
|
||||||
|
if @options.testing
|
||||||
|
_.delay @setupSimulationAndLoadLevel, 0, @options.testFile, "Testing...", status: 400
|
||||||
|
return
|
||||||
|
|
||||||
@trigger 'statusUpdate', 'Fetching simulation data!'
|
@trigger 'statusUpdate', 'Fetching simulation data!'
|
||||||
$.ajax
|
$.ajax
|
||||||
url: @taskURL
|
url: @taskURL
|
||||||
|
@ -32,7 +46,9 @@ module.exports = class Simulator extends CocoClass
|
||||||
@simulateAnotherTaskAfterDelay()
|
@simulateAnotherTaskAfterDelay()
|
||||||
|
|
||||||
handleNoGamesResponse: ->
|
handleNoGamesResponse: ->
|
||||||
@trigger 'statusUpdate', 'There were no games to simulate--all simulations are done or in process. Retrying in 10 seconds.'
|
info = 'There were no games to simulate--all simulations are done or in process. Retrying in 10 seconds.'
|
||||||
|
console.log info
|
||||||
|
@trigger 'statusUpdate', info
|
||||||
@simulateAnotherTaskAfterDelay()
|
@simulateAnotherTaskAfterDelay()
|
||||||
|
|
||||||
simulateAnotherTaskAfterDelay: =>
|
simulateAnotherTaskAfterDelay: =>
|
||||||
|
@ -53,7 +69,6 @@ module.exports = class Simulator extends CocoClass
|
||||||
return
|
return
|
||||||
|
|
||||||
@supermodel ?= new SuperModel()
|
@supermodel ?= new SuperModel()
|
||||||
@god = new God maxWorkerPoolSize: 1, maxAngels: 1 # Start loading worker.
|
|
||||||
|
|
||||||
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: levelID, sessionID: @task.getFirstSessionID(), headless: true
|
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: levelID, sessionID: @task.getFirstSessionID(), headless: true
|
||||||
if @supermodel.finished()
|
if @supermodel.finished()
|
||||||
|
@ -63,7 +78,9 @@ module.exports = class Simulator extends CocoClass
|
||||||
|
|
||||||
simulateGame: ->
|
simulateGame: ->
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
@trigger 'statusUpdate', 'All resources loaded, simulating!', @task.getSessions()
|
info = 'All resources loaded, simulating!'
|
||||||
|
console.log info
|
||||||
|
@trigger 'statusUpdate', info, @task.getSessions()
|
||||||
@assignWorldAndLevelFromLevelLoaderAndDestroyIt()
|
@assignWorldAndLevelFromLevelLoaderAndDestroyIt()
|
||||||
@setupGod()
|
@setupGod()
|
||||||
|
|
||||||
|
@ -74,6 +91,7 @@ module.exports = class Simulator extends CocoClass
|
||||||
@simulateAnotherTaskAfterDelay()
|
@simulateAnotherTaskAfterDelay()
|
||||||
|
|
||||||
assignWorldAndLevelFromLevelLoaderAndDestroyIt: ->
|
assignWorldAndLevelFromLevelLoaderAndDestroyIt: ->
|
||||||
|
console.log "Assigning world and level"
|
||||||
@world = @levelLoader.world
|
@world = @levelLoader.world
|
||||||
@level = @levelLoader.level
|
@level = @levelLoader.level
|
||||||
@levelLoader.destroy()
|
@levelLoader.destroy()
|
||||||
|
@ -81,18 +99,45 @@ module.exports = class Simulator extends CocoClass
|
||||||
|
|
||||||
setupGod: ->
|
setupGod: ->
|
||||||
@god.level = @level.serialize @supermodel
|
@god.level = @level.serialize @supermodel
|
||||||
@god.worldClassMap = @world.classMap
|
@god.setWorldClassMap @world.classMap
|
||||||
@setupGoalManager()
|
@setupGoalManager()
|
||||||
@setupGodSpells()
|
@setupGodSpells()
|
||||||
|
|
||||||
|
|
||||||
setupGoalManager: ->
|
setupGoalManager: ->
|
||||||
@god.goalManager = new GoalManager @world, @level.get 'goals'
|
@god.setGoalManager new GoalManager(@world, @level.get 'goals')
|
||||||
|
|
||||||
|
|
||||||
commenceSimulationAndSetupCallback: ->
|
commenceSimulationAndSetupCallback: ->
|
||||||
@god.createWorld()
|
@god.createWorld @generateSpellsObject()
|
||||||
Backbone.Mediator.subscribeOnce 'god:infinite-loop', @onInfiniteLoop, @
|
Backbone.Mediator.subscribeOnce 'god:infinite-loop', @onInfiniteLoop, @
|
||||||
Backbone.Mediator.subscribeOnce 'god:new-world-created', @processResults, @
|
Backbone.Mediator.subscribeOnce 'god:new-world-created', @processResults, @
|
||||||
|
|
||||||
|
#Search for leaks, headless-client only.
|
||||||
|
if @options.headlessClient and @options.leakTest and not @memwatch?
|
||||||
|
leakcount = 0
|
||||||
|
maxleakcount = 0
|
||||||
|
console.log "Setting leak callbacks."
|
||||||
|
@memwatch = require 'memwatch'
|
||||||
|
|
||||||
|
@memwatch.on 'leak', (info) =>
|
||||||
|
console.warn "LEAK!!\n" + JSON.stringify(info)
|
||||||
|
|
||||||
|
unless @hd?
|
||||||
|
if (leakcount++ is maxleakcount)
|
||||||
|
@hd = new @memwatch.HeapDiff()
|
||||||
|
|
||||||
|
@memwatch.on 'stats', (stats) =>
|
||||||
|
console.warn "stats callback: " + stats
|
||||||
|
diff = @hd.end()
|
||||||
|
console.warn "HeapDiff:\n" + JSON.stringify(diff)
|
||||||
|
|
||||||
|
if @options.exitOnLeak
|
||||||
|
console.warn "Exiting because of Leak."
|
||||||
|
process.exit()
|
||||||
|
@hd = new @memwatch.HeapDiff()
|
||||||
|
|
||||||
|
|
||||||
onInfiniteLoop: ->
|
onInfiniteLoop: ->
|
||||||
console.warn "Skipping infinitely looping game."
|
console.warn "Skipping infinitely looping game."
|
||||||
@trigger 'statusUpdate', "Infinite loop detected; grabbing a new game in #{@retryDelayInSeconds} seconds."
|
@trigger 'statusUpdate', "Infinite loop detected; grabbing a new game in #{@retryDelayInSeconds} seconds."
|
||||||
|
@ -106,6 +151,9 @@ module.exports = class Simulator extends CocoClass
|
||||||
@trigger 'statusUpdate', 'Simulation completed, sending results back to server!'
|
@trigger 'statusUpdate', 'Simulation completed, sending results back to server!'
|
||||||
console.log "Sending result back to server!"
|
console.log "Sending result back to server!"
|
||||||
|
|
||||||
|
if @options.headlessClient and @options.testing
|
||||||
|
return @fetchAndSimulateTask()
|
||||||
|
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "/queue/scoring"
|
url: "/queue/scoring"
|
||||||
data: results
|
data: results
|
||||||
|
@ -117,6 +165,9 @@ module.exports = class Simulator extends CocoClass
|
||||||
handleTaskResultsTransferSuccess: (result) =>
|
handleTaskResultsTransferSuccess: (result) =>
|
||||||
console.log "Task registration result: #{JSON.stringify result}"
|
console.log "Task registration result: #{JSON.stringify result}"
|
||||||
@trigger 'statusUpdate', 'Results were successfully sent back to server!'
|
@trigger 'statusUpdate', 'Results were successfully sent back to server!'
|
||||||
|
console.log "Simulated by you: " + @simulatedByYou
|
||||||
|
@simulatedByYou++
|
||||||
|
unless @options.headlessClient
|
||||||
simulatedBy = parseInt($('#simulated-by-you').text(), 10) + 1
|
simulatedBy = parseInt($('#simulated-by-you').text(), 10) + 1
|
||||||
$('#simulated-by-you').text(simulatedBy)
|
$('#simulated-by-you').text(simulatedBy)
|
||||||
|
|
||||||
|
@ -144,7 +195,6 @@ module.exports = class Simulator extends CocoClass
|
||||||
sessions: []
|
sessions: []
|
||||||
|
|
||||||
for session in @task.getSessions()
|
for session in @task.getSessions()
|
||||||
|
|
||||||
sessionResult =
|
sessionResult =
|
||||||
sessionID: session.sessionID
|
sessionID: session.sessionID
|
||||||
submitDate: session.submitDate
|
submitDate: session.submitDate
|
||||||
|
|
|
@ -168,10 +168,12 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
stop: ->
|
stop: ->
|
||||||
@imageObject?.stop?()
|
@imageObject?.stop?()
|
||||||
mark.stop() for name, mark of @marks
|
mark.stop() for name, mark of @marks
|
||||||
|
@stopped = true
|
||||||
|
|
||||||
play: ->
|
play: ->
|
||||||
@imageObject?.play?()
|
@imageObject?.play?()
|
||||||
mark.play() for name, mark of @marks
|
mark.play() for name, mark of @marks
|
||||||
|
@stopped = false
|
||||||
|
|
||||||
update: (frameChanged) ->
|
update: (frameChanged) ->
|
||||||
# Gets the sprite to reflect what the current state of the thangs and surface are
|
# Gets the sprite to reflect what the current state of the thangs and surface are
|
||||||
|
@ -222,7 +224,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
|
|
||||||
getBobOffset: ->
|
getBobOffset: ->
|
||||||
return 0 unless @thang.bobHeight
|
return 0 unless @thang.bobHeight
|
||||||
@thang.bobHeight * (1 + Math.sin(@age * Math.PI / @thang.bobTime))
|
return @lastBobOffset if @stopped
|
||||||
|
return @lastBobOffset = @thang.bobHeight * (1 + Math.sin(@age * Math.PI / @thang.bobTime))
|
||||||
|
|
||||||
getWorldPosition: ->
|
getWorldPosition: ->
|
||||||
p1 = if @possessed then @shadow.pos else @thang.pos
|
p1 = if @possessed then @shadow.pos else @thang.pos
|
||||||
|
@ -495,6 +498,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
|
|
||||||
updateEffectMarks: ->
|
updateEffectMarks: ->
|
||||||
return if _.isEqual @thang.effectNames, @previousEffectNames
|
return if _.isEqual @thang.effectNames, @previousEffectNames
|
||||||
|
return if @stopped
|
||||||
for effect in @thang.effectNames
|
for effect in @thang.effectNames
|
||||||
mark = @addMark effect, @options.floatingLayer, effect
|
mark = @addMark effect, @options.floatingLayer, effect
|
||||||
mark.statusEffect = true
|
mark.statusEffect = true
|
||||||
|
|
|
@ -221,12 +221,12 @@ module.exports = class SpriteBoss extends CocoClass
|
||||||
onCastSpells: -> @stop()
|
onCastSpells: -> @stop()
|
||||||
|
|
||||||
play: ->
|
play: ->
|
||||||
sprite.imageObject.play() for sprite in @spriteArray
|
sprite.play() for sprite in @spriteArray
|
||||||
@selectionMark?.play()
|
@selectionMark?.play()
|
||||||
@targetMark?.play()
|
@targetMark?.play()
|
||||||
|
|
||||||
stop: ->
|
stop: ->
|
||||||
sprite.imageObject.stop() for sprite in @spriteArray
|
sprite.stop() for sprite in @spriteArray
|
||||||
@selectionMark?.stop()
|
@selectionMark?.stop()
|
||||||
@targetMark?.stop()
|
@targetMark?.stop()
|
||||||
|
|
||||||
|
|
|
@ -204,7 +204,7 @@ module.exports = class GoalManager extends CocoClass
|
||||||
|
|
||||||
arrays = (prop for prop in whos when prop?.length)
|
arrays = (prop for prop in whos when prop?.length)
|
||||||
return unless arrays.length
|
return unless arrays.length
|
||||||
state[progressObjectName] = {}
|
state[progressObjectName] ?= {}
|
||||||
for array in arrays
|
for array in arrays
|
||||||
for thang in array
|
for thang in array
|
||||||
if @thangTeams[thang]?
|
if @thangTeams[thang]?
|
||||||
|
@ -235,7 +235,7 @@ module.exports = class GoalManager extends CocoClass
|
||||||
numNeeded = goal.howMany ? Math.max(1, _.size stateThangs)
|
numNeeded = goal.howMany ? Math.max(1, _.size stateThangs)
|
||||||
else
|
else
|
||||||
# saveThangs: by default we would want to save all the Thangs, which means that we would want none of them to be "done"
|
# saveThangs: by default we would want to save all the Thangs, which means that we would want none of them to be "done"
|
||||||
numNeeded = _.size(stateThangs) - Math.min((goal.howMany ? 1), _.size stateThangs) + 1
|
numNeeded = _.size(stateThangs) - Math.max((goal.howMany ? 1), _.size stateThangs) + 1
|
||||||
numDone = _.filter(stateThangs).length
|
numDone = _.filter(stateThangs).length
|
||||||
console.log "needed", numNeeded, "done", numDone, "of total", _.size(stateThangs), "with how many", goal.howMany, "and stateThangs", stateThangs
|
console.log "needed", numNeeded, "done", numDone, "of total", _.size(stateThangs), "with how many", goal.howMany, "and stateThangs", stateThangs
|
||||||
return unless numDone >= numNeeded
|
return unless numDone >= numNeeded
|
||||||
|
|
|
@ -72,7 +72,7 @@ module.exports = class World
|
||||||
(@runtimeErrors ?= []).push error
|
(@runtimeErrors ?= []).push error
|
||||||
(@unhandledRuntimeErrors ?= []).push error
|
(@unhandledRuntimeErrors ?= []).push error
|
||||||
|
|
||||||
loadFrames: (loadedCallback, errorCallback, loadProgressCallback) ->
|
loadFrames: (loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading) ->
|
||||||
return if @aborted
|
return if @aborted
|
||||||
unless @thangs.length
|
unless @thangs.length
|
||||||
console.log "Warning: loadFrames called on empty World (no thangs)."
|
console.log "Warning: loadFrames called on empty World (no thangs)."
|
||||||
|
@ -96,7 +96,11 @@ module.exports = class World
|
||||||
if t2 - @t0 > 1000
|
if t2 - @t0 > 1000
|
||||||
console.log(' Loaded', i, 'of', @totalFrames, "(+" + (t2 - @t0).toFixed(0) + "ms)")
|
console.log(' Loaded', i, 'of', @totalFrames, "(+" + (t2 - @t0).toFixed(0) + "ms)")
|
||||||
@t0 = t2
|
@t0 = t2
|
||||||
setTimeout((=> @loadFrames(loadedCallback, errorCallback, loadProgressCallback)), 0)
|
continueFn = => @loadFrames(loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading)
|
||||||
|
if skipDeferredLoading
|
||||||
|
continueFn()
|
||||||
|
else
|
||||||
|
setTimeout(continueFn, 0)
|
||||||
return
|
return
|
||||||
@ended = true
|
@ended = true
|
||||||
system.finish @thangs for system in @systems
|
system.finish @thangs for system in @systems
|
||||||
|
@ -336,7 +340,7 @@ module.exports = class World
|
||||||
console.log "Whoa, serializing a lot of WorldScriptNotes here:", o.scriptNotes.length
|
console.log "Whoa, serializing a lot of WorldScriptNotes here:", o.scriptNotes.length
|
||||||
{serializedWorld: o, transferableObjects: [o.storageBuffer]}
|
{serializedWorld: o, transferableObjects: [o.storageBuffer]}
|
||||||
|
|
||||||
@deserialize: (o, classMap, oldSerializedWorldFrames, worldCreationTime, finishedWorldCallback) ->
|
@deserialize: (o, classMap, oldSerializedWorldFrames, finishedWorldCallback) ->
|
||||||
# Code hotspot; optimize it
|
# Code hotspot; optimize it
|
||||||
#console.log "Deserializing", o, "length", JSON.stringify(o).length
|
#console.log "Deserializing", o, "length", JSON.stringify(o).length
|
||||||
#console.log JSON.stringify(o)
|
#console.log JSON.stringify(o)
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "български език", englishDescri
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "български език", englishDescri
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
|
||||||
multiplayer_hint_label: "Tip:"
|
multiplayer_hint_label: "Tip:"
|
||||||
multiplayer_hint: " Klikněte na odkaz pro jeho výběr, poté stiskněte ⌘-C nebo Ctrl-C pro kopírování odkazu."
|
multiplayer_hint: " Klikněte na odkaz pro jeho výběr, poté stiskněte ⌘-C nebo Ctrl-C pro kopírování odkazu."
|
||||||
multiplayer_coming_soon: "Další vlastnosti multiplayeru jsou na cestě!"
|
multiplayer_coming_soon: "Další vlastnosti multiplayeru jsou na cestě!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Průvodce"
|
guide_title: "Průvodce"
|
||||||
tome_minion_spells: "Vaše oblíbená kouzla"
|
tome_minion_spells: "Vaše oblíbená kouzla"
|
||||||
tome_read_only_spells: "Kouzla jen pro čtení"
|
tome_read_only_spells: "Kouzla jen pro čtení"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
||||||
multiplayer_hint_label: "Tip:"
|
multiplayer_hint_label: "Tip:"
|
||||||
multiplayer_hint: " Klik på linket for markere alt; tryk derefter ⌘-C eller Ctrl-C tfr at kopiere linket."
|
multiplayer_hint: " Klik på linket for markere alt; tryk derefter ⌘-C eller Ctrl-C tfr at kopiere linket."
|
||||||
multiplayer_coming_soon: "Yderligere flerspillermuligheder er på vej!"
|
multiplayer_coming_soon: "Yderligere flerspillermuligheder er på vej!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Instruktioner"
|
guide_title: "Instruktioner"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
||||||
multiplayer_hint_label: "Hinweis:"
|
multiplayer_hint_label: "Hinweis:"
|
||||||
multiplayer_hint: " Klick den Link, um alles auszuwählen, dann drück ⌘-C oder Strg-C um den Link zu kopieren."
|
multiplayer_hint: " Klick den Link, um alles auszuwählen, dann drück ⌘-C oder Strg-C um den Link zu kopieren."
|
||||||
multiplayer_coming_soon: "Mehr Multiplayerfeatures werden kommen!"
|
multiplayer_coming_soon: "Mehr Multiplayerfeatures werden kommen!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Anleitung"
|
guide_title: "Anleitung"
|
||||||
tome_minion_spells: "Die Zaubersprüche Deiner Knechte"
|
tome_minion_spells: "Die Zaubersprüche Deiner Knechte"
|
||||||
tome_read_only_spells: "Nur-lesen Zauberspüche"
|
tome_read_only_spells: "Nur-lesen Zauberspüche"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
|
||||||
multiplayer_hint_label: "Hinweis:"
|
multiplayer_hint_label: "Hinweis:"
|
||||||
multiplayer_hint: " Klick den Link, um alles auszuwählen, dann drück ⌘-C oder Strg-C um den Link zu kopieren."
|
multiplayer_hint: " Klick den Link, um alles auszuwählen, dann drück ⌘-C oder Strg-C um den Link zu kopieren."
|
||||||
multiplayer_coming_soon: "Mehr Multiplayerfeatures werden kommen!"
|
multiplayer_coming_soon: "Mehr Multiplayerfeatures werden kommen!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Anleitung"
|
guide_title: "Anleitung"
|
||||||
tome_minion_spells: "Die Zaubersprüche Deiner Knechte"
|
tome_minion_spells: "Die Zaubersprüche Deiner Knechte"
|
||||||
tome_read_only_spells: "Nur-lesen Zauberspüche"
|
tome_read_only_spells: "Nur-lesen Zauberspüche"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
|
||||||
multiplayer_hint_label: "Συμβουλή:"
|
multiplayer_hint_label: "Συμβουλή:"
|
||||||
multiplayer_hint: " Κάντε κλικ στο σύνδεσμο για να επιλέξετε όλα, στη συνέχεια, πατήστε την Apple-C ή Ctrl-C για να αντιγράψετε το σύνδεσμο."
|
multiplayer_hint: " Κάντε κλικ στο σύνδεσμο για να επιλέξετε όλα, στη συνέχεια, πατήστε την Apple-C ή Ctrl-C για να αντιγράψετε το σύνδεσμο."
|
||||||
multiplayer_coming_soon: "Περισσότερα multiplayer χαρακτιριστηκα προσεχως!"
|
multiplayer_coming_soon: "Περισσότερα multiplayer χαρακτιριστηκα προσεχως!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Οδηγός"
|
guide_title: "Οδηγός"
|
||||||
tome_minion_spells: "Ξόρκια για τα τσιράκια σας"
|
tome_minion_spells: "Ξόρκια για τα τσιράκια σας"
|
||||||
tome_read_only_spells: "Ξορκια μονο για αναγνωση"
|
tome_read_only_spells: "Ξορκια μονο για αναγνωση"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@
|
||||||
multiplayer_hint_label: "Hint:"
|
multiplayer_hint_label: "Hint:"
|
||||||
multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
multiplayer_coming_soon: "More multiplayer features to come!"
|
multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guide"
|
guide_title: "Guide"
|
||||||
tome_minion_spells: "Your Minions' Spells"
|
tome_minion_spells: "Your Minions' Spells"
|
||||||
tome_read_only_spells: "Read-Only Spells"
|
tome_read_only_spells: "Read-Only Spells"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
|
||||||
multiplayer_hint_label: "Consejo:"
|
multiplayer_hint_label: "Consejo:"
|
||||||
multiplayer_hint: " Cliquea el enlace para seleccionar todo, luego presiona ⌘-C o Ctrl-C para copiar el enlace."
|
multiplayer_hint: " Cliquea el enlace para seleccionar todo, luego presiona ⌘-C o Ctrl-C para copiar el enlace."
|
||||||
multiplayer_coming_soon: "¡Más características de multijugador por venir!"
|
multiplayer_coming_soon: "¡Más características de multijugador por venir!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guía"
|
guide_title: "Guía"
|
||||||
tome_minion_spells: "Hechizos de tus Secuaces"
|
tome_minion_spells: "Hechizos de tus Secuaces"
|
||||||
tome_read_only_spells: "Hechizos de Sólo Lectura"
|
tome_read_only_spells: "Hechizos de Sólo Lectura"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
multiplayer_hint_label: "Pista:"
|
multiplayer_hint_label: "Pista:"
|
||||||
multiplayer_hint: " Haz un click en el link para que se seleccione, después utiliza Ctrl-C o ⌘-C para copiar el link."
|
multiplayer_hint: " Haz un click en el link para que se seleccione, después utiliza Ctrl-C o ⌘-C para copiar el link."
|
||||||
multiplayer_coming_soon: "¡Más opciones de Multijugador están por venir!"
|
multiplayer_coming_soon: "¡Más opciones de Multijugador están por venir!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guía"
|
guide_title: "Guía"
|
||||||
tome_minion_spells: "Los hechizos de tus súbditos"
|
tome_minion_spells: "Los hechizos de tus súbditos"
|
||||||
tome_read_only_spells: "Hechizos de solo lectura"
|
tome_read_only_spells: "Hechizos de solo lectura"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
|
||||||
multiplayer_hint_label: "Consejo:"
|
multiplayer_hint_label: "Consejo:"
|
||||||
multiplayer_hint: " Cliquea el enlace para seleccionar todo, luego presiona ⌘-C o Ctrl-C para copiar el enlace."
|
multiplayer_hint: " Cliquea el enlace para seleccionar todo, luego presiona ⌘-C o Ctrl-C para copiar el enlace."
|
||||||
multiplayer_coming_soon: "¡Más características de multijugador por venir!"
|
multiplayer_coming_soon: "¡Más características de multijugador por venir!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guía"
|
guide_title: "Guía"
|
||||||
tome_minion_spells: "Hechizos de tus Secuaces"
|
tome_minion_spells: "Hechizos de tus Secuaces"
|
||||||
tome_read_only_spells: "Hechizos de Sólo Lectura"
|
tome_read_only_spells: "Hechizos de Sólo Lectura"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
|
||||||
multiplayer_hint_label: "Astuce:"
|
multiplayer_hint_label: "Astuce:"
|
||||||
multiplayer_hint: " Cliquez sur le lien pour tout sélectionner, puis appuyer sur Pomme-C ou Ctrl-C pour copier le lien."
|
multiplayer_hint: " Cliquez sur le lien pour tout sélectionner, puis appuyer sur Pomme-C ou Ctrl-C pour copier le lien."
|
||||||
multiplayer_coming_soon: "Plus de fonctionnalités multijoueurs sont à venir"
|
multiplayer_coming_soon: "Plus de fonctionnalités multijoueurs sont à venir"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guide"
|
guide_title: "Guide"
|
||||||
tome_minion_spells: "Les sorts de vos soldats"
|
tome_minion_spells: "Les sorts de vos soldats"
|
||||||
tome_read_only_spells: "Sorts en lecture-seule"
|
tome_read_only_spells: "Sorts en lecture-seule"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
|
||||||
multiplayer_hint_label: "Tipp:"
|
multiplayer_hint_label: "Tipp:"
|
||||||
multiplayer_hint: " Kattints a linkre, és Ctrl+C-vel (vagy ⌘+C-vel) másold a vágólapra!"
|
multiplayer_hint: " Kattints a linkre, és Ctrl+C-vel (vagy ⌘+C-vel) másold a vágólapra!"
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Útmutató"
|
guide_title: "Útmutató"
|
||||||
tome_minion_spells: "Egységeid varázslatai"
|
tome_minion_spells: "Egységeid varázslatai"
|
||||||
tome_read_only_spells: "Csak olvasható varázslatok"
|
tome_read_only_spells: "Csak olvasható varázslatok"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
multiplayer_hint_label: "Suggerimento:"
|
multiplayer_hint_label: "Suggerimento:"
|
||||||
multiplayer_hint: " Clicca il link per selezionare tutto, quindi premi CMD-C o Ctrl-C per copiare il link."
|
multiplayer_hint: " Clicca il link per selezionare tutto, quindi premi CMD-C o Ctrl-C per copiare il link."
|
||||||
multiplayer_coming_soon: "Ulteriori aggiunte per il multigiocatore in arrivo!"
|
multiplayer_coming_soon: "Ulteriori aggiunte per il multigiocatore in arrivo!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guida"
|
guide_title: "Guida"
|
||||||
tome_minion_spells: "Incantesimi dei tuoi seguaci"
|
tome_minion_spells: "Incantesimi dei tuoi seguaci"
|
||||||
tome_read_only_spells: "Incantesimi in sola lettura"
|
tome_read_only_spells: "Incantesimi in sola lettura"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
||||||
multiplayer_hint_label: "ヒント:"
|
multiplayer_hint_label: "ヒント:"
|
||||||
multiplayer_hint: " リンクを選択後、 ⌘-C(MacOS) or Ctrl-C(Windows) でリンクをコピーできます。"
|
multiplayer_hint: " リンクを選択後、 ⌘-C(MacOS) or Ctrl-C(Windows) でリンクをコピーできます。"
|
||||||
multiplayer_coming_soon: "今後より多くのマルチプレイ機能が追加されます。"
|
multiplayer_coming_soon: "今後より多くのマルチプレイ機能が追加されます。"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "ガイド"
|
guide_title: "ガイド"
|
||||||
tome_minion_spells: "操作できるキャラクターの呪文"
|
tome_minion_spells: "操作できるキャラクターの呪文"
|
||||||
tome_read_only_spells: "読込専用の呪文"
|
tome_read_only_spells: "読込専用の呪文"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
|
||||||
multiplayer_hint_label: "힌트:"
|
multiplayer_hint_label: "힌트:"
|
||||||
multiplayer_hint: " 모두 선택하려면 링크를 클릭하세요, 그리고 ⌘-C 또는 Ctrl-C 를 눌러서 링크를 복사하세요."
|
multiplayer_hint: " 모두 선택하려면 링크를 클릭하세요, 그리고 ⌘-C 또는 Ctrl-C 를 눌러서 링크를 복사하세요."
|
||||||
multiplayer_coming_soon: "곧 좀 더 다양한 멀티플레이어 모드가 업데이트 됩니다!"
|
multiplayer_coming_soon: "곧 좀 더 다양한 멀티플레이어 모드가 업데이트 됩니다!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "가이드"
|
guide_title: "가이드"
|
||||||
tome_minion_spells: "당신 미니언의' 마법"
|
tome_minion_spells: "당신 미니언의' 마법"
|
||||||
tome_read_only_spells: "읽기 전용 마법"
|
tome_read_only_spells: "읽기 전용 마법"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
|
||||||
multiplayer_hint_label: "Hint:"
|
multiplayer_hint_label: "Hint:"
|
||||||
multiplayer_hint: " Klikk lenken for å velge alle, så trykker du Apple-C eller Ctrl-C for å kopiere lenken."
|
multiplayer_hint: " Klikk lenken for å velge alle, så trykker du Apple-C eller Ctrl-C for å kopiere lenken."
|
||||||
multiplayer_coming_soon: "Det kommer flere flerspillsmuligheter!"
|
multiplayer_coming_soon: "Det kommer flere flerspillsmuligheter!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guide"
|
guide_title: "Guide"
|
||||||
tome_minion_spells: "Din Minions' Trylleformularer"
|
tome_minion_spells: "Din Minions' Trylleformularer"
|
||||||
tome_read_only_spells: "Kun-Lesbare Trylleformularer"
|
tome_read_only_spells: "Kun-Lesbare Trylleformularer"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
|
||||||
multiplayer_hint_label: "Hint:"
|
multiplayer_hint_label: "Hint:"
|
||||||
multiplayer_hint: " Klik de link om alles te selecteren, druk dan op Apple-C of Ctrl-C om de link te kopiëren."
|
multiplayer_hint: " Klik de link om alles te selecteren, druk dan op Apple-C of Ctrl-C om de link te kopiëren."
|
||||||
multiplayer_coming_soon: "Binnenkort komen er meer Multiplayermogelijkheden!"
|
multiplayer_coming_soon: "Binnenkort komen er meer Multiplayermogelijkheden!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Handleiding"
|
guide_title: "Handleiding"
|
||||||
tome_minion_spells: "Jouw Minions' Spreuken"
|
tome_minion_spells: "Jouw Minions' Spreuken"
|
||||||
tome_read_only_spells: "Read-Only Spreuken"
|
tome_read_only_spells: "Read-Only Spreuken"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
|
||||||
multiplayer_hint_label: "Hint:"
|
multiplayer_hint_label: "Hint:"
|
||||||
multiplayer_hint: " Klik de link om alles te selecteren, druk dan op Apple-C of Ctrl-C om de link te kopiëren."
|
multiplayer_hint: " Klik de link om alles te selecteren, druk dan op Apple-C of Ctrl-C om de link te kopiëren."
|
||||||
multiplayer_coming_soon: "Binnenkort komen er meer Multiplayermogelijkheden!"
|
multiplayer_coming_soon: "Binnenkort komen er meer Multiplayermogelijkheden!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Handleiding"
|
guide_title: "Handleiding"
|
||||||
tome_minion_spells: "Jouw Minions' Spreuken"
|
tome_minion_spells: "Jouw Minions' Spreuken"
|
||||||
tome_read_only_spells: "Read-Only Spreuken"
|
tome_read_only_spells: "Read-Only Spreuken"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
|
||||||
multiplayer_hint_label: "Hint:"
|
multiplayer_hint_label: "Hint:"
|
||||||
multiplayer_hint: " Klik de link om alles te selecteren, druk dan op Apple-C of Ctrl-C om de link te kopiëren."
|
multiplayer_hint: " Klik de link om alles te selecteren, druk dan op Apple-C of Ctrl-C om de link te kopiëren."
|
||||||
multiplayer_coming_soon: "Binnenkort komen er meer Multiplayermogelijkheden!"
|
multiplayer_coming_soon: "Binnenkort komen er meer Multiplayermogelijkheden!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Handleiding"
|
guide_title: "Handleiding"
|
||||||
tome_minion_spells: "Jouw Minions' Spreuken"
|
tome_minion_spells: "Jouw Minions' Spreuken"
|
||||||
tome_read_only_spells: "Read-Only Spreuken"
|
tome_read_only_spells: "Read-Only Spreuken"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
|
||||||
user_names: "Gebruikersnamen"
|
user_names: "Gebruikersnamen"
|
||||||
files: "Bestanden"
|
files: "Bestanden"
|
||||||
top_simulators: "Top Simulatoren"
|
top_simulators: "Top Simulatoren"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
|
||||||
multiplayer_hint_label: "Hint:"
|
multiplayer_hint_label: "Hint:"
|
||||||
multiplayer_hint: " Klikk lenken for å velge alle, så trykker du Apple-C eller Ctrl-C for å kopiere lenken."
|
multiplayer_hint: " Klikk lenken for å velge alle, så trykker du Apple-C eller Ctrl-C for å kopiere lenken."
|
||||||
multiplayer_coming_soon: "Det kommer flere flerspillsmuligheter!"
|
multiplayer_coming_soon: "Det kommer flere flerspillsmuligheter!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guide"
|
guide_title: "Guide"
|
||||||
tome_minion_spells: "Din Minions' Trylleformularer"
|
tome_minion_spells: "Din Minions' Trylleformularer"
|
||||||
tome_read_only_spells: "Kun-Lesbare Trylleformularer"
|
tome_read_only_spells: "Kun-Lesbare Trylleformularer"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
|
||||||
multiplayer_hint_label: "Podpowiedź:"
|
multiplayer_hint_label: "Podpowiedź:"
|
||||||
multiplayer_hint: "Kliknij link by zaznaczyć wszystko, potem wciśnij Cmd-C lub Ctrl-C by skopiować ten link."
|
multiplayer_hint: "Kliknij link by zaznaczyć wszystko, potem wciśnij Cmd-C lub Ctrl-C by skopiować ten link."
|
||||||
multiplayer_coming_soon: "Wkrótce więcej opcji multiplayer"
|
multiplayer_coming_soon: "Wkrótce więcej opcji multiplayer"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Przewodnik"
|
guide_title: "Przewodnik"
|
||||||
tome_minion_spells: "Czary twojego podopiecznego"
|
tome_minion_spells: "Czary twojego podopiecznego"
|
||||||
tome_read_only_spells: "Czary tylko do odczytu"
|
tome_read_only_spells: "Czary tylko do odczytu"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
|
||||||
multiplayer_hint_label: "Dica:"
|
multiplayer_hint_label: "Dica:"
|
||||||
multiplayer_hint: " Clique no link para selecionar tudo, então dê Ctrl+C ou ⌘+C para copiar o link. "
|
multiplayer_hint: " Clique no link para selecionar tudo, então dê Ctrl+C ou ⌘+C para copiar o link. "
|
||||||
multiplayer_coming_soon: "Mais novidades no multiplayer estão chegando!"
|
multiplayer_coming_soon: "Mais novidades no multiplayer estão chegando!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guia"
|
guide_title: "Guia"
|
||||||
tome_minion_spells: "Magias dos seus subordinados"
|
tome_minion_spells: "Magias dos seus subordinados"
|
||||||
tome_read_only_spells: "Magias não editáveis"
|
tome_read_only_spells: "Magias não editáveis"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
|
||||||
multiplayer_hint_label: "Dica:"
|
multiplayer_hint_label: "Dica:"
|
||||||
multiplayer_hint: " Carrega no link para seleccionar tudp, depois pressiona ⌘-C ou Ctrl-C para copiar o link."
|
multiplayer_hint: " Carrega no link para seleccionar tudp, depois pressiona ⌘-C ou Ctrl-C para copiar o link."
|
||||||
multiplayer_coming_soon: "Mais funcionalidades de multiplayer brevemente!"
|
multiplayer_coming_soon: "Mais funcionalidades de multiplayer brevemente!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guia"
|
guide_title: "Guia"
|
||||||
tome_minion_spells: "Feitiços dos teus Minions"
|
tome_minion_spells: "Feitiços dos teus Minions"
|
||||||
tome_read_only_spells: "Feitiços apenas de leitura"
|
tome_read_only_spells: "Feitiços apenas de leitura"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
|
||||||
multiplayer_hint_label: "Dica:"
|
multiplayer_hint_label: "Dica:"
|
||||||
multiplayer_hint: " Clique no link para selecionar tudo, então dê Ctrl+C ou ⌘+C para copiar o link. "
|
multiplayer_hint: " Clique no link para selecionar tudo, então dê Ctrl+C ou ⌘+C para copiar o link. "
|
||||||
multiplayer_coming_soon: "Mais novidades no multiplayer estão chegando!"
|
multiplayer_coming_soon: "Mais novidades no multiplayer estão chegando!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guia"
|
guide_title: "Guia"
|
||||||
tome_minion_spells: "Magias dos seus subordinados"
|
tome_minion_spells: "Magias dos seus subordinados"
|
||||||
tome_read_only_spells: "Magias não editáveis"
|
tome_read_only_spells: "Magias não editáveis"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
|
||||||
multiplayer_hint_label: "Hint:"
|
multiplayer_hint_label: "Hint:"
|
||||||
multiplayer_hint: " Apasă pe link pentru a selecta tot, apoi apasă ⌘-C sau Ctrl-C pentru a copia link-ul."
|
multiplayer_hint: " Apasă pe link pentru a selecta tot, apoi apasă ⌘-C sau Ctrl-C pentru a copia link-ul."
|
||||||
multiplayer_coming_soon: "Mai multe feature-uri multiplayer în curând!"
|
multiplayer_coming_soon: "Mai multe feature-uri multiplayer în curând!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Ghid"
|
guide_title: "Ghid"
|
||||||
tome_minion_spells: "Vrăjile Minion-ilor tăi"
|
tome_minion_spells: "Vrăjile Minion-ilor tăi"
|
||||||
tome_read_only_spells: "Vrăji Read-Only"
|
tome_read_only_spells: "Vrăji Read-Only"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
multiplayer_hint_label: "Подсказка: "
|
multiplayer_hint_label: "Подсказка: "
|
||||||
multiplayer_hint: "кликните на ссылку, чтобы выделить её, затем нажмите ⌘-С или Ctrl-C, чтобы скопировать."
|
multiplayer_hint: "кликните на ссылку, чтобы выделить её, затем нажмите ⌘-С или Ctrl-C, чтобы скопировать."
|
||||||
multiplayer_coming_soon: "Больше возможностей мультиплеера на подходе!"
|
multiplayer_coming_soon: "Больше возможностей мультиплеера на подходе!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Руководство"
|
guide_title: "Руководство"
|
||||||
tome_minion_spells: "Заклинания ваших миньонов"
|
tome_minion_spells: "Заклинания ваших миньонов"
|
||||||
tome_read_only_spells: "Заклинания только для чтения"
|
tome_read_only_spells: "Заклинания только для чтения"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
|
||||||
multiplayer_hint_label: "Мала помоћ"
|
multiplayer_hint_label: "Мала помоћ"
|
||||||
multiplayer_hint: " Кликни на линк да обележиш све, затим притисни Apple-C или Ctrl-C да копираш линк."
|
multiplayer_hint: " Кликни на линк да обележиш све, затим притисни Apple-C или Ctrl-C да копираш линк."
|
||||||
multiplayer_coming_soon: "Стиже још нових карактеристика!"
|
multiplayer_coming_soon: "Стиже још нових карактеристика!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Водич"
|
guide_title: "Водич"
|
||||||
tome_minion_spells: "Чини твојих поданика"
|
tome_minion_spells: "Чини твојих поданика"
|
||||||
tome_read_only_spells: "Чини које се могу само гледати"
|
tome_read_only_spells: "Чини које се могу само гледати"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
|
||||||
multiplayer_hint_label: "Tips:"
|
multiplayer_hint_label: "Tips:"
|
||||||
multiplayer_hint: " Klicka på länken för att välja allt, tryck sedan på Cmd-C eller Ctrl-C för att kopiera länken."
|
multiplayer_hint: " Klicka på länken för att välja allt, tryck sedan på Cmd-C eller Ctrl-C för att kopiera länken."
|
||||||
multiplayer_coming_soon: "Fler flerspelarlägen kommer!"
|
multiplayer_coming_soon: "Fler flerspelarlägen kommer!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Guide"
|
guide_title: "Guide"
|
||||||
tome_minion_spells: "Dina soldaters förmågor"
|
tome_minion_spells: "Dina soldaters förmågor"
|
||||||
tome_read_only_spells: "Skrivskyddade förmågor"
|
tome_read_only_spells: "Skrivskyddade förmågor"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
|
||||||
multiplayer_hint_label: "คำใบ้"
|
multiplayer_hint_label: "คำใบ้"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
|
||||||
multiplayer_hint_label: "İpucu:"
|
multiplayer_hint_label: "İpucu:"
|
||||||
multiplayer_hint: " Kopyalamak için önce linke tıklayın, ardından CTRL+C veya ⌘+C kombinasyonuna basın."
|
multiplayer_hint: " Kopyalamak için önce linke tıklayın, ardından CTRL+C veya ⌘+C kombinasyonuna basın."
|
||||||
multiplayer_coming_soon: "Daha bir çok çoklu oyuncu özelliği eklenecek!"
|
multiplayer_coming_soon: "Daha bir çok çoklu oyuncu özelliği eklenecek!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Rehber"
|
guide_title: "Rehber"
|
||||||
tome_minion_spells: "Minyonlarınızın Büyüleri"
|
tome_minion_spells: "Minyonlarınızın Büyüleri"
|
||||||
tome_read_only_spells: "Salt Okunur Büyüler"
|
tome_read_only_spells: "Salt Okunur Büyüler"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
|
||||||
multiplayer_hint_label: "Підказка:"
|
multiplayer_hint_label: "Підказка:"
|
||||||
multiplayer_hint: "Натисніть на посилання, щоб обрати всіх, та натисніть Apple-C або Ctrl-C, щоб скопіювати посилання."
|
multiplayer_hint: "Натисніть на посилання, щоб обрати всіх, та натисніть Apple-C або Ctrl-C, щоб скопіювати посилання."
|
||||||
multiplayer_coming_soon: "Скоро - більше можливостей у мультиплеєрі!"
|
multiplayer_coming_soon: "Скоро - більше можливостей у мультиплеєрі!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "Посібник"
|
guide_title: "Посібник"
|
||||||
tome_minion_spells: "Закляття ваших міньонів"
|
tome_minion_spells: "Закляття ваших міньонів"
|
||||||
tome_read_only_spells: "Закляття тільки для читання"
|
tome_read_only_spells: "Закляття тільки для читання"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "українська мова", englishDesc
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
multiplayer_hint_label: "提示:"
|
multiplayer_hint_label: "提示:"
|
||||||
multiplayer_hint: " 点击全选,然后按 Apple-C(苹果电脑)或 Ctrl-C 复制链接。"
|
multiplayer_hint: " 点击全选,然后按 Apple-C(苹果电脑)或 Ctrl-C 复制链接。"
|
||||||
multiplayer_coming_soon: "多人游戏的更多特性!"
|
multiplayer_coming_soon: "多人游戏的更多特性!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "指南"
|
guide_title: "指南"
|
||||||
tome_minion_spells: "助手的咒语"
|
tome_minion_spells: "助手的咒语"
|
||||||
tome_read_only_spells: "只读的咒语"
|
tome_read_only_spells: "只读的咒语"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
|
||||||
multiplayer_hint_label: "提示:"
|
multiplayer_hint_label: "提示:"
|
||||||
multiplayer_hint: " 點擊全選,然後按 ⌘-C 或 Ctrl-C 複製連結。"
|
multiplayer_hint: " 點擊全選,然後按 ⌘-C 或 Ctrl-C 複製連結。"
|
||||||
multiplayer_coming_soon: "請期待更多的多人關卡!"
|
multiplayer_coming_soon: "請期待更多的多人關卡!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "指南"
|
guide_title: "指南"
|
||||||
tome_minion_spells: "助手的咒語"
|
tome_minion_spells: "助手的咒語"
|
||||||
tome_read_only_spells: "唯讀的咒語"
|
tome_read_only_spells: "唯讀的咒語"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
|
||||||
multiplayer_hint_label: "提醒:"
|
multiplayer_hint_label: "提醒:"
|
||||||
multiplayer_hint: " 點牢全選,再捺 Apple-C(蘋果電腦)要勿 Ctrl-C 複製鏈接。"
|
multiplayer_hint: " 點牢全選,再捺 Apple-C(蘋果電腦)要勿 Ctrl-C 複製鏈接。"
|
||||||
multiplayer_coming_soon: "多人遊戲還多特性!"
|
multiplayer_coming_soon: "多人遊戲還多特性!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
guide_title: "指南"
|
guide_title: "指南"
|
||||||
tome_minion_spells: "下手個咒語"
|
tome_minion_spells: "下手個咒語"
|
||||||
tome_read_only_spells: "只讀個咒語"
|
tome_read_only_spells: "只讀個咒語"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -17,7 +17,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
|
||||||
retry: "重试"
|
retry: "重试"
|
||||||
# watch: "Watch"
|
# watch: "Watch"
|
||||||
# unwatch: "Unwatch"
|
# unwatch: "Unwatch"
|
||||||
# submit_patch: "Submit Patch"
|
submit_patch: "提交补丁"
|
||||||
|
|
||||||
units:
|
units:
|
||||||
second: "秒"
|
second: "秒"
|
||||||
|
@ -36,7 +36,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
play: "玩"
|
play: "玩"
|
||||||
# community: "Community"
|
community: "社区"
|
||||||
editor: "编辑"
|
editor: "编辑"
|
||||||
blog: "博客"
|
blog: "博客"
|
||||||
forum: "论坛"
|
forum: "论坛"
|
||||||
|
@ -53,7 +53,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
|
||||||
versions:
|
versions:
|
||||||
save_version_title: "保存新版本"
|
save_version_title: "保存新版本"
|
||||||
new_major_version: "最新主要版本"
|
new_major_version: "最新主要版本"
|
||||||
# cla_prefix: "To save changes, first you must agree to our"
|
cla_prefix: "要保存更改, 首先你必须要统一我们的"
|
||||||
# cla_url: "CLA"
|
# cla_url: "CLA"
|
||||||
# cla_suffix: "."
|
# cla_suffix: "."
|
||||||
cla_agree: "我同意"
|
cla_agree: "我同意"
|
||||||
|
@ -61,7 +61,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
|
||||||
login:
|
login:
|
||||||
sign_up: "注册"
|
sign_up: "注册"
|
||||||
log_in: "登录"
|
log_in: "登录"
|
||||||
# logging_in: "Logging In"
|
logging_in: "登录中..."
|
||||||
log_out: "登出"
|
log_out: "登出"
|
||||||
recover: "找回账户"
|
recover: "找回账户"
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
|
||||||
creating: "账户在创新中"
|
creating: "账户在创新中"
|
||||||
sign_up: "注册"
|
sign_up: "注册"
|
||||||
log_in: "以密码登录"
|
log_in: "以密码登录"
|
||||||
# social_signup: "Or, you can sign up through Facebook or G+:"
|
social_signup: "或者, 你可以通过Facebook 或者 G+ 注册:"
|
||||||
|
|
||||||
home:
|
home:
|
||||||
slogan: "通过游戏学习Javascript脚本语言"
|
slogan: "通过游戏学习Javascript脚本语言"
|
||||||
|
@ -130,21 +130,21 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
|
||||||
# learn_more: "Learn more about being a Diplomat"
|
# learn_more: "Learn more about being a Diplomat"
|
||||||
# subscribe_as_diplomat: "Subscribe as a Diplomat"
|
# subscribe_as_diplomat: "Subscribe as a Diplomat"
|
||||||
|
|
||||||
# wizard_settings:
|
wizard_settings:
|
||||||
# title: "Wizard Settings"
|
title: "巫师设定"
|
||||||
# customize_avatar: "Customize Your Avatar"
|
customize_avatar: "设置你的头像"
|
||||||
# active: "Active"
|
active: "启用"
|
||||||
# color: "Color"
|
color: "颜色"
|
||||||
# group: "Group"
|
group: "类别"
|
||||||
# clothes: "Clothes"
|
clothes: "衣服"
|
||||||
# trim: "Trim"
|
trim: "条纹"
|
||||||
# cloud: "Cloud"
|
cloud: "云"
|
||||||
# team: "Team"
|
team: "队伍"
|
||||||
# spell: "Spell"
|
spell: "魔法球"
|
||||||
# boots: "Boots"
|
boots: "鞋子"
|
||||||
# hue: "Hue"
|
hue: "色彩"
|
||||||
# saturation: "Saturation"
|
saturation: "饱和度"
|
||||||
# lightness: "Lightness"
|
lightness: "亮度"
|
||||||
|
|
||||||
# account_settings:
|
# account_settings:
|
||||||
# title: "Account Settings"
|
# title: "Account Settings"
|
||||||
|
@ -246,6 +246,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
|
||||||
# multiplayer_hint_label: "Hint:"
|
# multiplayer_hint_label: "Hint:"
|
||||||
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
|
||||||
# multiplayer_coming_soon: "More multiplayer features to come!"
|
# multiplayer_coming_soon: "More multiplayer features to come!"
|
||||||
|
# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard."
|
||||||
# guide_title: "Guide"
|
# guide_title: "Guide"
|
||||||
# tome_minion_spells: "Your Minions' Spells"
|
# tome_minion_spells: "Your Minions' Spells"
|
||||||
# tome_read_only_spells: "Read-Only Spells"
|
# tome_read_only_spells: "Read-Only Spells"
|
||||||
|
@ -710,3 +711,4 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
|
||||||
# user_names: "User Names"
|
# user_names: "User Names"
|
||||||
# files: "Files"
|
# files: "Files"
|
||||||
# top_simulators: "Top Simulators"
|
# top_simulators: "Top Simulators"
|
||||||
|
# source_document: "Source Document"
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
storage = require 'lib/storage'
|
storage = require 'lib/storage'
|
||||||
deltasLib = require 'lib/deltas'
|
deltasLib = require 'lib/deltas'
|
||||||
auth = require 'lib/auth'
|
|
||||||
|
|
||||||
class CocoModel extends Backbone.Model
|
class CocoModel extends Backbone.Model
|
||||||
idAttribute: "_id"
|
idAttribute: "_id"
|
||||||
|
@ -9,6 +8,8 @@ class CocoModel extends Backbone.Model
|
||||||
saveBackups: false
|
saveBackups: false
|
||||||
@schema: null
|
@schema: null
|
||||||
|
|
||||||
|
getMe: -> @me or @me = require('lib/auth').me
|
||||||
|
|
||||||
initialize: ->
|
initialize: ->
|
||||||
super()
|
super()
|
||||||
if not @constructor.className
|
if not @constructor.className
|
||||||
|
@ -96,7 +97,8 @@ class CocoModel extends Backbone.Model
|
||||||
not _.isEqual @attributes, @_revertAttributes
|
not _.isEqual @attributes, @_revertAttributes
|
||||||
|
|
||||||
cloneNewMinorVersion: ->
|
cloneNewMinorVersion: ->
|
||||||
newData = $.extend(null, {}, @attributes)
|
newData = _.clone @attributes
|
||||||
|
|
||||||
clone = new @constructor(newData)
|
clone = new @constructor(newData)
|
||||||
clone
|
clone
|
||||||
|
|
||||||
|
@ -136,7 +138,7 @@ class CocoModel extends Backbone.Model
|
||||||
hasReadAccess: (actor) ->
|
hasReadAccess: (actor) ->
|
||||||
# actor is a User object
|
# actor is a User object
|
||||||
|
|
||||||
actor ?= auth.me
|
actor ?= @getMe()
|
||||||
return true if actor.isAdmin()
|
return true if actor.isAdmin()
|
||||||
if @get('permissions')?
|
if @get('permissions')?
|
||||||
for permission in @get('permissions')
|
for permission in @get('permissions')
|
||||||
|
@ -148,7 +150,7 @@ class CocoModel extends Backbone.Model
|
||||||
hasWriteAccess: (actor) ->
|
hasWriteAccess: (actor) ->
|
||||||
# actor is a User object
|
# actor is a User object
|
||||||
|
|
||||||
actor ?= auth.me
|
actor ?= @getMe()
|
||||||
return true if actor.isAdmin()
|
return true if actor.isAdmin()
|
||||||
if @get('permissions')?
|
if @get('permissions')?
|
||||||
for permission in @get('permissions')
|
for permission in @get('permissions')
|
||||||
|
|
|
@ -24,3 +24,15 @@ module.exports = class LevelSession extends CocoModel
|
||||||
code = @get('code')
|
code = @get('code')
|
||||||
parts = spellKey.split '/'
|
parts = spellKey.split '/'
|
||||||
code?[parts[0]]?[parts[1]]
|
code?[parts[0]]?[parts[1]]
|
||||||
|
|
||||||
|
readyToRank: ->
|
||||||
|
return false unless @get('levelID') # If it hasn't been denormalized, then it's not ready.
|
||||||
|
return false unless c1 = @get('code')
|
||||||
|
return false unless team = @get('team')
|
||||||
|
return true unless c2 = @get('submittedCode')
|
||||||
|
thangSpellArr = (s.split("/") for s in @get('teamSpells')[team])
|
||||||
|
for item in thangSpellArr
|
||||||
|
thang = item[0]
|
||||||
|
spell = item[1]
|
||||||
|
return true if c1[thang][spell] isnt c2[thang][spell]
|
||||||
|
false
|
||||||
|
|
|
@ -4,6 +4,7 @@ ThangComponentSchema = require './thang_component'
|
||||||
SpecificArticleSchema = c.object()
|
SpecificArticleSchema = c.object()
|
||||||
c.extendNamedProperties SpecificArticleSchema # name first
|
c.extendNamedProperties SpecificArticleSchema # name first
|
||||||
SpecificArticleSchema.properties.body = { type: 'string', title: 'Content', description: "The body content of the article, in Markdown.", format: 'markdown' }
|
SpecificArticleSchema.properties.body = { type: 'string', title: 'Content', description: "The body content of the article, in Markdown.", format: 'markdown' }
|
||||||
|
SpecificArticleSchema.properties.i18n = {type: "object", format: 'i18n', props: ['name', 'body'], description: "Help translate this article"}
|
||||||
SpecificArticleSchema.displayProperty = 'name'
|
SpecificArticleSchema.displayProperty = 'name'
|
||||||
|
|
||||||
side = {title: "Side", description: "A side.", type: 'string', 'enum': ['left', 'right', 'top', 'bottom']}
|
side = {title: "Side", description: "A side.", type: 'string', 'enum': ['left', 'right', 'top', 'bottom']}
|
||||||
|
|
|
@ -27,10 +27,11 @@ block modal-body-content
|
||||||
|
|
||||||
if ladderGame
|
if ladderGame
|
||||||
if me.get('anonymous')
|
if me.get('anonymous')
|
||||||
p Sign in or create an account and get your solution on the leaderboard!
|
p(data-i18n="play_level.multiplayer_sign_in_leaderboard") Sign in or create an account and get your solution on the leaderboard.
|
||||||
|
else if readyToRank
|
||||||
|
button.btn.btn-success.rank-game-button(data-i18n="play_level.victory_rank_my_game") Rank My Game
|
||||||
else
|
else
|
||||||
a#go-to-leaderboard-button.btn.btn-primary(href="/play/ladder/#{levelSlug}#my-matches") Go to the leaderboard!
|
a.btn.btn-primary(href="/play/ladder/#{levelSlug}#my-matches", data-i18n="play_level.victory_go_ladder") Return to Ladder
|
||||||
p You can submit your game to be ranked from the leaderboard page.
|
|
||||||
|
|
||||||
block modal-footer-content
|
block modal-footer-content
|
||||||
a(href='#', data-dismiss="modal", aria-hidden="true", data-i18n="modal.close").btn.btn-primary Close
|
a(href='#', data-dismiss="modal", aria-hidden="true", data-i18n="modal.close").btn.btn-primary Close
|
||||||
|
|
|
@ -72,7 +72,7 @@ module.exports = class MyMatchesTabView extends CocoView
|
||||||
|
|
||||||
for team in @teams
|
for team in @teams
|
||||||
team.session = (s for s in @sessions.models when s.get('team') is team.id)[0]
|
team.session = (s for s in @sessions.models when s.get('team') is team.id)[0]
|
||||||
team.readyToRank = @readyToRank(team.session)
|
team.readyToRank = team.session?.readyToRank()
|
||||||
team.isRanking = team.session?.get('isRanking')
|
team.isRanking = team.session?.get('isRanking')
|
||||||
team.matches = (convertMatch(match, team.session.get('submitDate')) for match in team.session?.get('matches') or [])
|
team.matches = (convertMatch(match, team.session.get('submitDate')) for match in team.session?.get('matches') or [])
|
||||||
team.matches.reverse()
|
team.matches.reverse()
|
||||||
|
@ -108,7 +108,7 @@ module.exports = class MyMatchesTabView extends CocoView
|
||||||
sessionID = button.data('session-id')
|
sessionID = button.data('session-id')
|
||||||
session = _.find @sessions.models, {id: sessionID}
|
session = _.find @sessions.models, {id: sessionID}
|
||||||
rankingState = 'unavailable'
|
rankingState = 'unavailable'
|
||||||
if @readyToRank session
|
if session.readyToRank()
|
||||||
rankingState = 'rank'
|
rankingState = 'rank'
|
||||||
else if session.get 'isRanking'
|
else if session.get 'isRanking'
|
||||||
rankingState = 'ranking'
|
rankingState = 'ranking'
|
||||||
|
@ -119,7 +119,6 @@ module.exports = class MyMatchesTabView extends CocoView
|
||||||
team = _.find @teams, name: scoreWrapper.data('team-name')
|
team = _.find @teams, name: scoreWrapper.data('team-name')
|
||||||
@generateScoreLineChart(scoreWrapper.attr('id'), team.scoreHistory, team.name)
|
@generateScoreLineChart(scoreWrapper.attr('id'), team.scoreHistory, team.name)
|
||||||
|
|
||||||
|
|
||||||
generateScoreLineChart: (wrapperID, scoreHistory,teamName) =>
|
generateScoreLineChart: (wrapperID, scoreHistory,teamName) =>
|
||||||
margin =
|
margin =
|
||||||
top: 20
|
top: 20
|
||||||
|
@ -154,8 +153,6 @@ module.exports = class MyMatchesTabView extends CocoView
|
||||||
x.domain(d3.extent(data, (d) -> d.date))
|
x.domain(d3.extent(data, (d) -> d.date))
|
||||||
y.domain(d3.extent(data, (d) -> d.close))
|
y.domain(d3.extent(data, (d) -> d.close))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
svg.append("g")
|
svg.append("g")
|
||||||
.attr("class", "y axis")
|
.attr("class", "y axis")
|
||||||
.call(yAxis)
|
.call(yAxis)
|
||||||
|
@ -173,21 +170,6 @@ module.exports = class MyMatchesTabView extends CocoView
|
||||||
.attr("class",lineClass)
|
.attr("class",lineClass)
|
||||||
.attr("d",line)
|
.attr("d",line)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
readyToRank: (session) ->
|
|
||||||
return false unless session?.get('levelID') # If it hasn't been denormalized, then it's not ready.
|
|
||||||
return false unless c1 = session.get('code')
|
|
||||||
return false unless team = session.get('team')
|
|
||||||
return true unless c2 = session.get('submittedCode')
|
|
||||||
thangSpellArr = (s.split("/") for s in session.get('teamSpells')[team])
|
|
||||||
for item in thangSpellArr
|
|
||||||
thang = item[0]
|
|
||||||
spell = item[1]
|
|
||||||
return true if c1[thang][spell] isnt c2[thang][spell]
|
|
||||||
return false
|
|
||||||
|
|
||||||
rankSession: (e) ->
|
rankSession: (e) ->
|
||||||
button = $(e.target).closest('.rank-button')
|
button = $(e.target).closest('.rank-button')
|
||||||
sessionID = button.data('session-id')
|
sessionID = button.data('session-id')
|
||||||
|
@ -202,7 +184,6 @@ module.exports = class MyMatchesTabView extends CocoView
|
||||||
@setRankingButtonText(button, 'failed')
|
@setRankingButtonText(button, 'failed')
|
||||||
|
|
||||||
ajaxData = {session: sessionID, levelID: @level.id, originalLevelID: @level.attributes.original, levelMajorVersion: @level.attributes.version.major}
|
ajaxData = {session: sessionID, levelID: @level.id, originalLevelID: @level.attributes.original, levelMajorVersion: @level.attributes.version.major}
|
||||||
console.log "Posting game for ranking from My Matches view."
|
|
||||||
$.ajax '/queue/scoring', {
|
$.ajax '/queue/scoring', {
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
data: ajaxData
|
data: ajaxData
|
||||||
|
|
|
@ -56,7 +56,6 @@ module.exports = class ControlBarView extends View
|
||||||
c.multiplayerEnabled = @session.get('multiplayer')
|
c.multiplayerEnabled = @session.get('multiplayer')
|
||||||
c.ladderGame = @level.get('type') is 'ladder'
|
c.ladderGame = @level.get('type') is 'ladder'
|
||||||
c.spectateGame = @spectateGame
|
c.spectateGame = @spectateGame
|
||||||
console.log "level type is", @level.get('type')
|
|
||||||
if @level.get('type') in ['ladder', 'ladder-tutorial']
|
if @level.get('type') in ['ladder', 'ladder-tutorial']
|
||||||
c.homeLink = '/play/ladder/' + @level.get('slug').replace /\-tutorial$/, ''
|
c.homeLink = '/play/ladder/' + @level.get('slug').replace /\-tutorial$/, ''
|
||||||
else
|
else
|
||||||
|
|
|
@ -9,7 +9,7 @@ module.exports = class MultiplayerModal extends View
|
||||||
events:
|
events:
|
||||||
'click textarea': 'onClickLink'
|
'click textarea': 'onClickLink'
|
||||||
'change #multiplayer': 'updateLinkSection'
|
'change #multiplayer': 'updateLinkSection'
|
||||||
|
'click .rank-game-button': 'onRankGame'
|
||||||
|
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super(options)
|
super(options)
|
||||||
|
@ -17,20 +17,20 @@ module.exports = class MultiplayerModal extends View
|
||||||
@level = options.level
|
@level = options.level
|
||||||
@listenTo(@session, 'change:multiplayer', @updateLinkSection)
|
@listenTo(@session, 'change:multiplayer', @updateLinkSection)
|
||||||
@playableTeams = options.playableTeams
|
@playableTeams = options.playableTeams
|
||||||
@ladderGame = options.ladderGame
|
|
||||||
console.log 'ladder game is', @ladderGame
|
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
c = super()
|
c = super()
|
||||||
c.joinLink = (document.location.href.replace(/\?.*/, '').replace('#', '') +
|
c.joinLink = (document.location.href.replace(/\?.*/, '').replace('#', '') +
|
||||||
'?session=' +
|
'?session=' +
|
||||||
@session.id)
|
@session.id)
|
||||||
c.multiplayer = @session.get('multiplayer')
|
c.multiplayer = @session.get 'multiplayer'
|
||||||
c.team = @session.get 'team'
|
c.team = @session.get 'team'
|
||||||
c.levelSlug = @level?.get('slug')
|
c.levelSlug = @level?.get 'slug'
|
||||||
c.playableTeams = @playableTeams
|
c.playableTeams = @playableTeams
|
||||||
c.ladderGame = @ladderGame
|
|
||||||
# For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet.
|
# For now, ladderGame will disallow multiplayer, because session code combining doesn't play nice yet.
|
||||||
|
if @level?.get('type') is 'ladder'
|
||||||
|
c.ladderGame = true
|
||||||
|
c.readyToRank = @session?.readyToRank()
|
||||||
c
|
c
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
|
@ -50,5 +50,20 @@ module.exports = class MultiplayerModal extends View
|
||||||
multiplayer = Boolean(@$el.find('#multiplayer').prop('checked'))
|
multiplayer = Boolean(@$el.find('#multiplayer').prop('checked'))
|
||||||
@session.set('multiplayer', multiplayer)
|
@session.set('multiplayer', multiplayer)
|
||||||
|
|
||||||
|
onRankGame: (e) ->
|
||||||
|
button = @$el.find('.rank-game-button')
|
||||||
|
button.text($.i18n.t('play_level.victory_ranking_game', defaultValue: 'Submitting...'))
|
||||||
|
button.prop 'disabled', true
|
||||||
|
ajaxData = session: @session.id, levelID: @level.id, originalLevelID: @level.get('original'), levelMajorVersion: @level.get('version').major
|
||||||
|
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
|
||||||
|
goToLadder = -> Backbone.Mediator.publish 'router:navigate', route: ladderURL
|
||||||
|
$.ajax '/queue/scoring',
|
||||||
|
type: 'POST'
|
||||||
|
data: ajaxData
|
||||||
|
success: goToLadder
|
||||||
|
failure: (response) ->
|
||||||
|
console.error "Couldn't submit game for ranking:", response
|
||||||
|
goToLadder()
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
super()
|
super()
|
||||||
|
|
|
@ -65,7 +65,6 @@ module.exports = class VictoryModal extends View
|
||||||
ajaxData = session: @session.id, levelID: @level.id, originalLevelID: @level.get('original'), levelMajorVersion: @level.get('version').major
|
ajaxData = session: @session.id, levelID: @level.id, originalLevelID: @level.get('original'), levelMajorVersion: @level.get('version').major
|
||||||
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
|
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
|
||||||
goToLadder = -> Backbone.Mediator.publish 'router:navigate', route: ladderURL
|
goToLadder = -> Backbone.Mediator.publish 'router:navigate', route: ladderURL
|
||||||
console.log "Posting game for ranking from victory modal."
|
|
||||||
$.ajax '/queue/scoring',
|
$.ajax '/queue/scoring',
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
data: ajaxData
|
data: ajaxData
|
||||||
|
@ -82,9 +81,7 @@ module.exports = class VictoryModal extends View
|
||||||
c.levelName = utils.i18n @level.attributes, 'name'
|
c.levelName = utils.i18n @level.attributes, 'name'
|
||||||
c.level = @level
|
c.level = @level
|
||||||
if c.level.get('type') is 'ladder'
|
if c.level.get('type') is 'ladder'
|
||||||
c1 = @session?.get('code')
|
c.readyToRank = @session.readyToRank()
|
||||||
c2 = @session?.get('submittedCode')
|
|
||||||
c.readyToRank = @session.get('levelID') and c1 and not _.isEqual(c1, c2)
|
|
||||||
if me.get 'hourOfCode'
|
if me.get 'hourOfCode'
|
||||||
# Show the Hour of Code "I'm Done" tracking pixel after they played for 30 minutes
|
# Show the Hour of Code "I'm Done" tracking pixel after they played for 30 minutes
|
||||||
elapsed = (new Date() - new Date(me.get('dateCreated')))
|
elapsed = (new Date() - new Date(me.get('dateCreated')))
|
||||||
|
|
|
@ -12,7 +12,7 @@ Surface = require 'lib/surface/Surface'
|
||||||
God = require 'lib/God'
|
God = require 'lib/God'
|
||||||
GoalManager = require 'lib/world/GoalManager'
|
GoalManager = require 'lib/world/GoalManager'
|
||||||
ScriptManager = require 'lib/scripts/ScriptManager'
|
ScriptManager = require 'lib/scripts/ScriptManager'
|
||||||
LevelBus = require('lib/LevelBus')
|
LevelBus = require 'lib/LevelBus'
|
||||||
LevelLoader = require 'lib/LevelLoader'
|
LevelLoader = require 'lib/LevelLoader'
|
||||||
LevelSession = require 'models/LevelSession'
|
LevelSession = require 'models/LevelSession'
|
||||||
Level = require 'models/Level'
|
Level = require 'models/Level'
|
||||||
|
@ -112,8 +112,8 @@ module.exports = class PlayLevelView extends View
|
||||||
|
|
||||||
load: ->
|
load: ->
|
||||||
@loadStartTime = new Date()
|
@loadStartTime = new Date()
|
||||||
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @getQueryVariable('opponent'), team: @getQueryVariable("team")
|
|
||||||
@god = new God()
|
@god = new God()
|
||||||
|
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @getQueryVariable('opponent'), team: @getQueryVariable("team")
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
c = super()
|
c = super()
|
||||||
|
@ -169,7 +169,7 @@ module.exports = class PlayLevelView extends View
|
||||||
team = @getQueryVariable("team") ? @world.teamForPlayer(0)
|
team = @getQueryVariable("team") ? @world.teamForPlayer(0)
|
||||||
@loadOpponentTeam(team)
|
@loadOpponentTeam(team)
|
||||||
@god.level = @level.serialize @supermodel
|
@god.level = @level.serialize @supermodel
|
||||||
@god.worldClassMap = @world.classMap
|
@god.setWorldClassMap @world.classMap
|
||||||
@setTeam team
|
@setTeam team
|
||||||
@initSurface()
|
@initSurface()
|
||||||
@initGoalManager()
|
@initGoalManager()
|
||||||
|
@ -427,7 +427,7 @@ module.exports = class PlayLevelView extends View
|
||||||
|
|
||||||
initGoalManager: ->
|
initGoalManager: ->
|
||||||
@goalManager = new GoalManager(@world, @level.get('goals'))
|
@goalManager = new GoalManager(@world, @level.get('goals'))
|
||||||
@god.goalManager = @goalManager
|
@god.setGoalManager @goalManager
|
||||||
|
|
||||||
initScriptManager: ->
|
initScriptManager: ->
|
||||||
@scriptManager = new ScriptManager({scripts: @world.scripts or [], view:@, session: @session})
|
@scriptManager = new ScriptManager({scripts: @world.scripts or [], view:@, session: @session})
|
||||||
|
|
|
@ -8,7 +8,7 @@ World = require 'lib/world/world'
|
||||||
|
|
||||||
# tools
|
# tools
|
||||||
Surface = require 'lib/surface/Surface'
|
Surface = require 'lib/surface/Surface'
|
||||||
God = require 'lib/God'
|
God = require 'lib/God' # 'lib/Buddha'
|
||||||
GoalManager = require 'lib/world/GoalManager'
|
GoalManager = require 'lib/world/GoalManager'
|
||||||
ScriptManager = require 'lib/scripts/ScriptManager'
|
ScriptManager = require 'lib/scripts/ScriptManager'
|
||||||
LevelLoader = require 'lib/LevelLoader'
|
LevelLoader = require 'lib/LevelLoader'
|
||||||
|
@ -156,7 +156,7 @@ module.exports = class SpectateLevelView extends View
|
||||||
team = @world.teamForPlayer(0)
|
team = @world.teamForPlayer(0)
|
||||||
@loadOpponentTeam(team)
|
@loadOpponentTeam(team)
|
||||||
@god.level = @level.serialize @supermodel
|
@god.level = @level.serialize @supermodel
|
||||||
@god.worldClassMap = @world.classMap
|
@god.setWorldClassMap @world.classMap
|
||||||
@setTeam team
|
@setTeam team
|
||||||
@initSurface()
|
@initSurface()
|
||||||
@initGoalManager()
|
@initGoalManager()
|
||||||
|
@ -387,7 +387,7 @@ module.exports = class SpectateLevelView extends View
|
||||||
|
|
||||||
initGoalManager: ->
|
initGoalManager: ->
|
||||||
@goalManager = new GoalManager(@world, @level.get('goals'))
|
@goalManager = new GoalManager(@world, @level.get('goals'))
|
||||||
@god.goalManager = @goalManager
|
@god.setGoalManager @goalManager
|
||||||
|
|
||||||
initScriptManager: ->
|
initScriptManager: ->
|
||||||
if @world.scripts
|
if @world.scripts
|
||||||
|
|
214
headless_client.coffee
Normal file
214
headless_client.coffee
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
###
|
||||||
|
This file will simulate games on node.js by emulating the browser environment.
|
||||||
|
At some point, most of the code can be merged with Simulator.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
bowerComponentsPath = "./bower_components/"
|
||||||
|
headlessClientPath = "./headless_client/"
|
||||||
|
|
||||||
|
# SETTINGS
|
||||||
|
options =
|
||||||
|
workerCode: require headlessClientPath + 'worker_world'
|
||||||
|
debug: false # Enable logging of ajax calls mainly
|
||||||
|
testing: true # Instead of simulating 'real' games, use the same one over and over again. Good for leak hunting.
|
||||||
|
testFile: require headlessClientPath + 'test.js'
|
||||||
|
leakTest: false # Install callback that tries to find leaks automatically
|
||||||
|
exitOnLeak: false # Exit if leak is found. Only useful if leaktest is set to true, obviously.
|
||||||
|
heapdump: false # Dumps the whole heap after every pass. The heap dumps can then be viewed in Chrome browser.
|
||||||
|
headlessClient: true
|
||||||
|
|
||||||
|
options.heapdump = require('heapdump') if options.heapdump
|
||||||
|
server = if options.testing then "http://127.0.0.1:3000" else "http://codecombat.com"
|
||||||
|
|
||||||
|
# Disabled modules
|
||||||
|
disable = [
|
||||||
|
'lib/AudioPlayer'
|
||||||
|
'locale/locale'
|
||||||
|
'../locale/locale'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Start of the actual code. Setting up the enivronment to match the environment of the browser
|
||||||
|
|
||||||
|
# the path used for the loader. __dirname is module dependent.
|
||||||
|
path = __dirname
|
||||||
|
|
||||||
|
m = require 'module'
|
||||||
|
request = require 'request'
|
||||||
|
|
||||||
|
originalLoader = m._load
|
||||||
|
|
||||||
|
unhook = () ->
|
||||||
|
m._load = originalLoader
|
||||||
|
|
||||||
|
hook = () ->
|
||||||
|
m._load = hookedLoader
|
||||||
|
|
||||||
|
|
||||||
|
JASON = require 'jason'
|
||||||
|
|
||||||
|
# Global emulated stuff
|
||||||
|
GLOBAL.window = GLOBAL
|
||||||
|
GLOBAL.document = location: pathname: "headless_client"
|
||||||
|
GLOBAL.console.debug = console.log
|
||||||
|
|
||||||
|
GLOBAL.Worker = require('webworker-threads').Worker
|
||||||
|
Worker::removeEventListener = (what) ->
|
||||||
|
if what is 'message'
|
||||||
|
@onmessage = -> #This webworker api has only one event listener at a time.
|
||||||
|
|
||||||
|
GLOBAL.tv4 = require('tv4').tv4
|
||||||
|
|
||||||
|
GLOBAL.marked = setOptions: ->
|
||||||
|
|
||||||
|
GLOBAL.navigator =
|
||||||
|
# userAgent: "nodejs"
|
||||||
|
platform: "headless_client"
|
||||||
|
vendor: "codecombat"
|
||||||
|
opera: false
|
||||||
|
|
||||||
|
store = {}
|
||||||
|
GLOBAL.localStorage =
|
||||||
|
getItem: (key) => store[key]
|
||||||
|
setItem: (key, s) => store[key] = s
|
||||||
|
removeItem: (key) => delete store[key]
|
||||||
|
|
||||||
|
# Hook node.js require. See https://github.com/mfncooper/mockery/blob/master/mockery.js
|
||||||
|
# The signature of this function *must* match that of Node's Module._load,
|
||||||
|
# since it will replace that.
|
||||||
|
# (Why is there no easier way?)
|
||||||
|
hookedLoader = (request, parent, isMain) ->
|
||||||
|
if request == 'lib/God'
|
||||||
|
request = 'lib/Buddha'
|
||||||
|
|
||||||
|
if request in disable or ~request.indexOf('templates')
|
||||||
|
console.log 'Ignored ' + request if options.debug
|
||||||
|
return class fake
|
||||||
|
else if '/' in request and not (request[0] is '.') or request is 'application'
|
||||||
|
request = path + '/app/' + request
|
||||||
|
else if request is 'underscore'
|
||||||
|
request = 'lodash'
|
||||||
|
|
||||||
|
console.log "loading " + request if options.debug
|
||||||
|
originalLoader request, parent, isMain
|
||||||
|
|
||||||
|
|
||||||
|
#jQuery wrapped for compatibility purposes. Poorly.
|
||||||
|
GLOBAL.$ = GLOBAL.jQuery = (input) ->
|
||||||
|
console.log 'Ignored jQuery: ' + input if options.debug
|
||||||
|
append: (input)-> exports: ()->
|
||||||
|
|
||||||
|
cookies = request.jar()
|
||||||
|
|
||||||
|
$.ajax = (options) ->
|
||||||
|
responded = false
|
||||||
|
url = options.url
|
||||||
|
if url.indexOf('http')
|
||||||
|
url = '/' + url unless url[0] is '/'
|
||||||
|
url = server + url
|
||||||
|
|
||||||
|
data = options.data
|
||||||
|
|
||||||
|
|
||||||
|
#if (typeof data) is 'object'
|
||||||
|
#console.warn JSON.stringify data
|
||||||
|
#data = JSON.stringify data
|
||||||
|
|
||||||
|
console.log "Requesting: " + JSON.stringify options if options.debug
|
||||||
|
console.log "URL: " + url if options.debug
|
||||||
|
request
|
||||||
|
url: url
|
||||||
|
jar: cookies
|
||||||
|
json: options.parse
|
||||||
|
method: options.type
|
||||||
|
body: data
|
||||||
|
, (error, response, body) ->
|
||||||
|
console.log "HTTP Request:" + JSON.stringify options if options.debug and not error
|
||||||
|
|
||||||
|
if responded
|
||||||
|
console.log "\t↳Already returned before." if options.debug
|
||||||
|
return
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
console.warn "\t↳Returned: error: #{error}"
|
||||||
|
options.error(error) if options.error?
|
||||||
|
else
|
||||||
|
console.log "\t↳Returned: statusCode #{response.statusCode}: #{if options.parse then JSON.stringify body else body}" if options.debug
|
||||||
|
options.success(body, response, status: response.statusCode) if options.success?
|
||||||
|
|
||||||
|
|
||||||
|
statusCode = response.statusCode if response?
|
||||||
|
options.complete(status: statusCode) if options.complete?
|
||||||
|
responded = true
|
||||||
|
|
||||||
|
$.extend = (deep, into, from) ->
|
||||||
|
copy = _.clone(from, deep);
|
||||||
|
if into
|
||||||
|
_.assign into, copy
|
||||||
|
copy = into
|
||||||
|
copy
|
||||||
|
|
||||||
|
$.isArray = (object) ->
|
||||||
|
_.isArray object
|
||||||
|
|
||||||
|
$.isPlainObject = (object) ->
|
||||||
|
_.isPlainObject object
|
||||||
|
|
||||||
|
|
||||||
|
do (setupLodash = this) ->
|
||||||
|
GLOBAL._ = require 'lodash'
|
||||||
|
_.str = require 'underscore.string'
|
||||||
|
_.string = _.str
|
||||||
|
_.mixin _.str.exports()
|
||||||
|
|
||||||
|
|
||||||
|
# load Backbone. Needs hooked loader to reroute underscore to lodash.
|
||||||
|
hook()
|
||||||
|
GLOBAL.Backbone = require bowerComponentsPath + 'backbone/backbone'
|
||||||
|
unhook()
|
||||||
|
Backbone.$ = $
|
||||||
|
|
||||||
|
require bowerComponentsPath + 'validated-backbone-mediator/backbone-mediator'
|
||||||
|
# Instead of mediator, dummy might be faster yet suffice?
|
||||||
|
#Mediator = class Mediator
|
||||||
|
# publish: (id, object) ->
|
||||||
|
# console.Log "Published #{id}: #{object}"
|
||||||
|
# @subscribe: () ->
|
||||||
|
# @unsubscribe: () ->
|
||||||
|
|
||||||
|
GLOBAL.Aether = require 'aether'
|
||||||
|
|
||||||
|
# Set up new loader.
|
||||||
|
hook()
|
||||||
|
|
||||||
|
login = require './login.coffee' #should contain an object containing they keys 'username' and 'password'
|
||||||
|
|
||||||
|
|
||||||
|
#Login user and start the code.
|
||||||
|
$.ajax
|
||||||
|
url: '/auth/login'
|
||||||
|
type: "POST"
|
||||||
|
data: login
|
||||||
|
parse: true
|
||||||
|
error: (error) -> "Bad Error. Can't connect to server or something. " + error
|
||||||
|
success: (response) ->
|
||||||
|
console.log "User: " + response
|
||||||
|
GLOBAL.window.userObject = response # JSON.parse response
|
||||||
|
|
||||||
|
User = require 'models/User'
|
||||||
|
|
||||||
|
World = require 'lib/world/world'
|
||||||
|
LevelLoader = require 'lib/LevelLoader'
|
||||||
|
GoalManager = require 'lib/world/GoalManager'
|
||||||
|
|
||||||
|
SuperModel = require 'models/SuperModel'
|
||||||
|
|
||||||
|
log = require 'winston'
|
||||||
|
|
||||||
|
CocoClass = require 'lib/CocoClass'
|
||||||
|
|
||||||
|
Simulator = require 'lib/simulator/Simulator'
|
||||||
|
|
||||||
|
sim = new Simulator options
|
||||||
|
|
||||||
|
sim.fetchAndSimulateTask()
|
87
headless_client/test.js
Normal file
87
headless_client/test.js
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
module.exports = {
|
||||||
|
"messageGenerated": 1396792689279,
|
||||||
|
"sessions": [
|
||||||
|
{
|
||||||
|
"sessionID": "533a2c4893b95d9319a58049",
|
||||||
|
"submitDate": "2014-04-06T06:31:11.806Z",
|
||||||
|
"team": "humans",
|
||||||
|
"code": {
|
||||||
|
"ogre-base": {
|
||||||
|
"chooseAction": "// This is the code for your base. Decide which unit to build each frame.\n// Units you build will go into the this.built array.\n// Destroy the enemy base within 60 seconds!\n// Check out the Guide at the top for more info.\n\n// Choose your hero! You can only build one hero.\nvar hero;\n//hero = 'ironjaw'; // A leaping juggernaut hero, type 'brawler'.\nhero = 'yugargen'; // A devious spellcaster hero, type 'shaman'.\nif(hero && !this.builtHero) {\n this.builtHero = this.build(hero);\n return;\n}\n\n// Munchkins are weak melee units with 1.25s build cooldown.\n// Throwers are fragile, deadly ranged units with 2.5s build cooldown.\nvar buildOrder = ['munchkin', 'thrower', 'munchkin', 'thrower', 'munchkin', 'thrower'];\nvar type = buildOrder[this.built.length % buildOrder.length];\n//this.say('Unit #' + this.built.length + ' will be a ' + type);\nthis.build(type);\n//this.say(\"Move\", {to:{x:20, y:30}});{x: 68, y: 29}{x: 70, y: 30}"
|
||||||
|
},
|
||||||
|
"programmable-shaman": {
|
||||||
|
"chooseAction": "if (this.hero !== undefined) {\n this.hero = this.getNearest(enemy);\n}\n// Shamans are spellcasters with a weak magic attack\n// and three spells: 'shrink', 'grow', and 'poison-cloud'.\n// Shrink: target has 2/3 health, 1.5x speed for 5s.\n// Grow: target has double health, half speed for 5s.\n// Once per match, she can cast poison cloud, which does\n// 5 poison dps for 10s to enemies in a 10m radius.\nvar right = 0;\nif(right === 0){this.move({x: 70, y: 40});\n}\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar friend = this.getNearest(friends);\n\nif(this.canCast('shrink', enemy)) \n{\n this.castShrink(enemy);\n}\nelse\n{\n this.castGrow(friend);\n}\n\nvar enemiesinpoisonrange = 0;\nfor (var i = 0; i < enemies.lenght; ++i) {\n var enemi = enemies[i];\n if (this.distance(enemi) <= 10) {\n enemiesinpoisonrange++;\n }\n}\nif (enemiesinpoisonrange >= 7) {\n this.castPoisonCloud(enemy);\n}\n//if (this.distance(ogrebase) > 10) {\n// this.move({x: 70, y: 30});\n//}\n//this.say(\"Defend!\", {targetPos: {x: 45, y: 30}});\n\n//this.say(\"Defend!\", {targetPos: {x: 35, y: 30}});\n\n//this.say(\"Defend!\", {targetPos: {x: 25, y: 30}});\n\n//this.say(\"Attack!\", {to:{x:20, y:30}});\n\n\n// Which one do you do at any given time? Only the last called action happens.\n//if(this.canCast('shrink', enemy)) this.castShrink(enemy);\n//if(this.canCast('grow', friend)) this.castGrow(friend);\n//if(this.canCast('poison-cloud', enemy)) this.castPoisonCloud(enemy);\n//this.attack(enemy);\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 45, y: 30}});\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 50, y: 40});"
|
||||||
|
},
|
||||||
|
"programmable-brawler": {
|
||||||
|
"chooseAction": "// The Brawler is a huge melee hero with mighty mass.\n// this.throw() hurls an enemy behind him.\n// this.jumpTo() leaps to a target within 20m every 10s.\n// this.stomp() knocks everyone away, once per match.\n\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar friend = this.getNearest(friends);\n\n// Which one do you do at any given time? Only the last called action happens.\n//if(!this.getCooldown('jump')) this.jumpTo(enemy.pos);\n//if(!this.getCooldown('stomp') && this.distance(enemy) < 10) this.stomp();\n//if(!this.getCooldown('throw')) this.throw(enemy);\n//this.attack(enemy);\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 60, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 50, y: 40});\n\n// You can store state on this across frames:\n//this.lastHealth = this.health;{x: 68, y: 29}{x: 70, y: 30}"
|
||||||
|
},
|
||||||
|
"programmable-librarian": {
|
||||||
|
"chooseAction": "var enemies = this.getEnemies();\nif (enemies.length === 0)\n return;\nvar enemy = this.getNearest(enemies);\nvar friends = this.getFriends();\nvar friend = this.getNearest(friends);\nvar archer = this.getFriends(type, \"archer\");\nvar soldier = this.getFriends(type, \"soldier\");\nvar hero = this.getFriends(type, \"hushbaum\");\nvar rand = Math.random();\nvar xmove;\nvar ymove;\nfor (var i = 0; i < enemies.length / 3; i += 1) {\n var e = enemies[i];\n var ehealth = Math.floor(e.health);\n if (this.canCast(\"haste\", friend)) {\n this.say(\"Godspeed \" + friend.id + \"!\");\n this.castHaste(friend);\n }\n if (this.canCast(\"haste\", this)) {\n this.say(\"I am Godspeed!\");\n this.castHaste(this);\n }\n if (this.canCast(\"slow\", e)) {\n this.say(\"Chill Out \" + e.id + \"!\");\n this.castSlow(e);\n }\n if (this.distance(e) < 45) {\n this.attack(e);\n this.say(\"Attacking \" + e.id + \" life is \" + ehealth + \".\");\n }\n if (this.health < this.maxHealth * 0.75) {\n if (this.pos.x > 20) {\n this.move({\n x: this.pos.x - 20,\n y: this.pos.y\n });\n } else {\n this.move({\n x: this.pos.x + 20,\n y: this.pos.y\n });\n }\n }\n if (this.canCast(\"regen\", this)) {\n this.castRegen(this);\n this.say(\"I won't die today bitch!\");\n }\n if (friend.health < friend.maxHealth * 0.5) {\n if (this.canCast(\"regen\", friend)) {\n this.say(\"You won't die today \" + friend.id + \".\");\n this.castRegen(friend);\n }\n }\n}\n;"
|
||||||
|
},
|
||||||
|
"programmable-tharin": {
|
||||||
|
"chooseAction": "// Tharin is a melee fighter with shield, warcry, and terrify skills.\n// this.shield() lets him take one-third damage while defending.\n// this.warcry() gives allies within 10m 30% haste for 5s, every 10s.\n// this.terrify() sends foes within 30m fleeing for 5s, once per match.\n\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar friend = this.getNearest(friends);\n\n// Which one do you do at any given time? Only the last called action happens.\n//if(!this.getCooldown('warcry')) this.warcry();\n//if(!this.getCooldown('terrify')) this.terrify();\n//this.shield();\n//this.attack(enemy);\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 40, y: 40});\n\n// You can store state on this across frames:\n//this.lastHealth = this.health;"
|
||||||
|
},
|
||||||
|
"human-base": {
|
||||||
|
"chooseAction": "// This is the code for your base. Decide which unit to build each frame.\n// Units you build will go into the this.built array.\n// Destroy the enemy base within 60 seconds!\n// Check out the Guide at the top for more info.\n\n// CHOOSE YOUR HERO! You can only build one hero.\nvar hero;\n//hero = 'tharin'; // A fierce knight with battlecry abilities.\nhero = 'hushbaum'; // A fiery spellcaster hero.\n\nif(hero && !this.builtHero) {\n this.builtHero = this.build(hero);\n return;\n}\n\n// Soldiers are hard-to-kill, low damage melee units with 2s build cooldown.\n// Archers are fragile but deadly ranged units with 2.5s build cooldown.\nvar buildOrder = ['soldier', 'soldier', 'archer', 'archer', 'soldier', 'soldier'];\nvar type = buildOrder[this.built.length % buildOrder.length];\nthis.say('Unit #' + this.built.length + ' will be a ' + type);\nthis.build(type);\n\n "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"teamSpells": {
|
||||||
|
"ogres": [
|
||||||
|
"programmable-brawler/chooseAction",
|
||||||
|
"programmable-shaman/chooseAction",
|
||||||
|
"ogre-base/chooseAction"
|
||||||
|
],
|
||||||
|
"humans": [
|
||||||
|
"programmable-librarian/chooseAction",
|
||||||
|
"programmable-tharin/chooseAction",
|
||||||
|
"human-base/chooseAction"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"levelID": "dungeon-arena",
|
||||||
|
"creator": "5338c38c4811eff221de2347",
|
||||||
|
"creatorName": "iC0DE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sessionID": "532a777c2042708b711a6c29",
|
||||||
|
"submitDate": "2014-03-20T05:45:54.691Z",
|
||||||
|
"team": "ogres",
|
||||||
|
"code": {
|
||||||
|
"ogre-base": {
|
||||||
|
"chooseAction": "// This is the code for your base. Decide which unit to build each frame.\n// Units you build will go into the this.built array.\n// Destroy the enemy base within 60 seconds!\n// Check out the Guide at the top for more info.\n\n// Choose your hero! You can only build one hero.\nvar hero;\n//hero = 'ironjaw'; // A leaping juggernaut hero, type 'brawler'.\nhero = 'yugargen'; // A devious spellcaster hero, type 'shaman'.\nif(hero && !this.builtHero) {\n this.builtHero = this.build(hero);\n return;\n}\n\n// Munchkins are weak melee units with 1.25s build cooldown.\n// Throwers are fragile, deadly ranged units with 2.5s build cooldown.\nvar buildOrder = ['munchkin', 'munchkin', 'munchkin', 'thrower'];\nvar type = buildOrder[this.built.length % buildOrder.length];\n//this.say('Unit #' + this.built.length + ' will be a ' + type);\nthis.build(type);"
|
||||||
|
},
|
||||||
|
"programmable-shaman": {
|
||||||
|
"chooseAction": "// Shamans are spellcasters with a weak magic attack\n// and three spells: 'shrink', 'grow', and 'poison-cloud'.\n// Shrink: target has 2/3 health, 1.5x speed for 5s.\n// Grow: target has double health, half speed for 5s.\n// Once per match, she can cast poison cloud, which does\n// 5 poison dps for 10s to enemies in a 10m radius.\n\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) {\n return; // Chill if all enemies are dead.\n}\nvar enemy = this.getNearest(enemies);\nvar friend = this.getNearest(friends);\nif (enemies.length > 5) {\n if(this.canCast('poison-cloud', enemy)) {\n this.castPoisonCloud(enemy);\n return;\n }\n}\n\nif (friends.length > 4) {\n this.attack(enemy); \n}\nfor (var i = 0; i < friends.length; ++i) {\n if (friends[i].health < 0) {\n continue;\n }\n if(friends[i].type == \"thrower\" && this.canCast('shrink', friends[i])) {\n this.castShrink(friends[i]);\n return;\n } \n if(friends[i].type == \"munchkin\" && this.canCast('grow', friends[i])) {\n this.castGrow(friends[i]);\n return;\n } \n}\n\n// Which one do you do at any given time? Only the last called action happens.\n//if(this.canCast('shrink', enemy)) this.castShrink(enemy);\n//if(this.canCast('grow', friend)) this.castGrow(friend);\n//if(this.canCast('poison-cloud', enemy)) this.castPoisonCloud(enemy);\n//this.attack(enemy);\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 60, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 50, y: 40});"
|
||||||
|
},
|
||||||
|
"programmable-brawler": {
|
||||||
|
"chooseAction": "// The Brawler is a huge melee hero with mighty mass.\n// this.throw() hurls an enemy behind him.\n// this.jumpTo() leaps to a target within 20m every 10s.\n// this.stomp() knocks everyone away, once per match.\n\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar friend = this.getNearest(friends);\n\n// Which one do you do at any given time? Only the last called action happens.\n//if(!this.getCooldown('jump')) this.jumpTo(enemy.pos);\n//if(!this.getCooldown('stomp') && this.distance(enemy) < 10) this.stomp();\n//if(!this.getCooldown('throw')) this.throw(enemy);\n//this.attack(enemy);\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 60, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 50, y: 40});\n\n// You can store state on this across frames:\n//this.lastHealth = this.health;"
|
||||||
|
},
|
||||||
|
"human-base": {
|
||||||
|
"chooseAction": "// This is the code for your base. Decide which unit to build each frame.\n// Units you build will go into the this.built array.\n// Destroy the enemy base within 60 seconds!\n// Check out the Guide at the top for more info.\n\n// CHOOSE YOUR HERO! You can only build one hero.\nvar hero;\nhero = 'tharin'; // A fierce knight with battlecry abilities.\n//hero = 'hushbaum'; // A fiery spellcaster hero.\n\nif(hero && !this.builtHero) {\n this.builtHero = this.build(hero);\n return;\n}\n\n// Soldiers are hard-to-kill, low damage melee units with 2s build cooldown.\n// Archers are fragile but deadly ranged units with 2.5s build cooldown.\nvar buildOrder = ['archer', 'archer', 'soldier', 'archer', 'soldier'];\nvar type = buildOrder[this.built.length % buildOrder.length];\n//this.say('Unit #' + this.built.length + ' will be a ' + type);\nthis.build(type);"
|
||||||
|
},
|
||||||
|
"programmable-tharin": {
|
||||||
|
"chooseAction": "this.findTypeInRange = function(units, type) {\n for (var i = 0; i < units.length; ++i) {\n var unit = units[i];\n if (unit.type === type && this.distance(unit) < 20)\n return unit;\n }\n return null;\n};\n\nthis.findType = function(units, type) {\n for (var i = 0; i < units.length; ++i) {\n var unit = units[i];\n if (unit.type === type)\n return unit;\n }\n return null;\n};\n\nthis.findHeroInRange = function(units, range) {\n for (var i = 0; i < units.length; ++i) {\n var unit = units[i];\n if ((unit.type === 'shaman' || unit.type === 'brawler') && this.distance(unit) < range)\n return unit;\n }\n return null;\n};\n\n// Tharin is a melee fighter with shield, warcry, and terrify skills.\n// this.shield() lets him take one-third damage while defending.\n// this.warcry() gives allies within 10m 30% haste for 5s, every 10s.\n// this.terrify() sends foes within 30m fleeing for 5s, once per match.\n\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\n\n//Enemies\nvar enemyBase = this.findType(enemies, 'base');\nvar brawler = this.findTypeInRange(enemies, 'brawler');\nvar shaman = this.findTypeInRange(enemies, 'shaman');\n\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar friend = this.getNearest(friends);\n\n// Which one do you do at any given time? Only the last called action happens.\n//if(!this.getCooldown('warcry')) this.warcry();\n//if(!this.getCooldown('terrify')) this.terrify();\n//this.shield();\n\nif((brawler || shaman) && !this.attackTime)\n{\n this.attackTime = true;\n if(brawler)\n this.say(\"Attack!\", {target: brawler});\n else if(shaman)\n this.say(\"Attack!\", {target: shaman});\n}\nelse if(this.health < 15 && this.getCooldown('terrify'))\n{\n this.terrify();\n}\nelse if(this.findHeroInRange(enemies, 30) && this.getCooldown('terrify'))\n{\n this.terrify();\n}\nelse if(this.health < 25)\n{\n this.shield();\n}\nelse if(brawler && this.distance(brawler) <=10)\n{\n this.attack(brawler);\n}\nelse\n{\n this.attack(enemy);\n}\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 40, y: 40});\n\n// You can store state on this across frames:\n//this.lastHealth = this.health;"
|
||||||
|
},
|
||||||
|
"programmable-librarian": {
|
||||||
|
"chooseAction": "// The Librarian is a spellcaster with a fireball attack\n// plus three useful spells: 'slow', 'regen', and 'haste'.\n// Slow makes a target move and attack at half speed for 5s.\n// Regen makes a target heal 10 hp/s for 10s.\n// Haste speeds up a target by 4x for 5s, once per match.\n\nvar friends = this.getFriends();\nvar enemies = this.getEnemies();\nif (enemies.length === 0) return; // Chill if all enemies are dead.\nvar enemy = this.getNearest(enemies);\nvar friend = this.getNearest(friends);\n\n// Which one do you do at any given time? Only the last called action happens.\n//if(this.canCast('slow', enemy)) this.castSlow(enemy);\n//if(this.canCast('regen', friend)) this.castRegen(friend);\n//if(this.canCast('haste', friend)) this.castHaste(friend);\n//this.attack(enemy);\n\n// You can also command your troops with this.say():\n//this.say(\"Defend!\", {targetPos: {x: 30, y: 30}}));\n//this.say(\"Attack!\", {target: enemy});\n//this.say(\"Move!\", {targetPos: {x: 50, y: 40});"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"teamSpells": {
|
||||||
|
"ogres": [
|
||||||
|
"programmable-brawler/chooseAction",
|
||||||
|
"programmable-shaman/chooseAction",
|
||||||
|
"ogre-base/chooseAction"
|
||||||
|
],
|
||||||
|
"humans": [
|
||||||
|
"programmable-librarian/chooseAction",
|
||||||
|
"programmable-tharin/chooseAction",
|
||||||
|
"human-base/chooseAction"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"levelID": "dungeon-arena",
|
||||||
|
"creator": "53291a80b112e7240f324667",
|
||||||
|
"creatorName": "Imbal Oceanrage"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"taskID": "53415d71942d00aa43dbf3e9",
|
||||||
|
"receiptHandle": "cd50e44db7dbd4cc0bcce047aa822ba2fe3556cf"
|
||||||
|
}
|
209
headless_client/worker_world.coffee
Normal file
209
headless_client/worker_world.coffee
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
# function to use inside a webworker.
|
||||||
|
# This function needs to run inside an environment that has a 'self'.
|
||||||
|
# This specific worker is targeted towards the node.js headless_client environment.
|
||||||
|
|
||||||
|
JASON = require 'jason'
|
||||||
|
fs = require 'fs'
|
||||||
|
|
||||||
|
betterConsole = () ->
|
||||||
|
|
||||||
|
self.logLimit = 200;
|
||||||
|
self.logsLogged = 0;
|
||||||
|
|
||||||
|
self.transferableSupported = () -> true
|
||||||
|
|
||||||
|
self.console = log: ->
|
||||||
|
if self.logsLogged++ is self.logLimit
|
||||||
|
self.postMessage
|
||||||
|
type: "console-log"
|
||||||
|
args: ["Log limit " + self.logLimit + " reached; shutting up."]
|
||||||
|
id: self.workerID
|
||||||
|
|
||||||
|
else if self.logsLogged < self.logLimit
|
||||||
|
args = [].slice.call(arguments)
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
while i < args.length
|
||||||
|
args[i] = args[i].toString() if args[i].constructor.className is "Thang" or args[i].isComponent if args[i] and args[i].constructor
|
||||||
|
++i
|
||||||
|
try
|
||||||
|
self.postMessage
|
||||||
|
type: "console-log"
|
||||||
|
args: args
|
||||||
|
id: self.workerID
|
||||||
|
|
||||||
|
catch error
|
||||||
|
self.postMessage
|
||||||
|
type: "console-log"
|
||||||
|
args: [
|
||||||
|
"Could not post log: " + args
|
||||||
|
error.toString()
|
||||||
|
error.stack
|
||||||
|
error.stackTrace
|
||||||
|
]
|
||||||
|
id: self.workerID
|
||||||
|
|
||||||
|
# so that we don't crash when debugging statements happen
|
||||||
|
self.console.error = self.console.info = self.console.log
|
||||||
|
GLOBAL.console = console = self.console
|
||||||
|
self.console
|
||||||
|
|
||||||
|
|
||||||
|
work = () ->
|
||||||
|
console.log "starting..."
|
||||||
|
|
||||||
|
console.log = ->
|
||||||
|
|
||||||
|
World = self.require('lib/world/world');
|
||||||
|
GoalManager = self.require('lib/world/GoalManager');
|
||||||
|
|
||||||
|
self.cleanUp = ->
|
||||||
|
self.world = null
|
||||||
|
self.goalManager = null
|
||||||
|
self.postedErrors = {}
|
||||||
|
self.t0 = null
|
||||||
|
self.logsLogged = 0
|
||||||
|
|
||||||
|
self.runWorld = (args) ->
|
||||||
|
console.log "Running world inside worker."
|
||||||
|
self.postedErrors = {}
|
||||||
|
self.t0 = new Date()
|
||||||
|
self.postedErrors = false
|
||||||
|
self.logsLogged = 0
|
||||||
|
|
||||||
|
try
|
||||||
|
self.world = new World(args.worldName, args.userCodeMap)
|
||||||
|
self.world.loadFromLevel args.level, true if args.level
|
||||||
|
self.goalManager = new GoalManager(self.world)
|
||||||
|
self.goalManager.setGoals args.goals
|
||||||
|
self.goalManager.setCode args.userCodeMap
|
||||||
|
self.goalManager.worldGenerationWillBegin()
|
||||||
|
self.world.setGoalManager self.goalManager
|
||||||
|
catch error
|
||||||
|
console.log "There has been an error inside the worker."
|
||||||
|
self.onWorldError error
|
||||||
|
return
|
||||||
|
Math.random = self.world.rand.randf # so user code is predictable
|
||||||
|
console.log "Loading frames."
|
||||||
|
|
||||||
|
self.postMessage type: "start-load-frames"
|
||||||
|
|
||||||
|
|
||||||
|
self.world.loadFrames self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress, true
|
||||||
|
|
||||||
|
|
||||||
|
self.onWorldLoaded = onWorldLoaded = ->
|
||||||
|
self.postMessage type: "end-load-frames"
|
||||||
|
|
||||||
|
self.goalManager.worldGenerationEnded()
|
||||||
|
t1 = new Date()
|
||||||
|
diff = t1 - self.t0
|
||||||
|
transferableSupported = self.transferableSupported()
|
||||||
|
try
|
||||||
|
serialized = serializedWorld: undefined # self.world.serialize()
|
||||||
|
transferableSupported = false
|
||||||
|
catch error
|
||||||
|
console.log "World serialization error:", error.toString() + "\n" + error.stack or error.stackTrace
|
||||||
|
t2 = new Date()
|
||||||
|
|
||||||
|
# console.log("About to transfer", serialized.serializedWorld.trackedPropertiesPerThangValues, serialized.transferableObjects);
|
||||||
|
try
|
||||||
|
if transferableSupported
|
||||||
|
self.postMessage
|
||||||
|
type: "new-world"
|
||||||
|
serialized: serialized.serializedWorld
|
||||||
|
goalStates: self.goalManager.getGoalStates()
|
||||||
|
, serialized.transferableObjects
|
||||||
|
else
|
||||||
|
self.postMessage
|
||||||
|
type: "new-world"
|
||||||
|
serialized: serialized.serializedWorld
|
||||||
|
goalStates: self.goalManager.getGoalStates()
|
||||||
|
|
||||||
|
catch error
|
||||||
|
console.log "World delivery error:", error.toString() + "\n" + error.stack or error.stackTrace
|
||||||
|
t3 = new Date()
|
||||||
|
console.log "And it was so: (" + (diff / self.world.totalFrames).toFixed(3) + "ms per frame,", self.world.totalFrames, "frames)\nSimulation :", diff + "ms \nSerialization:", (t2 - t1) + "ms\nDelivery :", (t3 - t2) + "ms"
|
||||||
|
self.cleanUp()
|
||||||
|
|
||||||
|
|
||||||
|
self.onWorldError = onWorldError = (error) ->
|
||||||
|
self.postMessage type: "end-load-frames"
|
||||||
|
if error instanceof Aether.problems.UserCodeProblem
|
||||||
|
#console.log "Aether userCodeProblem occured."
|
||||||
|
unless self.postedErrors[error.key]
|
||||||
|
problem = error.serialize()
|
||||||
|
self.postMessage
|
||||||
|
type: "user-code-problem"
|
||||||
|
problem: problem
|
||||||
|
|
||||||
|
self.postedErrors[error.key] = problem
|
||||||
|
else
|
||||||
|
console.log "Non-UserCodeError:", error.toString() + "\n" + error.stack or error.stackTrace
|
||||||
|
self.cleanUp()
|
||||||
|
|
||||||
|
self.onWorldLoadProgress = onWorldLoadProgress = (progress) ->
|
||||||
|
#console.log "Worker onWorldLoadProgress"
|
||||||
|
self.postMessage
|
||||||
|
type: "world-load-progress-changed"
|
||||||
|
progress: progress
|
||||||
|
|
||||||
|
self.abort = abort = ->
|
||||||
|
#console.log "Abort called for worker."
|
||||||
|
if self.world and self.world.name
|
||||||
|
#console.log "About to abort:", self.world.name, typeof self.world.abort
|
||||||
|
self.world.abort() if typeof self.world isnt "undefined"
|
||||||
|
self.world = null
|
||||||
|
self.postMessage type: "abort"
|
||||||
|
self.cleanUp()
|
||||||
|
|
||||||
|
self.reportIn = reportIn = ->
|
||||||
|
console.log "Reporting in."
|
||||||
|
self.postMessage type: "reportIn"
|
||||||
|
|
||||||
|
self.addEventListener "message", (event) ->
|
||||||
|
#console.log JSON.stringify event
|
||||||
|
self[event.data.func] event.data.args
|
||||||
|
|
||||||
|
self.postMessage type: "worker-initialized"
|
||||||
|
|
||||||
|
world = fs.readFileSync "./public/javascripts/world.js", 'utf8'
|
||||||
|
|
||||||
|
|
||||||
|
#window.BOX2D_ENABLED = true;
|
||||||
|
|
||||||
|
newConsole = "newConsole = #{}JASON.stringify newConsole}()";
|
||||||
|
|
||||||
|
ret = """
|
||||||
|
|
||||||
|
GLOBAL = root = window = self;
|
||||||
|
GLOBAL.window = window;
|
||||||
|
|
||||||
|
self.workerID = "Worker";
|
||||||
|
|
||||||
|
console = #{JASON.stringify betterConsole}();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// the world javascript file
|
||||||
|
#{world};
|
||||||
|
|
||||||
|
// Don't let user generated code access stuff from our file system!
|
||||||
|
self.importScripts = importScripts = null;
|
||||||
|
self.native_fs_ = native_fs_ = null;
|
||||||
|
|
||||||
|
// the actual function
|
||||||
|
#{JASON.stringify work}();
|
||||||
|
}catch (error) {
|
||||||
|
self.postMessage({"type": "console-log", args: ["An unhandled error occured: ", error.toString(), error.stack], id: -1});
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
#console = #{JASON.stringify createConsole}();
|
||||||
|
#
|
||||||
|
# console.error = console.info = console.log;
|
||||||
|
#self.console = console;
|
||||||
|
#GLOBAL.console = console;
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = new Function(ret)
|
|
@ -62,7 +62,11 @@
|
||||||
"sendwithus": "2.0.x",
|
"sendwithus": "2.0.x",
|
||||||
"aws-sdk": "~2.0.0",
|
"aws-sdk": "~2.0.0",
|
||||||
"bayesian-battle": "0.0.x",
|
"bayesian-battle": "0.0.x",
|
||||||
"redis": ""
|
"redis": "",
|
||||||
|
"webworker-threads": "~0.4.11",
|
||||||
|
"node-gyp": "~0.13.0",
|
||||||
|
"aether": "~0.1.18",
|
||||||
|
"JASON": "~0.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"jade": "0.33.x",
|
"jade": "0.33.x",
|
||||||
|
|
Reference in a new issue