mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-14 07:00:01 -04:00
Merge branch 'master' of https://github.com/codecombat/codecombat
This commit is contained in:
commit
9019368d1d
30 changed files with 154 additions and 253 deletions
16
README.md
16
README.md
|
@ -1,8 +1,20 @@
|
|||
CodeCombat
|
||||
==========
|
||||
|
||||
CodeCombat is a multiplayer programming game for learning how to code. See the [Archmage developer wiki](https://github.com/codecombat/codecombat/wiki) for all information.
|
||||

|
||||
|
||||
We just open-sourced everything on 2014-01-03 as a preview release for our [Archmages](http://codecombat.com/contribute#archmage) who have been waiting to contribute. We will announce it fully on Monday. Please poke around, add issues, work on issues, and have fun! We'd love to see as many contributors as possible this weekend, so no contribution is too small.
|
||||
CodeCombat is a multiplayer programming game for learning how to code. **See the [Archmage developer wiki](https://github.com/codecombat/codecombat/wiki) for a dev setup guide, extensive documentation, and much more.**
|
||||
|
||||
It's both a startup and a community project, completely open source under the [MIT and Creative Commons licenses](http://codecombat.com/legal). It's the largest open source [CoffeeScript](http://coffeescript.org/) project by lines of code, and since it's a game (with [really cool tech](https://github.com/codecombat/codecombat/wiki/Third-party-software-and-services)), it's really fun to hack on. Join us in teaching the world to code! Your contribution will go on to show millions of players how cool programming can be.
|
||||
|
||||
### [Getting Started](https://github.com/codecombat/codecombat/wiki/Developer-environment)
|
||||
|
||||
We've made it easy to fork the project, run a simple script that'll install all the dependencies, and get a local copy of CodeCombat running right away on Mac, Linux, or Windows. See [the docs for details](https://github.com/codecombat/codecombat/wiki/Developer-environment).
|
||||
|
||||
### [Getting In Touch](https://github.com/codecombat/codecombat/wiki/Developer-organization)
|
||||
|
||||
Whether you're novice or pro, the CodeCombat team is ready to help you implement your ideas. Reach out on our forum, our issue tracker, or our developer chat room, or see the docs for [more on how to contribute](https://github.com/codecombat/codecombat/wiki/Developer-organization).
|
||||
|
||||
### [License](https://github.com/codecombat/codecombat/blob/master/LICENSE)
|
||||
|
||||
[MIT](https://github.com/codecombat/codecombat/blob/master/LICENSE) for the code, and [CC-BY](http://codecombat.com/legal) for the art and music. Please also [sign the CodeCombat contributor license agreement](http://codecombat.com/cla) so we can accept your pull requests. It is easy.
|
||||
|
|
|
@ -52,9 +52,10 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
'level-sprite-dialogue': 'onDialogue'
|
||||
'level-sprite-clear-dialogue': 'onClearDialogue'
|
||||
'level-set-letterbox': 'onSetLetterbox'
|
||||
'surface:ticked': 'onSurfaceTicked'
|
||||
|
||||
constructor: (@thangType, options) ->
|
||||
super()
|
||||
super()
|
||||
@options = _.extend(_.cloneDeep(@options), options)
|
||||
@setThang @options.thang
|
||||
console.error @toString(), "has no ThangType!" unless @thangType
|
||||
|
@ -63,6 +64,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@labels = {}
|
||||
@actions = @thangType.getActions()
|
||||
@buildFromSpriteSheet @buildSpriteSheet()
|
||||
@ticker = 0
|
||||
|
||||
destroy: ->
|
||||
super()
|
||||
|
@ -112,6 +114,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@playNextAction()
|
||||
|
||||
onActionEnd: (e) => @playNextAction()
|
||||
onSurfaceTicked: -> @ticker += 1
|
||||
|
||||
playNextAction: ->
|
||||
@playAction(@actionQueue.splice(0,1)[0]) if @actionQueue.length
|
||||
|
@ -147,6 +150,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
|
||||
updatePosition: ->
|
||||
return unless @thang?.pos and @options.camera?
|
||||
if @thang.bobHeight
|
||||
@thang.pos.z = @thang.pos.z + (Math.sin @ticker / @thang.bobTime) * 0.1 * @thang.bobHeight
|
||||
[p0, p1] = [@lastPos, @thang.pos]
|
||||
return if p0 and p0.x is p1.x and p0.y is p1.y and p0.z is p1.z and not @options.camera.tweeningZoomTo
|
||||
wop = x: p1.x, y: p1.y, z: if @thang.isLand then 0 else p1.z - @thang.depth / 2
|
||||
|
@ -422,4 +427,4 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
name = AudioPlayer.nameForSoundReference sound
|
||||
instance = createjs.Sound.play name, "none", delay, 0, 0, volume
|
||||
#console.log @thang?.id, "played sound", name, "with delay", delay, "volume", volume, "and got sound instance", instance
|
||||
instance
|
||||
instance
|
|
@ -21,8 +21,7 @@ module.exports = class WizardSprite extends IndieSprite
|
|||
subscriptions:
|
||||
'bus:player-states-changed': 'onPlayerStatesChanged'
|
||||
'me:synced': 'onMeSynced'
|
||||
'surface:sprite-selected': 'onSpriteSelected'
|
||||
'surface:ticked': 'onSurfaceTicked'
|
||||
'surface:sprite-selected': 'onSpriteSelected'
|
||||
'echo-self-wizard-sprite': 'onEchoSelfWizardSprite'
|
||||
'echo-all-wizard-sprites': 'onEchoAllWizardSprites'
|
||||
|
||||
|
@ -102,8 +101,7 @@ module.exports = class WizardSprite extends IndieSprite
|
|||
onEchoSelfWizardSprite: (e) -> e.payload = @ if @isSelf
|
||||
onEchoAllWizardSprites: (e) -> e.payload.push @
|
||||
defaultPos: -> x: 35, y: 24, z: @thang.depth / 2 + @spriteZOffset
|
||||
getZOffset: -> @thang.depth / 2 + @spriteZOffset + Math.sin @ticker / 20 # Cloud bobbing.
|
||||
onSurfaceTicked: -> @ticker += 1
|
||||
getZOffset: -> @thang.depth / 2 + @spriteZOffset + Math.sin @ticker / 20 # Cloud bobbing.
|
||||
move: (pos, duration) -> @setTarget(pos, duration)
|
||||
|
||||
setTarget: (newTarget, duration) ->
|
||||
|
|
|
@ -72,7 +72,7 @@ module.exports = nativeDescription: "English", englishDescription: "English", tr
|
|||
|
||||
contact:
|
||||
contact_us: "Contact CodeCombat"
|
||||
welcome: "Good to hear from you! Use this form to send us email."
|
||||
welcome: "Good to hear from you! Use this form to send us email. "
|
||||
contribute_prefix: "If you're interested in contributing, check out our "
|
||||
contribute_page: "contribute page"
|
||||
contribute_suffix: "!"
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
#contribute-view
|
||||
|
||||
#intro
|
||||
margin-right: 20%
|
||||
|
||||
|
||||
#homepage_screenshot
|
||||
margin: 20px 0px
|
||||
.signature
|
||||
text-align: right
|
||||
|
||||
|
||||
a
|
||||
cursor: pointer
|
||||
|
||||
|
@ -15,8 +12,8 @@
|
|||
float: left
|
||||
width: 150px
|
||||
margin: 10px 10px 20px 20px
|
||||
padding-top: 30px
|
||||
|
||||
padding-top: 65px
|
||||
|
||||
#contribute-nav
|
||||
float: left
|
||||
max-width: 20%
|
||||
|
@ -27,14 +24,18 @@
|
|||
li
|
||||
float: none
|
||||
width: 100%
|
||||
|
||||
|
||||
#contribute-main
|
||||
margin-left: 25%
|
||||
padding: 40px
|
||||
box-sizing: border-box
|
||||
|
||||
|
||||
h3
|
||||
padding-top: 30px
|
||||
|
||||
padding-top: 70px
|
||||
|
||||
.well
|
||||
padding: 5px 5px 5px 30px
|
||||
|
||||
.saved-notification
|
||||
display: none
|
||||
float: right
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
hr
|
||||
|
||||
if me.get('anonymous')
|
||||
p
|
||||
h1
|
||||
| Either
|
||||
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="nav.sign_up") create an account
|
||||
| or
|
||||
|
|
|
@ -40,8 +40,7 @@ block content
|
|||
li Artisans - Sootn, Aftermath, mcdavid1991
|
||||
li Scribes - Ryan Faidley
|
||||
li Adventurers - Kieizroe, (...)
|
||||
li Archmages - David Golds, Zach Martin
|
||||
|
||||
li Archmages - David Golds, Zach Martin, Tom Steinbrecher, Mischa Lewis-Norelle, Sébastien Moratinos
|
||||
|
||||
div#contribute-main
|
||||
div#intro
|
||||
|
@ -59,10 +58,12 @@ block content
|
|||
| We can't and don't want to do that alone;
|
||||
| what makes projects like GitHub, Stack Overflow and Linux great are the people who
|
||||
| use them and build on them.
|
||||
| To that end, we aim to provide as many ways as possible for you to take part and
|
||||
| To that end,
|
||||
a(href="https://github.com/codecombat/codecombat") CodeCombat is totally open source
|
||||
| , and we aim to provide as many ways as possible for you to take part and
|
||||
| make this project as much yours as ours.
|
||||
p We hope you'll join our party!
|
||||
p.signature - Nick, George and Scott
|
||||
p.signature - Nick, George, Scott, Michael, and Jeremy
|
||||
hr
|
||||
|
||||
if me.attributes.anonymous
|
||||
|
@ -72,8 +73,6 @@ block content
|
|||
a(data-toggle="coco-modal", data-target="modal/signup") create an account
|
||||
| first .
|
||||
|
||||
h3 Changes are saved automatically when you toggle checkboxes.
|
||||
|
||||
#archmage
|
||||
.class_image
|
||||
img(src="/images/pages/contribute/archmage.png", alt="")
|
||||
|
@ -85,13 +84,7 @@ block content
|
|||
| and server administration to user facing design and interface building.
|
||||
| There's a lot to do, and if you're an experienced programmer with a hankering
|
||||
| to really dive into the nitty-gritty of CodeCombat, this class might be for you.
|
||||
|
||||
p Right now we have open-sourced two of our tools on the project:
|
||||
a(href="https://github.com/codecombat/aether") Aether
|
||||
| and
|
||||
a(href="https://github.com/codecombat/treema") Treema
|
||||
| . We are also open sourcing everything momentarily, so stay tuned for access to the main repo!
|
||||
| We would love to have your help building out the best programming game ever.
|
||||
| We would love to have your help building the best programming game ever.
|
||||
|
||||
h4 Class Attributes
|
||||
ul
|
||||
|
@ -107,17 +100,17 @@ block content
|
|||
|
||||
p
|
||||
| Anyone can help out! Just check out our
|
||||
a(title='GitHub', tabindex=-1) GitHub
|
||||
a(title='GitHub', href="https://github.com/codecombat/codecombat", tabindex=-1) GitHub
|
||||
| to get started, and check the box below to mark yourself as a brave Archmage.
|
||||
| Want to chat about what to do or how to get more deeply involved?
|
||||
a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact") Contact us
|
||||
| , tell us a little about yourself, what you've done and what you'd
|
||||
| be interested in working on. We'll go from there!
|
||||
|
||||
if !me.attributes.anonymous
|
||||
label.checkbox(for="developer").well
|
||||
input(type='checkbox', name="developer", id="developer")
|
||||
| Get emails on new coding opportunities and announcements.
|
||||
label.checkbox(for="developer").well
|
||||
input(type='checkbox', name="developer", id="developer")
|
||||
| Get emails on new coding opportunities and announcements.
|
||||
.saved-notification ✓ Saved
|
||||
|
||||
|
||||
#artisan
|
||||
|
@ -152,10 +145,10 @@ block content
|
|||
a(href="https://docs.google.com/document/d/117tMcL95T1KY8BDisr0iGi5Frb2ZvBJTC0us5hyQkJY/edit?usp=sharing") preliminary documentation
|
||||
| for more info, and please comment on it so we can make the whole system better.
|
||||
|
||||
if !me.attributes.anonymous
|
||||
label.checkbox(for="level_creator").well
|
||||
input(type='checkbox', name="level_creator", id="level_creator")
|
||||
| Get emails on level editor updates and announcements.
|
||||
label.checkbox(for="level_creator").well
|
||||
input(type='checkbox', name="level_creator", id="level_creator")
|
||||
| Get emails on level editor updates and announcements.
|
||||
.saved-notification ✓ Saved
|
||||
|
||||
|
||||
#adventurer
|
||||
|
@ -192,10 +185,10 @@ block content
|
|||
a(href="https://plus.google.com/115285980638641924488/posts") Google+
|
||||
| , so if you prefer to be notified those ways, sign up there!
|
||||
|
||||
if !me.attributes.anonymous
|
||||
label.checkbox(for="tester").well
|
||||
input(type='checkbox', name="tester", id="tester")
|
||||
| Get emails when there are new levels to test.
|
||||
label.checkbox(for="tester").well
|
||||
input(type='checkbox', name="tester", id="tester")
|
||||
| Get emails when there are new levels to test.
|
||||
.saved-notification ✓ Saved
|
||||
|
||||
|
||||
#scribe
|
||||
|
@ -224,10 +217,10 @@ block content
|
|||
| , tell us a little about yourself, your experience with programming and
|
||||
| what sort of things you'd like to write about. We'll go from there!
|
||||
|
||||
if !me.attributes.anonymous
|
||||
label.checkbox(for="article_editor").well
|
||||
input(type='checkbox', name="article_editor", id="article_editor")
|
||||
| Get emails about article writing announcements.
|
||||
label.checkbox(for="article_editor").well
|
||||
input(type='checkbox', name="article_editor", id="article_editor")
|
||||
| Get emails about article writing announcements.
|
||||
.saved-notification ✓ Saved
|
||||
|
||||
|
||||
|
||||
|
@ -257,10 +250,10 @@ block content
|
|||
| , so check it out and add things for your language. Also, check this box below to
|
||||
| keep up-to-date on new internationalization developments!
|
||||
|
||||
if !me.attributes.anonymous
|
||||
label.checkbox(for="translator").well
|
||||
input(type='checkbox', name="translator", id="translator")
|
||||
| Get emails about i18n developments and levels to translate.
|
||||
label.checkbox(for="translator").well
|
||||
input(type='checkbox', name="translator", id="translator")
|
||||
| Get emails about i18n developments and levels to translate.
|
||||
.saved-notification ✓ Saved
|
||||
|
||||
|
||||
#ambassador
|
||||
|
@ -293,10 +286,10 @@ block content
|
|||
| solving levels can summon higher level wizards to help them.
|
||||
| This will be a great way for ambassadors to do their thing. We'll keep you posted!
|
||||
|
||||
if !me.attributes.anonymous
|
||||
label.checkbox(for="support").well
|
||||
input(type='checkbox', name="support", id="support")
|
||||
| Get emails on support updates and multiplayer developments.
|
||||
label.checkbox(for="support").well
|
||||
input(type='checkbox', name="support", id="support")
|
||||
| Get emails on support updates and multiplayer developments.
|
||||
.saved-notification ✓ Saved
|
||||
|
||||
|
||||
#counselor
|
||||
|
|
|
@ -77,13 +77,13 @@ module.exports = class SettingsView extends View
|
|||
getSubscriptions: ->
|
||||
inputs = $('#email-pane input[type="checkbox"]', @$el)
|
||||
inputs = ($(i) for i in inputs)
|
||||
subs = (i.attr('name') for i in inputs when i.attr('checked'))
|
||||
subs = (i.attr('name') for i in inputs when i.prop('checked'))
|
||||
subs = (s.replace('email_', '') for s in subs)
|
||||
subs
|
||||
|
||||
toggleEmailSubscriptions: =>
|
||||
subs = @getSubscriptions()
|
||||
$('#email-pane input[type="checkbox"]', @$el).attr('checked', not Boolean(subs.length))
|
||||
$('#email-pane input[type="checkbox"]', @$el).prop('checked', not Boolean(subs.length))
|
||||
@save()
|
||||
|
||||
save: =>
|
||||
|
|
|
@ -5,17 +5,17 @@ template = require 'templates/cla'
|
|||
module.exports = class CLAView extends View
|
||||
id: "cla-view"
|
||||
template: template
|
||||
|
||||
|
||||
events:
|
||||
'click #agreement-button': 'onAgree'
|
||||
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
c.signedOn = moment(me.get('signedCLA')).format('LLLL') if me.get('signedCLA')
|
||||
c
|
||||
|
||||
|
||||
onAgree: ->
|
||||
@$el.find('#agreement-button').attr('disabled', true).text('Saving')
|
||||
@$el.find('#agreement-button').prop('disabled', true).text('Saving')
|
||||
$.ajax({
|
||||
url: "/db/user/me/agreeToCLA"
|
||||
data: { 'githubUsername': @$el.find('#github-username').val() }
|
||||
|
@ -23,9 +23,9 @@ module.exports = class CLAView extends View
|
|||
success: @onAgreeSucceeded
|
||||
error: @onAgreeFailed
|
||||
})
|
||||
|
||||
|
||||
onAgreeSucceeded: =>
|
||||
@$el.find('#agreement-button').text('Success')
|
||||
|
||||
onAgreeFailed: =>
|
||||
@$el.find('#agreement-button').text('Failed')
|
||||
@$el.find('#agreement-button').text('Failed')
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
View = require 'views/kinds/RootView'
|
||||
template = require 'templates/contribute'
|
||||
{me} = require('lib/auth')
|
||||
{me} = require 'lib/auth'
|
||||
SignupModalView = require 'views/modal/signup_modal'
|
||||
|
||||
module.exports = class ContributeView extends View
|
||||
id: "contribute-view"
|
||||
|
@ -15,17 +16,20 @@ module.exports = class ContributeView extends View
|
|||
_.forEach checkboxes, (el) ->
|
||||
el = $(el)
|
||||
if el.attr('name') in me.get('emailSubscriptions')
|
||||
el.attr('checked', true)
|
||||
el.prop('checked', true)
|
||||
|
||||
onCheckboxChanged: (e) ->
|
||||
el = $(e.target)
|
||||
checked = el.attr('checked')
|
||||
checked = el.prop('checked')
|
||||
subscription = el.attr('name')
|
||||
subscriptions = me.get('emailSubscriptions')
|
||||
subscriptions = me.get('emailSubscriptions') ? []
|
||||
if checked and not (subscription in subscriptions)
|
||||
subscriptions.push(subscription)
|
||||
if me.get 'anonymous'
|
||||
@openModalView new SignupModalView()
|
||||
if not checked
|
||||
subscriptions = _.without subscriptions, subscription
|
||||
el.parent().find('.saved-notification').finish().show('fast').delay(3000).fadeOut(2000)
|
||||
|
||||
me.set('emailSubscriptions', subscriptions)
|
||||
me.save()
|
||||
|
|
|
@ -27,10 +27,10 @@ module.exports = class ThangTypeEditView extends View
|
|||
'click #upload-button': -> @$el.find('input#real-upload-button').click()
|
||||
'change #real-upload-button': 'animationFileChosen'
|
||||
'change #animations-select': 'showAnimation'
|
||||
|
||||
|
||||
subscriptions:
|
||||
'save-new-version': 'saveNewThangType'
|
||||
|
||||
|
||||
# init / render
|
||||
|
||||
constructor: (options, @thangTypeID) ->
|
||||
|
@ -160,7 +160,7 @@ module.exports = class ThangTypeEditView extends View
|
|||
@file = e.target.files[0]
|
||||
return unless @file
|
||||
return unless @file.type is 'text/javascript'
|
||||
@$el.find('#upload-button').val('disabled', true)
|
||||
@$el.find('#upload-button').prop('disabled', true)
|
||||
@reader = new FileReader()
|
||||
@reader.onload = @onFileLoad
|
||||
@reader.readAsText(@file)
|
||||
|
@ -205,7 +205,7 @@ module.exports = class ThangTypeEditView extends View
|
|||
movieClip.regX = -reg.x
|
||||
movieClip.regY = -reg.y
|
||||
@showDisplayObject(movieClip)
|
||||
|
||||
|
||||
getSpriteOptions: -> { resolutionFactor: @resolution, thang: @mockThang}
|
||||
|
||||
showSprite: (actionName) ->
|
||||
|
@ -215,14 +215,14 @@ module.exports = class ThangTypeEditView extends View
|
|||
@currentSprite?.destroy()
|
||||
@currentSprite = sprite
|
||||
@showDisplayObject(sprite.displayObject)
|
||||
|
||||
|
||||
updatePortrait: ->
|
||||
options = @getSpriteOptions()
|
||||
portrait = @thangType.getPortrait(options)
|
||||
return unless portrait
|
||||
portrait?.attr('id', 'portrait').addClass('img-polaroid')
|
||||
$('#portrait').replaceWith(portrait)
|
||||
|
||||
|
||||
showDisplayObject: (displayObject) ->
|
||||
@clearDisplayObject()
|
||||
displayObject.x = CENTER.x
|
||||
|
|
|
@ -57,7 +57,7 @@ module.exports = class CocoView extends Backbone.View
|
|||
@hidden = false
|
||||
@listenToShortcuts()
|
||||
view.didReappear() for id, view of @subviews
|
||||
|
||||
|
||||
# View Rendering
|
||||
|
||||
render: =>
|
||||
|
@ -86,7 +86,7 @@ module.exports = class CocoView extends Backbone.View
|
|||
# Modals
|
||||
|
||||
toggleModal: (e) ->
|
||||
if $(event.currentTarget).prop('target') is '_blank'
|
||||
if $(e.currentTarget).prop('target') is '_blank'
|
||||
return true
|
||||
# special handler for opening modals that are dynamically loaded, rather than static in the page. It works (or should work) like Bootstrap's modals, except use coco-modal for the data-toggle value.
|
||||
elem = $(e.target)
|
||||
|
@ -133,7 +133,7 @@ module.exports = class CocoView extends Backbone.View
|
|||
visibleModal.$el.addClass('hide')
|
||||
waitingModal = null
|
||||
@modalClosed()
|
||||
|
||||
|
||||
# Loading RootViews
|
||||
|
||||
showLoading: ($el=@$el) ->
|
||||
|
@ -148,7 +148,7 @@ module.exports = class CocoView extends Backbone.View
|
|||
@_lastLoading.find('.loading-screen').remove()
|
||||
@_lastLoading.find('>').removeClass('hide')
|
||||
@_lastLoading = null
|
||||
|
||||
|
||||
# Loading ModalViews
|
||||
|
||||
enableModalInProgress: (modal) ->
|
||||
|
@ -194,7 +194,7 @@ module.exports = class CocoView extends Backbone.View
|
|||
return (tag is 'textarea' or (tag is 'input' and type in textInputTypes) or el.contentEditable in ["", "true"]) and not (el.readOnly or el.disabled)
|
||||
|
||||
# Subviews
|
||||
|
||||
|
||||
insertSubView: (view) ->
|
||||
@subviews[view.id].destroy() if view.id of @subviews
|
||||
@$el.find('#'+view.id).after(view.el).remove()
|
||||
|
|
|
@ -16,7 +16,7 @@ module.exports = class RootView extends CocoView
|
|||
events:
|
||||
"click #logout-button": "logoutAccount"
|
||||
'change .language-dropdown': 'showDiplomatSuggestionModal'
|
||||
|
||||
|
||||
shortcuts:
|
||||
'backspace, delete': 'preventBackspace'
|
||||
# 'backspace': 'preventBackspace'
|
||||
|
@ -56,7 +56,7 @@ module.exports = class RootView extends CocoView
|
|||
code2 isnt code and code2.split('-')[0] is code)
|
||||
for code, localeInfo of locale when not (code in genericCodes) or code is preferred
|
||||
$select.append(
|
||||
$("<option></option>").attr("value", code).text(localeInfo.nativeDescription))
|
||||
$("<option></option>").val(code).text(localeInfo.nativeDescription))
|
||||
$select.val(preferred).fancySelect()
|
||||
|
||||
showDiplomatSuggestionModal: ->
|
||||
|
|
|
@ -14,6 +14,6 @@ module.exports = class DiplomatSuggestionView extends View
|
|||
currentSubscriptions = me.get("emailSubscriptions")
|
||||
me.set("emailSubscriptions", currentSubscriptions.concat ["translator"]) if "translator" not in currentSubscriptions
|
||||
me.save()
|
||||
$("#email_translator").attr("checked", 1)
|
||||
$("#email_translator").prop("checked", 1)
|
||||
@hide()
|
||||
return
|
||||
|
|
|
@ -37,17 +37,20 @@ module.exports = class SignupModalView extends View
|
|||
@enableModalInProgress(modal) # TODO: part of forms
|
||||
|
||||
checkAge: (e) ->
|
||||
$("#signup-button", @$el).attr 'disabled', not $(e.target).attr('checked')
|
||||
$("#signup-button", @$el).prop 'disabled', not $(e.target).prop('checked')
|
||||
|
||||
createAccount: (e) =>
|
||||
forms.clearFormAlerts(@$el)
|
||||
userObject = forms.formToObject @$el
|
||||
delete userObject.subscribe
|
||||
delete userObject["confirm-age"]
|
||||
for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume"]
|
||||
for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume", "emailSubscriptions"]
|
||||
userObject[key] ?= val
|
||||
subscribe = @$el.find('#signup-subscribe').attr('checked')
|
||||
userObject.emailSubscriptions = if subscribe then ['announcement'] else []
|
||||
subscribe = @$el.find('#signup-subscribe').prop('checked')
|
||||
if subscribe
|
||||
(userObject.emailSubscriptions ?= []).push 'announcement'
|
||||
else
|
||||
userObject.emailSubscriptions = _.without (userObject.emailSubscriptions ? []), 'announcement'
|
||||
res = tv4.validateMultiple userObject, User.schema.attributes
|
||||
return forms.applyErrorsToForm(@$el, res.errors) unless res.valid
|
||||
window.tracker?.trackEvent 'Finished Signup'
|
||||
|
|
|
@ -8,7 +8,7 @@ module.exports = class MultiplayerModal extends View
|
|||
events:
|
||||
'click textarea': 'onClickLink'
|
||||
'change #multiplayer': 'updateLinkSection'
|
||||
|
||||
|
||||
constructor: (options) ->
|
||||
super(options)
|
||||
@session = options.session
|
||||
|
@ -21,19 +21,20 @@ module.exports = class MultiplayerModal extends View
|
|||
@session.id)
|
||||
c.multiplayer = @session.get('multiplayer')
|
||||
c
|
||||
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
@updateLinkSection()
|
||||
|
||||
|
||||
onClickLink: (e) =>
|
||||
e.target.select()
|
||||
|
||||
|
||||
updateLinkSection: =>
|
||||
multiplayer = @$el.find('#multiplayer').attr('checked')
|
||||
multiplayer = @$el.find('#multiplayer').prop('checked')
|
||||
la = @$el.find('#link-area')
|
||||
if multiplayer then la.show() else la.hide()
|
||||
true
|
||||
|
||||
onHidden: ->
|
||||
multiplayer = Boolean(@$el.find('#multiplayer').attr('checked'))
|
||||
@session.set('multiplayer', multiplayer)
|
||||
multiplayer = Boolean(@$el.find('#multiplayer').prop('checked'))
|
||||
@session.set('multiplayer', multiplayer)
|
||||
|
|
|
@ -73,7 +73,7 @@ module.exports = class CastButtonView extends View
|
|||
else
|
||||
s = $.i18n.t("play_level.tome_cast_button_cast", defaultValue: "Spell Cast")
|
||||
@castButton.text s
|
||||
@castButton.attr 'disabled', not castable
|
||||
@castButton.prop 'disabled', not castable
|
||||
|
||||
setAutocastDelay: (delay) ->
|
||||
#console.log "Set autocast delay to", delay
|
||||
|
|
|
@ -95,4 +95,4 @@ module.exports = class SpellListEntryView extends View
|
|||
disabled = not enabled
|
||||
# Should refactor the disabling list so we can target the spell list separately?
|
||||
# Should not call it 'editor' any more?
|
||||
@$el.toggleClass('disabled', disabled).find('*').attr('disabled', disabled)
|
||||
@$el.toggleClass('disabled', disabled).find('*').prop('disabled', disabled)
|
||||
|
|
|
@ -53,6 +53,8 @@ module.exports = class SpellView extends View
|
|||
@aceSession.setMode 'ace/mode/javascript'
|
||||
@aceSession.setWrapLimitRange null
|
||||
@aceSession.setUseWrapMode true
|
||||
@aceSession.setNewLineMode "unix"
|
||||
@aceSession.setUseSoftTabs true
|
||||
@ace.setTheme 'ace/theme/textmate'
|
||||
@ace.setDisplayIndentGuides false
|
||||
@ace.setShowPrintMargin false
|
||||
|
@ -79,7 +81,7 @@ module.exports = class SpellView extends View
|
|||
name: 'end-all-scripts'
|
||||
bindKey: {win: 'Escape', mac: 'Escape'}
|
||||
exec: -> Backbone.Mediator.publish 'level:escape-pressed'
|
||||
|
||||
|
||||
# TODO: These don't work on, for example, Danish keyboards. Figure out a more universal solution.
|
||||
# @ace.commands.addCommand
|
||||
# name: 'toggle-grid'
|
||||
|
|
|
@ -353,7 +353,7 @@ module.exports = class PlayLevelView extends View
|
|||
# Need to set this team stuff before the Tome loads... let's think about this with Scott.
|
||||
#@setTeam @world.teamForPlayer(@bus.countPlayers()) unless me.team
|
||||
#$('#multiplayer-team-selection').toggle(@world.playableTeams.length > 1)
|
||||
# .find('input').attr('checked', -> $(@).val() is me.team)
|
||||
# .find('input').prop('checked', -> $(@).val() is me.team)
|
||||
# .bind('change', @setTeam)
|
||||
|
||||
onSessionWillSave: (e) ->
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
# full script path
|
||||
_scriptDir="$(cd "$(dirname "$0")" && pwd -P)"
|
||||
|
||||
sleep 5
|
||||
cd ~/Desktop/coco
|
||||
cd $_scriptDir
|
||||
cd ../
|
||||
until node_modules/karma/bin/karma start; do
|
||||
echo "Karma crashed with exit code $?. Respawning.." >&2
|
||||
sleep 1
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
#sleep 5
|
||||
cd ~/Desktop/coco
|
||||
# full script path
|
||||
_scriptDir="$(cd "$(dirname "$0")" && pwd -P)"
|
||||
|
||||
cd $_scriptDir
|
||||
cd ../
|
||||
node_modules/jasmine-node/bin/jasmine-node test/server/ --coffee --autotest --captureExceptions
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd ~/Desktop/coco
|
||||
# full script path
|
||||
_scriptDir="$(cd "$(dirname "$0")" && pwd -P)"
|
||||
|
||||
cd $_scriptDir
|
||||
cd ../
|
||||
node_modules/.bin/nodemon . --ext ".coffee|.js" --watch server --watch server.coffee --unittest
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
__author__ = u'schmatz'
|
||||
from subprocess import call
|
||||
import os
|
||||
import sys
|
||||
#TODO: Upgrade this so it works on windows
|
||||
#These scripts will be placed in coco/bin
|
||||
current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
coco_path = os.getenv("COCO_DIR",os.path.join(current_directory,os.pardir))
|
||||
nodemon_path = coco_path + os.sep + "node_modules" + os.sep + ".bin" + os.sep + "nodemon"
|
||||
|
||||
call(nodemon_path + " . --ext \".coffee|.js\" --watch server --watch app.js --watch server_config.js",shell=True,cwd=coco_path)
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
__author__ = u'schmatz'
|
||||
from subprocess import call
|
||||
import subprocess
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
#TODO: Upgrade this so it works on windows
|
||||
#These scripts will be placed in coco/bin
|
||||
current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
coco_path = os.getenv("COCO_DIR",os.path.join(current_directory,os.pardir))
|
||||
brunch_path = coco_path + os.sep + "node_modules" + os.sep + ".bin" + os.sep + "brunch"
|
||||
subprocess.Popen("ulimit -n 10000",shell=True)
|
||||
while True:
|
||||
call(brunch_path + " w --config " + coco_path + os.sep + "brunch.coffee",shell=True,cwd=coco_path)
|
||||
print("Brunch crashed. Press control+C within 1 second to quit.")
|
||||
time.sleep(1)
|
|
@ -1,90 +0,0 @@
|
|||
__author__ = u'schmatz'
|
||||
from subprocess import call
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
#copied straight from the python 3 standard library
|
||||
def which(cmd, mode=os.F_OK | os.X_OK, path=None):
|
||||
"""Given a command, mode, and a PATH string, return the path which
|
||||
conforms to the given mode on the PATH, or None if there is no such
|
||||
file.
|
||||
|
||||
`mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
|
||||
of os.environ.get("PATH"), or can be overridden with a custom search
|
||||
path.
|
||||
|
||||
"""
|
||||
# Check that a given file can be accessed with the correct mode.
|
||||
# Additionally check that `file` is not a directory, as on Windows
|
||||
# directories pass the os.access check.
|
||||
def _access_check(fn, mode):
|
||||
return (os.path.exists(fn) and os.access(fn, mode)
|
||||
and not os.path.isdir(fn))
|
||||
|
||||
# If we're given a path with a directory part, look it up directly rather
|
||||
# than referring to PATH directories. This includes checking relative to the
|
||||
# current directory, e.g. ./script
|
||||
if os.path.dirname(cmd):
|
||||
if _access_check(cmd, mode):
|
||||
return cmd
|
||||
return None
|
||||
|
||||
if path is None:
|
||||
path = os.environ.get("PATH", os.defpath)
|
||||
if not path:
|
||||
return None
|
||||
path = path.split(os.pathsep)
|
||||
|
||||
if sys.platform == "win32":
|
||||
# The current directory takes precedence on Windows.
|
||||
if not os.curdir in path:
|
||||
path.insert(0, os.curdir)
|
||||
|
||||
# PATHEXT is necessary to check on Windows.
|
||||
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
|
||||
# See if the given file matches any of the expected path extensions.
|
||||
# This will allow us to short circuit when given "python.exe".
|
||||
# If it does match, only test that one, otherwise we have to try
|
||||
# others.
|
||||
if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
|
||||
files = [cmd]
|
||||
else:
|
||||
files = [cmd + ext for ext in pathext]
|
||||
else:
|
||||
# On other platforms you don't have things like PATHEXT to tell you
|
||||
# what file suffixes are executable, so just pass on cmd as-is.
|
||||
files = [cmd]
|
||||
|
||||
seen = set()
|
||||
for dir in path:
|
||||
normdir = os.path.normcase(dir)
|
||||
if not normdir in seen:
|
||||
seen.add(normdir)
|
||||
for thefile in files:
|
||||
name = os.path.join(dir, thefile)
|
||||
if _access_check(name, mode):
|
||||
return name
|
||||
return None
|
||||
|
||||
#TODO: Upgrade this so it works on windows
|
||||
#These scripts will be placed in coco/bin
|
||||
|
||||
current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
if which("mongod") and "v2.5.4" in subprocess.check_output("mongod --version",shell=True):
|
||||
mongo_executable = "mongod"
|
||||
else:
|
||||
mongo_executable = None
|
||||
print("Mongod 2.5.4 wasn't found. Searching in bin directory...")
|
||||
|
||||
mongo_directory = current_directory + os.sep + u"mongo"
|
||||
if not mongo_executable:
|
||||
mongo_executable = os.environ.get("COCO_MONGOD_PATH",mongo_directory + os.sep + u"mongod")
|
||||
if not os.path.exists(mongo_executable):
|
||||
raise FileNotFoundError("Mongo executable not found.")
|
||||
print("Using mongo executable: " + str(mongo_executable))
|
||||
mongo_db_path = os.path.abspath(os.path.join(current_directory,os.pardir)) + os.sep + u"mongo"
|
||||
if not os.path.exists(mongo_db_path):
|
||||
os.mkdir(mongo_db_path)
|
||||
mongo_arguments = [mongo_executable + u" --setParameter textSearchEnabled=true --dbpath=" + mongo_db_path]
|
||||
call(mongo_arguments,shell=True)
|
||||
|
|
@ -12,7 +12,6 @@ class DirectoryController(object):
|
|||
|
||||
@property
|
||||
def root_install_directory(self):
|
||||
#return self.root_dir + os.sep + u"codecombat"
|
||||
return self.root_dir + os.sep + "coco" + os.sep + "bin"
|
||||
@property
|
||||
def tmp_directory(self):
|
||||
|
@ -31,20 +30,19 @@ class DirectoryController(object):
|
|||
os.mkdir(full_path)
|
||||
|
||||
def create_base_directories(self):
|
||||
#first create the directory for the development environment to be installed in
|
||||
shutil.rmtree(self.root_dir + os.sep + "coco" + os.sep + "node_modules",ignore_errors=True) #just in case
|
||||
try:
|
||||
#os.mkdir(self.root_install_directory)
|
||||
#then the tmp directory for file downloads and the like
|
||||
os.mkdir(self.tmp_directory)
|
||||
#then the bin directory for binaries(also includes binaries for dependencies?
|
||||
#os.mkdir(self.bin_directory)
|
||||
if os.path.exists(self.tmp_directory):
|
||||
self.remove_directories()
|
||||
os.mkdir(self.tmp_directory)
|
||||
except:
|
||||
#cleanup whatever we created
|
||||
#self.remove_directories()
|
||||
raise errors.CoCoError(u"There was an error creating the directory structure, do you have correct permissions? Please remove all and start over.")
|
||||
|
||||
raise errors.CoCoError(u"There was an error creating the directory structure, do you have correct permissions? Please remove all and start over.")
|
||||
|
||||
def remove_directories(self):
|
||||
print u"Removed directories created!"
|
||||
shutil.rmtree(self.bin_directory + os.sep + "node",ignore_errors=True)
|
||||
shutil.rmtree(self.bin_directory + os.sep + "mongo",ignore_errors=True)
|
||||
def remove_tmp_directory(self):
|
||||
shutil.rmtree(self.tmp_directory)
|
||||
#shutil.rmtree(self.root_install_directory)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -10,17 +10,19 @@ import shutil
|
|||
import os
|
||||
import glob
|
||||
import subprocess
|
||||
def print_computer_information(os_name,address_width):
|
||||
print(os_name + " detected, architecture: " + str(address_width) + " bit")
|
||||
def constructSetup():
|
||||
config = configuration.Configuration()
|
||||
address_width = config.system.get_virtual_memory_address_width()
|
||||
if config.system.operating_system == u"mac":
|
||||
print("Mac detected, architecture: " + str(config.system.get_virtual_memory_address_width()) + " bit")
|
||||
print_computer_information("Mac",address_width)
|
||||
return MacSetup(config)
|
||||
elif config.system.operating_system == u"win":
|
||||
print("Windows detected, architecture: " + str(config.system.get_virtual_memory_address_width())+ " bit")
|
||||
print_computer_information("Windows",address_width)
|
||||
raise NotImplementedError("Windows is not supported at this time.")
|
||||
#return WinSetup(config)
|
||||
elif config.system.operating_system == u"linux":
|
||||
print("Linux detected, architecture: " + str(config.system.get_virtual_memory_address_width())+ " bit")
|
||||
print_computer_information("Linux",address_width)
|
||||
return LinuxSetup(config)
|
||||
|
||||
class SetupFactory(object):
|
||||
|
@ -49,13 +51,6 @@ class SetupFactory(object):
|
|||
print ("Doing initial bower install...")
|
||||
bower_path = self.config.directory.root_dir + os.sep + "coco" + os.sep + "node_modules" + os.sep + ".bin" + os.sep + "bower"
|
||||
subprocess.call(bower_path + " --allow-root install",shell=True,cwd=self.config.directory.root_dir + os.sep + "coco")
|
||||
print("Copying bin scripts...")
|
||||
|
||||
script_location =self.config.directory.root_dir + os.sep + "coco" + os.sep + "scripts" + os.sep + "devSetup" + os.sep + "bin"
|
||||
#print("Script location: " + script_location)
|
||||
#print("Destination: "+ self.config.directory.root_install_directory)
|
||||
#for filename in glob.glob(os.path.join(script_location, '*.*')):
|
||||
# shutil.copy(filename, self.config.directory.root_install_directory)
|
||||
print("Removing temporary directories")
|
||||
self.config.directory.remove_directories()
|
||||
print("Changing permissions of files...")
|
||||
|
@ -67,12 +62,8 @@ class SetupFactory(object):
|
|||
print("2. ./coco-brunch")
|
||||
print("3. ./coco-dev-server")
|
||||
print("Once brunch is done, visit http://localhost:3000!")
|
||||
#print self.mongo.bashrc_string()
|
||||
#print self.node.bashrc_string()
|
||||
#print "COCO_DIR="+ self.config.directory.root_dir + os.sep + "coco"
|
||||
def cleanup(self):
|
||||
self.config.directory.remove_directories()
|
||||
|
||||
self.config.directory.remove_tmp_directory()
|
||||
|
||||
class MacSetup(SetupFactory):
|
||||
def setup(self):
|
||||
|
|
|
@ -12,7 +12,7 @@ class MongoDB(Dependency):
|
|||
super(self.__class__, self).__init__(configuration)
|
||||
operating_system = configuration.system.operating_system
|
||||
self.config.directory.create_directory_in_tmp(u"mongo")
|
||||
#self.config.directory.create_directory_in_bin("mongo")
|
||||
|
||||
if operating_system == u"mac":
|
||||
self.downloader = MacMongoDBDownloader(self)
|
||||
elif operating_system == u"win":
|
||||
|
|
|
@ -29,7 +29,7 @@ class SystemConfiguration(object):
|
|||
if is64Bit:
|
||||
return 64
|
||||
else:
|
||||
if self.operating_system != u"linux" or self.operating_system !=u"windows":
|
||||
if self.operating_system == u"mac":
|
||||
raise NotSupportedError(u"Your processor is determined to have a maxSize of" + sys.maxsize +
|
||||
u",\n which doesn't correspond with a 64-bit architecture.")
|
||||
return 32
|
||||
|
|
Loading…
Reference in a new issue