競争力のあるターンベースのゲームを開発しています。匿名の訪問者がページにアクセスすると、ゲームの完全ではないインスタンスに自動的にサブスクライブし、アクションを観察するか参加することができます。各ゲーム インスタンスのスポット数は限られています。ゲームに参加する (スポットを取得する) と、古いサブスクリプションは停止され、選択したスポットに基づく個人情報も含む新しいサブスクリプションが作成されます。ここまでは順調ですね。
ここで、プレーヤーが妥当な時間内に自分のターンを完了しないときはいつでも、サーバーがスポットを解放できるようにしたいと考えています。
問題は、自分の場所から追い出されたプレーヤーが、自分の場所を占有している他の誰かに送られることを意図した更新を受信しないようにするにはどうすればよいかということです。クライアントは信頼できないため、明らかにこれはサーバー側で発生する必要があります。追い出されたユーザーがシームレスにオブザーバーに戻ることが理想的です。
publish()内で呼び出すことができるメソッドstop()があることは知っていますが、 Meteor.setTimeout()によって設定されたコールバックがサーバーで呼び出されたときに、特定のクライアントの公開されたサブスクリプションを停止するためにそれを使用する方法は?
私がやろうとしていることの大幅に変更されたコード (動作することを意図したものではなく、アイデアを提供するためだけに)
if Meteor.isClient
publicGameHandle = Meteor.subscribe 'GameInstances'
join = (gameInstanceId, spot) ->
Meteor.call "join", gameInstanceId, spot, (err, guestId) ->
Session.set("guestId", guestId)
privateGameHandle = Meteor.subscribe 'GameInstances',
gameInstanceId, spot, guestId, ->
publicGameHandle.stop()
if Meteor.isServer
privateSubscriptions = {}
Meteor.publish 'GameInstances', (gameInstanceId, spot, guestId) ->
if gameInstanceId
GameInstances.find {_id: gameInstanceId}
privateSubscriptions[guestId] = @
else
secretFields = {spots.guestId:false, spots.privateGameInfo:false}
GameInstances.find {openSpots: {$gt: 0}}, {fields: secretFields}
Meteor.methods({
join: (gameInstanceId, spot) ->
guestId = Random.id()
gameInstances[gameInstanceId].addPlayer(spot, guestId)
guestId
completePlayerTurn: (gameInstanceId, spot, guestId) ->
gameInstance = gameInstances[gameInstanceId]
Meteor.clearTimeout(gameInstance.timer)
nextPlayer = gameInstance.getNextPlayer()
kick = () ->
privateSubcriptions[nextPlayer.guestId].stop()
gameInstance.removePlayer(nextPlayer.guestId)
gameinstance.timer = Meteor.setTimeout(kick, 60000)