首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根据文档变量订阅/发布

根据文档变量订阅/发布
EN

Stack Overflow用户
提问于 2015-10-26 22:02:20
回答 1查看 68关注 0票数 1

我有一个建立在流星框架上的游戏。一个游戏文档是这样的:

代码语言:javascript
复制
{
...
participants : [
    {
    "name":"a",
    "character":"fighter",
    "weapon" : "sword"
    },
    {
    "name":"b",
    "character":"wizard",
    "weapon" : "book"
    },
   ...
  ],
...
}

我希望战士字符不要看到"b“用户的字符。(和b字符没有看到a)有大约10个领域,如字符和武器,他们的价值可以在游戏中改变,这样的限制。

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

这里有两个可能的解决方案: 1.发布针对不同字段值的所有组合,并根据用户的当前状态进行订阅。但是,在呈现页面之前,我将使用铁路由器的waitOn功能来加载订阅。所以我不太相信我可以在游戏中改变订阅。此外,因为这是一个时间敏感的游戏,我想改变订阅将需要时间,在游戏期间,破坏游戏的乐趣。

  1. 我现在的问题是用户输入 Collection.find({})

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

EN

回答 1

Stack Overflow用户

发布于 2015-10-27 06:27:10

在“流星”中,解决这个问题的方法通常是使用两种出版物。如果您的游戏状态是由单个文档表示的,那么很容易实现这一点可能会有问题,因此为了举一个示例,我将暂时假设您有一个Participants集合,您将在其中存储相应的数据。

因此,无论如何,你应该有一个订阅与所有球员可用的数据,例如。

代码语言:javascript
复制
Meteor.publish('players', function (gameId) {
  return Participants.find({ gameId: gameId }, { fields: {
    // exclude the "character" field from the result
    character: 0
  }});
});

以及另一项私人播放器数据的订阅:

代码语言:javascript
复制
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,
  }); 
});

现在,在客户端,唯一需要做的事情是订阅这两个数据集,因此:

代码语言:javascript
复制
Meteor.subscribe('players', myGameId);
Meteor.subscribe('myPrivateData', myGameId);

Meteor将足够聪明地将传入的数据合并到一个Participants集合中,在该集合中,其他参与者的文档将不包含character字段。

编辑

如果您的字段可见性将动态更改,我建议采用以下方法:

  • 将所有受限制的属性放入一个单独的集合中,该集合可以准确地跟踪谁可以查看哪个字段。
  • 在客户端,使用observe将该集合集成到本地播放器表示中,以便更容易地访问数据。

数据模型

例如,集合可能如下所示:

代码语言:javascript
复制
PlayerProperties = new Mongo.Collection('playerProperties');
/* schema:

     userId    : String
     gameId    : String
     key       : String
     value     : *
     whoCanSee : [String]
*/

发布数据

首先,您需要向每个玩家公开自己的属性。

代码语言:javascript
复制
Meteor.publish('myProperties', function (gameId) {
  return PlayerProperties.find({
    userId: this.userId,
    gameId: gameId
  });
});

然后其他玩家属性:

代码语言:javascript
复制
Meteor.publish('otherPlayersProperties', function (gameId) {
  if (!this.userId) return [];
  return PlayerProperties.find({
    gameId: gameId,
    whoCanSee: this.userId,
  });
});

现在,您在游戏中需要做的唯一一件事就是确保一旦用户能够看到该属性,就将相应的userId添加到whoCanSee数组中。

改进

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

代码语言:javascript
复制
 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 ])
     });
   }
 });

这种数据“集成”只是一个草案,可以用许多不同的方式加以改进。它可以使用自定义发布方法在服务器端完成。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33356437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档