Meteor框架根据文档变量订阅/发布

Meteor框架根据文档变量订阅/发布,meteor,publish,subscribe,Meteor,Publish,Subscribe,我有一个基于流星框架的游戏。一个游戏文档是这样的: { ... participants : [ { "name":"a", "character":"fighter", "weapon" : "sword" }, { "name":"b", "character":"wizard", "weapon" : "book" }, ... ], ... } PlayerProperties = new Mon

我有一个基于流星框架的游戏。一个游戏文档是这样的:

{
...
participants : [
    {
    "name":"a",
    "character":"fighter",
    "weapon" : "sword"
    },
    {
    "name":"b",
    "character":"wizard",
    "weapon" : "book"
    },
   ...
  ],
...
}
PlayerProperties = new Mongo.Collection('playerProperties');
/* schema:

     userId    : String
     gameId    : String
     key       : String
     value     : *
     whoCanSee : [String]
*/
我不想让战士角色看到“b”用户的角色。(b角色看不到a的)大约有10个字段,比如角色和武器,它们的值可以在游戏中改变,因此限制也会改变

现在,我使用会话变量不显示这些信息。然而,这不是一个非常安全的想法。如何根据基于字符的值订阅/发布文档

我想到了两种可能的解决方案: 1.发布不同字段值的所有组合,并根据用户的当前状态进行订阅。但是,我使用Iron Router的waitOn功能在呈现页面之前加载订阅。所以我不太相信我可以在游戏期间更改订阅。另外,因为这是一个时间敏感的游戏,我猜更改订阅会在游戏过程中花费时间,破坏游戏乐趣

  • 我现在的问题是用户输入

    Collection.find({})


  • 转到控制台并查看其他用户的字段。如果我将收藏名称更改为难以找到的名称,有人能发现收藏名称吗?我找不到在客户端查找集合的命令

    在Meteor中解决这个问题的方法通常是使用两种出版物。如果您的游戏状态由单个文档表示,那么您可能很难轻松实现它,因此为了示例起见,我将暂时假设您有一个
    参与者
    集合,其中存储了相应的数据

    所以无论如何,你应该有一个订阅,所有玩家都可以使用数据,例如

    Meteor.publish('players', function (gameId) {
      return Participants.find({ gameId: gameId }, { fields: {
        // exclude the "character" field from the result
        character: 0
      }});
    });
    
    和另一个私人玩家数据订阅:

    Meteor.publish('myPrivateData', function (gameId) {
      // NOTE: not excluding anything, because we are only
      //       publishing a single document here, whose owner
      //       is the current user ...
      return Participants.find({
        userId: this.userId,
        gameId: gameId,
      }); 
    });
    
    现在,在客户端,您只需要订阅两个数据集,因此:

    Meteor.subscribe('players', myGameId);
    Meteor.subscribe('myPrivateData', myGameId);
    
    Meteor将非常聪明地将传入的数据合并到一个
    参与者
    集合中,其他玩家的文档将不包含
    字符
    字段

    编辑 如果您的字段可见性将动态变化,我建议采用以下方法:

    • 将所有受限属性放在一个单独的集合中,该集合精确跟踪谁可以查看哪个字段
    • 在客户端,使用
      observe
      将该集合集成到本地播放器表示中,以便更轻松地访问数据
    数据模型 例如,集合可能如下所示:

    {
    ...
    participants : [
        {
        "name":"a",
        "character":"fighter",
        "weapon" : "sword"
        },
        {
        "name":"b",
        "character":"wizard",
        "weapon" : "book"
        },
       ...
      ],
    ...
    }
    
    PlayerProperties = new Mongo.Collection('playerProperties');
    /* schema:
    
         userId    : String
         gameId    : String
         key       : String
         value     : *
         whoCanSee : [String]
    */
    
    发布数据 首先,您需要向每个玩家公开自己的属性

    Meteor.publish('myProperties', function (gameId) {
      return PlayerProperties.find({
        userId: this.userId,
        gameId: gameId
      });
    });
    
    然后是其他玩家的属性:

    Meteor.publish('otherPlayersProperties', function (gameId) {
      if (!this.userId) return [];
      return PlayerProperties.find({
        gameId: gameId,
        whoCanSee: this.userId,
      });
    });
    
    现在,在游戏过程中,您需要做的唯一一件事就是确保在用户能够看到该属性后,立即将相应的
    userId
    添加到
    whoCanSee
    数组中

    改进 为了使您的数据保持有序,我建议仅使用客户端收集,例如,
    IntegratedPlayerData
    ,您可以使用它将播放器属性安排到一些可管理的结构中:

     var IntegratedPlayerData = new Mongo.Collection(null);
     var cache = {};
    
     PlayerProperties.find().observe({
       added: function (doc) {
         IntegratedPlayerData.upsert({ _id : doc.userId }, {
           $set: _.object([ doc.key ], [ doc.value ])  
         });
       },
       changed: function (doc) {
         IntegratedPlayerData.update({ _id : doc.userId }, {
           $set: _.object([ doc.key ], [ doc.value ])  
         });
       },
       removed: function (doc) {
         IntegratedPlayerData.update({ _id : doc.userId }, {
           $unset: _.object([ doc.key ], [ true ])
         });
       }
     });
    

    此数据“集成”只是一个草稿,可以通过多种不同的方式进行细化。可以在服务器端使用。

    对数组中任何对象的
    字符
    字段未发送到客户端,您是否同意?您的问题不清楚。例如,你是否只想让玩家知道他们自己的角色和武器是什么?如果是,那么是的。您可以根据用户名控制对其他集合的订阅(如果您跟踪
    \u id
    s会更好)。角色可以自由查看自己的字段,但不应查看其他用户的字段(可以查看部分字段,但不能查看全部字段)。基于字段的这些限制可以在游戏期间更改。所以我想根据字段值而不是用户名来订阅。谢谢你的评论。一个角色有许多字段,这些字段可以在游戏中更改。那么,我想你的答案不能解决问题?你认为它在什么方面不能解决问题?这与游戏中更改的字段值有什么关系?所有字段都限制玩家查看其他字段。大约有10个字段。假设我在服务器上发布了每个组合,当一个值在游戏中改变时,订阅也应该改变。那么,我如何在游戏期间更改订阅?(我正在使用Iron Router的waitOn字段进行订阅)如果您不介意更新您的问题并更详细地描述您的问题,那么我也可以更新我的答案。听起来合理吗?我编辑了我的问题并添加了更多细节。很抱歉,没有相关信息。