Real-time multiplayer subscription schemas

This commit is contained in:
Matt Lott 2014-08-29 15:10:04 -07:00
parent 68cca74b43
commit 92cad5f46f
10 changed files with 58 additions and 46 deletions

View file

@ -7,6 +7,7 @@ channelSchemas =
'editor': require './schemas/subscriptions/editor' 'editor': require './schemas/subscriptions/editor'
'errors': require './schemas/subscriptions/errors' 'errors': require './schemas/subscriptions/errors'
'misc': require './schemas/subscriptions/misc' 'misc': require './schemas/subscriptions/misc'
'multiplayer': require './schemas/subscriptions/multiplayer'
'play': require './schemas/subscriptions/play' 'play': require './schemas/subscriptions/play'
'surface': require './schemas/subscriptions/surface' 'surface': require './schemas/subscriptions/surface'
'tome': require './schemas/subscriptions/tome' 'tome': require './schemas/subscriptions/tome'

View file

@ -0,0 +1,14 @@
c = require 'schemas/schemas'
module.exports =
'real-time-multiplayer:joined-game': c.object {title: 'Multiplayer joined game', required: ['session']},
session: {type: 'object'}
'real-time-multiplayer:left-game': c.object {title: 'Multiplayer left game'}
'real-time-multiplayer:manual-cast': c.object {title: 'Multiplayer manual cast'}
'real-time-multiplayer:new-opponent-code': c.object {title: 'Multiplayer new opponent code', required: ['code', 'codeLanguage']},
code: {type: 'object'}
codeLanguage: {type: 'string'}

View file

@ -6,18 +6,18 @@ h4.home
h4.title h4.title
| #{worldName} | #{worldName}
| - span.spl.spr -
a(href=editorLink, data-i18n="nav.editor", title="Open " + worldName + " in the Level Editor") Editor a(href=editorLink, data-i18n="nav.editor", title="Open " + worldName + " in the Level Editor") Editor
if multiplayerSession if multiplayerSession
- found = false - found = false
- for (var i=0; i < multiplayerPlayers.length; i++) { - for (var i=0; i < multiplayerPlayers.length; i++) {
if (multiplayerPlayers.at(i).id !== meID) if (multiplayerPlayers.at(i).id !== meID)
| - vs #{multiplayerPlayers.at(i).get('name')} span.spl.spr - vs #{multiplayerPlayers.at(i).get('name')}
- found = true - found = true
- break - break
- } - }
if !found if !found
| - waiting... span.spl.spr - waiting...

View file

