mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-30 02:55:43 -05:00
135 lines
3.7 KiB
CoffeeScript
135 lines
3.7 KiB
CoffeeScript
|
CocoClass = require 'lib/CocoClass'
|
||
|
|
||
|
{me} = require 'lib/auth'
|
||
|
|
||
|
CHAT_SIZE_LIMIT = 500 # no more than 500 messages
|
||
|
|
||
|
module.exports = Bus = class Bus extends CocoClass
|
||
|
joined: null
|
||
|
players: null
|
||
|
|
||
|
@get: (docName) -> return @getFromCache or new Bus docName
|
||
|
@getFromCache: (docName) -> return Bus.activeBuses[docName]
|
||
|
@activeBuses: {}
|
||
|
@fireHost: 'https://codecombat.firebaseio.com'
|
||
|
|
||
|
constructor: (@docName) ->
|
||
|
super()
|
||
|
@players = {}
|
||
|
Bus.activeBuses[@docName] = @
|
||
|
|
||
|
subscriptions:
|
||
|
'level-bus-echo-states': 'onEchoStates'
|
||
|
'me:synced': 'onMeSynced'
|
||
|
|
||
|
onEchoStates: ->
|
||
|
@notifyStateChanges()
|
||
|
|
||
|
connect: ->
|
||
|
Backbone.Mediator.publish 'bus:connecting', {bus:@}
|
||
|
Firebase.goOnline()
|
||
|
@fireRef = new Firebase(Bus.fireHost + "/" + @docName)
|
||
|
@fireRef.once 'value', @onFireOpen
|
||
|
|
||
|
onFireOpen: (snapshot) =>
|
||
|
if @destroyed
|
||
|
console.log("Leaving '#{@docName}' because class has been destroyed.")
|
||
|
return
|
||
|
@init()
|
||
|
Backbone.Mediator.publish 'bus:connected', {bus:@}
|
||
|
|
||
|
disconnect: ->
|
||
|
Firebase.goOffline()
|
||
|
@fireRef?.off()
|
||
|
@fireRef = null
|
||
|
@fireChatRef?.off()
|
||
|
@fireChatRef = null
|
||
|
@firePlayersRef?.off()
|
||
|
@firePlayersRef = null
|
||
|
@myConnection?.off()
|
||
|
@myConnection = null
|
||
|
@joined = false
|
||
|
Backbone.Mediator.publish 'bus:disconnected', {bus:@}
|
||
|
|
||
|
init: ->
|
||
|
"""
|
||
|
Init happens when we're connected.
|
||
|
"""
|
||
|
@fireChatRef = @fireRef.child('chat')
|
||
|
@firePlayersRef = @fireRef.child('players')
|
||
|
@join()
|
||
|
@listenForChanges()
|
||
|
@sendMessage("/me joined.", true)
|
||
|
|
||
|
join: ->
|
||
|
@joined = true
|
||
|
@myConnection = @firePlayersRef.child(me.id)
|
||
|
@myConnection.set({id: me.id, name: me.get('name'), connected: true})
|
||
|
@onDisconnect = @myConnection.child('connected').onDisconnect()
|
||
|
@onDisconnect.set(false)
|
||
|
|
||
|
listenForChanges: ->
|
||
|
@fireChatRef.limit(CHAT_SIZE_LIMIT).on 'child_added', @onChatAdded
|
||
|
@firePlayersRef.on 'child_added', @onPlayerJoined
|
||
|
@firePlayersRef.on 'child_removed', @onPlayerLeft
|
||
|
@firePlayersRef.on 'child_changed', @onPlayerChanged
|
||
|
|
||
|
onChatAdded: (snapshot) =>
|
||
|
Backbone.Mediator.publish('bus:new-message', {message:snapshot.val(), bus:@})
|
||
|
|
||
|
onPlayerJoined: (snapshot) =>
|
||
|
player = snapshot.val()
|
||
|
return unless player.connected
|
||
|
@players[player.id] = player
|
||
|
Backbone.Mediator.publish('bus:player-joined', {player:player, bus:@})
|
||
|
|
||
|
onPlayerLeft: (snapshot) =>
|
||
|
val = snapshot.val()
|
||
|
return unless val
|
||
|
player = @players[val.id]
|
||
|
return unless player
|
||
|
delete @players[player.id]
|
||
|
Backbone.Mediator.publish('bus:player-left', {player:player, bus:@})
|
||
|
|
||
|
onPlayerChanged: (snapshot) =>
|
||
|
player = snapshot.val()
|
||
|
wasConnected = @players[player.id]?.connected
|
||
|
@players[player.id] = player
|
||
|
@onPlayerLeft(snapshot) if wasConnected and not player.connected
|
||
|
@onPlayerJoined(snapshot) if player.connected and not wasConnected
|
||
|
Backbone.Mediator.publish('bus:player-states-changed', {states:@players, bus:@})
|
||
|
|
||
|
onMeSynced: =>
|
||
|
@myConnection?.child('name').set(me.get('name'))
|
||
|
|
||
|
countPlayers: -> _.size(@players)
|
||
|
|
||
|
onPoint: ->
|
||
|
# simple way to elect somone to do jobs that don't need to be done by each player
|
||
|
ids = _.keys(@players)
|
||
|
ids.sort()
|
||
|
return ids[0] is me.id
|
||
|
|
||
|
# MESSAGING
|
||
|
|
||
|
sendSystemMessage: (content) ->
|
||
|
@sendMessage(content, true)
|
||
|
|
||
|
sendMessage: (content, system=false) ->
|
||
|
MAX_MESSAGE_LENGTH = 400
|
||
|
message =
|
||
|
content:content[... MAX_MESSAGE_LENGTH]
|
||
|
authorName:me.displayName()
|
||
|
authorID:me.id
|
||
|
dateMade: new Date()
|
||
|
message.system = system if system
|
||
|
@fireChatRef.push(message)
|
||
|
|
||
|
# TEARDOWN
|
||
|
|
||
|
destroy: ->
|
||
|
@sendMessage("/me left.", true) if @joined
|
||
|
delete Bus.activeBuses[@docName] if @docName of Bus.activeBuses
|
||
|
@disconnect()
|
||
|
super()
|