Meteor 1.0 - 托管大厅并重定向其他用户

Meteor 1.0 - Hosting a lobby and redirecting other users

我有一个问题,我不知道如何解决。我正在创建涉及多个玩家的游戏。一个人 "hosts" 游戏并发送 "invitations" 给其他用户加入 "lobby"。如果您曾经玩过《使命召唤》或任何类似游戏,就会发现它们是同一个概念。

这个过程的大部分目前都在正常工作。

我创建了一个名为 Lobby 的集合来跟踪所有打开和关闭的大厅。当用户想要主持大厅时,他单击按钮,这将创建一个新的大厅并将用户重定向到正确的 url:

Template.lobby.events
  'click button#host-lobby': (e,t) ->
    lobbyId = Lobby.insert
      host: Meteor.user()._id
      hostName: Meteor.user().username
      status: true
      players: []
    Router.go("currentLobby", _id: lobbyId)

然后,用户可以通过模态邀请其他用户到大厅 (url),这会向受邀用户的个人资料添加通知对象。可能不是最好的方法,所以我愿意接受这方面的建议。

Template._playerItem.events
  'click button': (e,t) ->
    lobbyId = Session.get "currentLobby"
    Meteor.call "sendNotification", @_id, lobbyId, Meteor.user().username
    Lobby.update
      _id: lobbyId
    ,
      $addToSet:
        invitedPlayers: @_id

以及方法:

Meteor.methods
  sendNotification: (userId, lobbyId, hostName) ->
    sendTo = Meteor.users.findOne(_id: userId)
    Meteor.users.update
      _id: userId
    ,
      $push:
        invite:
          hostName: hostName
          lobbyId: lobbyId

所以此时,用户可以接受或拒绝邀请。如果他接受,他将被路由到大厅并被添加到大厅对象中的 players 数组中。用户如预期的那样出现在玩家列表中。

当我尝试 "start" 游戏时,我的问题就开始了。单击按钮后,游戏将正确创建,主机(按下按钮的人)将路由到新游戏的 url:

Template.currentLobby.events
  'click #start-game': (e,t) ->
    playerIds = [@host]
    @players.forEach (player) ->
      playerIds.push(player.id)
    Meteor.call 'createGame', playerIds
    Router.go('home')

问题是大厅中的其他用户没有被重定向。如果他们手动转到 url,他们可以访问游戏,但他们不会被带到那里。他们根本不知道比赛真的开始了...

一个解决方案是在游戏中添加一个 "Game has started" 徽章,带有 link,但我认为更优雅的解决方案是将所有用户路由到当前大厅 url 到刚刚开始的游戏。

这个功能可行吗?有没有更好的方式来举办大厅?

编辑

感谢切特提供的解决方案。这就是我最终实现它的方式:

Template.currentLobby.rendered = ->
  @autorun ->
    data = Template.currentData()
    if data.url
      Router.go data.url

@autorun 有一些上下文困难,所以我只使用大厅数据。然后,当有人点击 "start game" 按钮时,当前大厅将更新为新游戏的 url(Meteor.call 'createGame' returns 的 _id新游戏)。

Template.currentLobby.events
  'click #start-game': (e,t) ->
    playerIds = [@host]
    lobbyId = Template.currentData()._id

    @players.forEach (player) ->
      playerIds.push(player.id)

    Meteor.call 'createGame', playerIds, (err, res) ->
      Lobby.update
        _id: lobbyId
      ,
        $set:
          url: "/game/#{res}"

很有魅力。谢谢!

好的。首先,处理您的通知。这是一个有效的解决方案。但是,您可能希望按日期对它们进行排序!您还需要创建一个单独的通知集合。每当您更新文档时,整个过程都会通过 DDP 发送到客户端。因此,添加到配置文件的任何新通知都会导致将整个配置文件发送到客户端。您还需要某种方式将通知标记为已读,以便将其删除。

为了解决您关于重定向大厅的问题,创建名为 url 的 属性。最初它被设置为 false。一旦主持人准备好开始游戏,他们将 url 属性 设置为 url。

当用户进入大厅时,启动重定向的自动运行。

Template.lobby.rendered = ->
  @autorun ->
    if game.url
      Router.go(game.url)

您必须确保 game.url 是反应式数据源。如果您使用 iron router 将游戏作为数据上下文传递,那么您应该可以使用 @data.url 但我不能 100% 确定它会是反应式的。为安全起见,请尝试 Games.findOne(@data._id)——这肯定会产生反应。

编辑: 为了清楚起见,试试这个:

Template.lobby.rendered = ->
  @autorun ->
    game = Games.findOne(@data._id)
    if game.url
      Router.go(game.url)