@ -37,8 +37,7 @@ module.exports = class MultiplayerView extends CocoView
destroy: -> destroy: ->
@multiplayerSessions?.off() @multiplayerSessions?.off()
@currentMultiplayerSession?.off() @currentMultiplayerSession?.off()
for id in @playersCollections collection.off() for id, collection of @playersCollections
@playersCollections[id].off()
super() super()
getRenderData: -> getRenderData: ->
@ -65,7 +64,7 @@ module.exports = class MultiplayerView extends CocoView
@ladderSubmissionView = new LadderSubmissionView session: @session, level: @level @ladderSubmissionView = new LadderSubmissionView session: @session, level: @level
@insertSubView @ladderSubmissionView, @$el.find('.ladder-submission-view') @insertSubView @ladderSubmissionView, @$el.find('.ladder-submission-view')
@$el.find('#created-multiplayer-session').toggle Boolean(@currentMultiplayerSession?) @$el.find('#created-multiplayer-session').toggle Boolean(@currentMultiplayerSession?)
@$el.find('#create-game-button').toggle Boolean(!(@currentMultiplayerSession?)) @$el.find('#create-game-button').toggle Boolean(not (@currentMultiplayerSession?))
onClickLink: (e) -> onClickLink: (e) ->
e.target.select() e.target.select()
@ -94,14 +93,12 @@ module.exports = class MultiplayerView extends CocoView
@playersCollections[e.id].on 'add', @onPlayerAdded @playersCollections[e.id].on 'add', @onPlayerAdded
@playersCollections[e.id].on 'remove', @onPlayerRemoved @playersCollections[e.id].on 'remove', @onPlayerRemoved
# Check if we've already joined this multiplayer session # Check if we've already joined this multiplayer session
if not @currentMultiplayerSession and e.get('levelID') == @session.get('levelID') if not @currentMultiplayerSession and e.get('levelID') is @session.get('levelID')
for i in [0...@playersCollections[e.id].length] @playersCollections[e.id].each (player) =>
player = @playersCollections[e.id].at(i) if player.id is me.id and player.get('team') is @session.get('team')
if player.get('id') is me.id and player.get('team') is @session.get('team')
@currentMultiplayerSession = e @currentMultiplayerSession = e
@currentMultiplayerSession.on 'change', @onMultiplayerSessionChanged @currentMultiplayerSession.on 'change', @onMultiplayerSessionChanged
Backbone.Mediator.publish 'realtime-multiplayer:joined-game', @currentMultiplayerSession Backbone.Mediator.publish 'real-time-multiplayer:joined-game', session: @currentMultiplayerSession
break
@render() @render()
onMultiplayerSessionRemoved: (e) => onMultiplayerSessionRemoved: (e) =>
@ -113,26 +110,26 @@ module.exports = class MultiplayerView extends CocoView
@render() @render()
onPlayerAdded: (e) => onPlayerAdded: (e) =>
# TODO: listeners not being unhooked, this should not be called if no @render. # TODO: listeners not being unhooked
@render() if @render @render?()
onPlayerRemoved: (e) => onPlayerRemoved: (e) =>
# TODO: listeners not being unhooked, this should not be called if no @render. # TODO: listeners not being unhooked
@render() if @render @render?()
onCreateGame: -> onCreateGame: ->
s = @multiplayerSessions.create { s = @multiplayerSessions.create {
creator: @session.get('creator') creator: @session.get('creator')
creatorName: @session.get('creatorName') creatorName: @session.get('creatorName')
levelID: @session.get('levelID') levelID: @session.get('levelID')
created: Date.now() created: (new Date()).toISOString()
state: 'creating' state: 'creating'
} }
@currentMultiplayerSession = @multiplayerSessions.get(s.id) @currentMultiplayerSession = @multiplayerSessions.get(s.id)
@currentMultiplayerSession.on 'change', @onMultiplayerSessionChanged @currentMultiplayerSession.on 'change', @onMultiplayerSessionChanged
players = new RealTimeCollection('multiplayer_level_sessions/' + @currentMultiplayerSession.id + '/players') players = new RealTimeCollection('multiplayer_level_sessions/' + @currentMultiplayerSession.id + '/players')
players.create {id: me.id, name: @session.get('creatorName'), team: @session.get('team')} players.create {id: me.id, name: @session.get('creatorName'), team: @session.get('team')}
Backbone.Mediator.publish 'realtime-multiplayer:joined-game', @currentMultiplayerSession Backbone.Mediator.publish 'real-time-multiplayer:joined-game', session: @currentMultiplayerSession
@render() @render()
onJoinGame: (e) -> onJoinGame: (e) ->
@ -144,7 +141,7 @@ module.exports = class MultiplayerView extends CocoView
@playersCollections[item.id].create {id: me.id, name: @session.get('creatorName'), team: @session.get('team')} @playersCollections[item.id].create {id: me.id, name: @session.get('creatorName'), team: @session.get('team')}
else else
console.error 'onJoinGame did not have a players collection', @currentMultiplayerSession console.error 'onJoinGame did not have a players collection', @currentMultiplayerSession
Backbone.Mediator.publish 'realtime-multiplayer:joined-game', @currentMultiplayerSession Backbone.Mediator.publish 'real-time-multiplayer:joined-game', session: @currentMultiplayerSession
if @playersCollections[item.id]?.length is 2 if @playersCollections[item.id]?.length is 2
@currentMultiplayerSession.set 'state', 'coding' @currentMultiplayerSession.set 'state', 'coding'
# TODO: close multiplayer view? # TODO: close multiplayer view?
@ -166,7 +163,7 @@ module.exports = class MultiplayerView extends CocoView
@multiplayerSessions.remove(cms) @multiplayerSessions.remove(cms)
break break
console.error "Tried to leave a game we hadn't joined!" if @currentMultiplayerSession console.error "Tried to leave a game we hadn't joined!" if @currentMultiplayerSession
Backbone.Mediator.publish 'realtime-multiplayer:left-game' Backbone.Mediator.publish 'real-time-multiplayer:left-game', {}
else else
console.error "Tried to leave a game with no currentMultiplayerSession" console.error "Tried to leave a game with no currentMultiplayerSession"
@render() @render()

View file

@ -12,8 +12,8 @@ module.exports = class ControlBarView extends CocoView
subscriptions: subscriptions:
'bus:player-states-changed': 'onPlayerStatesChanged' 'bus:player-states-changed': 'onPlayerStatesChanged'
'realtime-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame' 'real-time-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame'
'realtime-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame' 'real-time-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame'
events: events:
'click #docs-button': -> 'click #docs-button': ->
@ -85,14 +85,14 @@ module.exports = class ControlBarView extends CocoView
showGameMenuModal: -> showGameMenuModal: ->
@openModalView new GameMenuModal level: @level, session: @session, playableTeams: @playableTeams @openModalView new GameMenuModal level: @level, session: @session, playableTeams: @playableTeams
onJoinedRealTimeMultiplayerGame: (item) -> onJoinedRealTimeMultiplayerGame: (e) ->
@multiplayerSession = item @multiplayerSession = e.session
@multiplayerPlayers = new RealTimeCollection('multiplayer_level_sessions/' + item.id + '/players') @multiplayerPlayers = new RealTimeCollection('multiplayer_level_sessions/' + @multiplayerSession.id + '/players')
@multiplayerPlayers.on 'add', @onRealTimeMultiplayerPlayerAdded @multiplayerPlayers.on 'add', @onRealTimeMultiplayerPlayerAdded
@multiplayerPlayers.on 'remove', @onRealTimeMultiplayerPlayerRemoved @multiplayerPlayers.on 'remove', @onRealTimeMultiplayerPlayerRemoved
@render() @render()
onLeftRealTimeMultiplayerGame: -> onLeftRealTimeMultiplayerGame: (e) ->
@multiplayerSession = null @multiplayerSession = null
@multiplayerPlayers.off() @multiplayerPlayers.off()
@multiplayerPlayers = null @multiplayerPlayers = null

View file

@ -14,8 +14,8 @@ module.exports = class LevelFlagsView extends CocoView
'god:new-world-created': 'onNewWorld' 'god:new-world-created': 'onNewWorld'
'god:streaming-world-updated': 'onNewWorld' 'god:streaming-world-updated': 'onNewWorld'
'surface:remove-flag': 'onRemoveFlag' 'surface:remove-flag': 'onRemoveFlag'
'realtime-multiplayer:joined-game': 'onJoinedMultiplayerGame' 'real-time-multiplayer:joined-game': 'onJoinedMultiplayerGame'
'realtime-multiplayer:left-game': 'onLeftMultiplayerGame' 'real-time-multiplayer:left-game': 'onLeftMultiplayerGame'
events: events:
'click .green-flag': -> @onFlagSelected color: 'green', source: 'button' 'click .green-flag': -> @onFlagSelected color: 'green', source: 'button'
@ -78,11 +78,11 @@ module.exports = class LevelFlagsView extends CocoView
return unless event.world.name is @world.name return unless event.world.name is @world.name
@world = @options.world = event.world @world = @options.world = event.world
onJoinedMultiplayerGame: (item) -> onJoinedMultiplayerGame: (e) ->
@realTimeFlags = new RealTimeCollection('multiplayer_level_sessions/' + item.id + '/flagHistory') @realTimeFlags = new RealTimeCollection('multiplayer_level_sessions/' + e.session.id + '/flagHistory')
@realTimeFlags.on 'add', @onRealTimeMultiplayerFlagAdded @realTimeFlags.on 'add', @onRealTimeMultiplayerFlagAdded
onLeftMultiplayerGame: () -> onLeftMultiplayerGame: (e) ->
@multiplayerState = null @multiplayerState = null
if @multiplayerSession if @multiplayerSession
@multiplayerSession.off() @multiplayerSession.off()

View file

@ -25,7 +25,7 @@ module.exports = class LevelPlaybackView extends CocoView
'tome:cast-spells': 'onTomeCast' 'tome:cast-spells': 'onTomeCast'
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded' 'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
'playback:stop-real-time-playback': 'onStopRealTimePlayback' 'playback:stop-real-time-playback': 'onStopRealTimePlayback'
'realtime-multiplayer:manual-cast': 'onRealTimeMultiplayerCast' 'real-time-multiplayer:manual-cast': 'onRealTimeMultiplayerCast'
events: events:
'click #debug-toggle': 'onToggleDebug' 'click #debug-toggle': 'onToggleDebug'

View file

@ -66,9 +66,9 @@ module.exports = class PlayLevelView extends RootView
'level:loading-view-unveiled': 'onLoadingViewUnveiled' 'level:loading-view-unveiled': 'onLoadingViewUnveiled'
'playback:real-time-playback-started': 'onRealTimePlaybackStarted' 'playback:real-time-playback-started': 'onRealTimePlaybackStarted'
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded' 'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
'realtime-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame' 'real-time-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame'
'realtime-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame' 'real-time-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame'
'realtime-multiplayer:manual-cast': 'onRealTimeMultiplayerCast' 'real-time-multiplayer:manual-cast': 'onRealTimeMultiplayerCast'
events: events:
'click #level-done-button': 'onDonePressed' 'click #level-done-button': 'onDonePressed'
@ -550,10 +550,10 @@ module.exports = class PlayLevelView extends RootView
# Real-time Multiplayer ###################################################### # Real-time Multiplayer ######################################################
onJoinedRealTimeMultiplayerGame: (item) -> onJoinedRealTimeMultiplayerGame: (e) ->
@multiplayerSession = item @multiplayerSession = e.session
onLeftRealTimeMultiplayerGame: () -> onLeftRealTimeMultiplayerGame: (e) ->
if @multiplayerSession if @multiplayerSession
@multiplayerSession.off() @multiplayerSession.off()
@multiplayerSession = null @multiplayerSession = null
@ -592,7 +592,7 @@ module.exports = class PlayLevelView extends RootView
onOpponentSubmitted: (opponentPlayer, myPlayer) => onOpponentSubmitted: (opponentPlayer, myPlayer) =>
# Save opponent's code # Save opponent's code
Backbone.Mediator.publish 'realtime-multiplayer:new-opponent-code', {codeLanguage: opponentPlayer.get('codeLanguage'), code: opponentPlayer.get('code')} Backbone.Mediator.publish 'real-time-multiplayer:new-opponent-code', {codeLanguage: opponentPlayer.get('codeLanguage'), code: opponentPlayer.get('code')}
# I'm ready to rumble # I'm ready to rumble
myPlayer.set 'state', 'ready' myPlayer.set 'state', 'ready'
if opponentPlayer.get('state') is 'ready' if opponentPlayer.get('state') is 'ready'

View file

@ -15,8 +15,8 @@ module.exports = class CastButtonView extends CocoView
'tome:cast-spells': 'onCastSpells' 'tome:cast-spells': 'onCastSpells'
'god:world-load-progress-changed': 'onWorldLoadProgressChanged' 'god:world-load-progress-changed': 'onWorldLoadProgressChanged'
'god:new-world-created': 'onNewWorld' 'god:new-world-created': 'onNewWorld'
'realtime-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame' 'real-time-multiplayer:joined-game': 'onJoinedRealTimeMultiplayerGame'
'realtime-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame' 'real-time-multiplayer:left-game': 'onLeftRealTimeMultiplayerGame'
constructor: (options) -> constructor: (options) ->
super options super options
@ -51,7 +51,7 @@ module.exports = class CastButtonView extends CocoView
onCastRealTimeButtonClick: (e) -> onCastRealTimeButtonClick: (e) ->
if @multiplayerSession if @multiplayerSession
Backbone.Mediator.publish 'realtime-multiplayer:manual-cast', {} Backbone.Mediator.publish 'real-time-multiplayer:manual-cast', {}
# Wait for multiplayer session to be up and running # Wait for multiplayer session to be up and running
@multiplayerSession.on 'change', (e) => @multiplayerSession.on 'change', (e) =>
if @multiplayerSession.get('state') is 'running' if @multiplayerSession.get('state') is 'running'
@ -118,10 +118,10 @@ module.exports = class CastButtonView extends CocoView
@castOptions.find('a').each -> @castOptions.find('a').each ->
$(@).toggleClass('selected', parseInt($(@).attr('data-delay')) is delay) $(@).toggleClass('selected', parseInt($(@).attr('data-delay')) is delay)
onJoinedRealTimeMultiplayerGame: (item) -> onJoinedRealTimeMultiplayerGame: (e) ->
@multiplayerSession = item @multiplayerSession = e.session
onLeftRealTimeMultiplayerGame: () -> onLeftRealTimeMultiplayerGame: (e) ->
if @multiplayerSession if @multiplayerSession
@multiplayerSession.off() @multiplayerSession.off()
@multiplayerSession = null @multiplayerSession = null

View file

@ -47,7 +47,7 @@ module.exports = class Spell
@tabView.render() @tabView.render()
@team = @permissions.readwrite[0] ? 'common' @team = @permissions.readwrite[0] ? 'common'
Backbone.Mediator.publish 'tome:spell-created', spell: @ Backbone.Mediator.publish 'tome:spell-created', spell: @
Backbone.Mediator.subscribe 'realtime-multiplayer:new-opponent-code', @onNewOpponentCode Backbone.Mediator.subscribe 'real-time-multiplayer:new-opponent-code', @onNewOpponentCode
destroy: -> destroy: ->
@view?.destroy() @view?.destroy()