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功能在呈现页面之前加载订阅。所以我不太相信我可以在游戏期间更改订阅。另外,因为这是一个时间敏感的游戏,我猜更改订阅会在游戏过程中花费时间,破坏游戏乐趣
转到控制台并查看其他用户的字段。如果我将收藏名称更改为难以找到的名称,有人能发现收藏名称吗?我找不到在客户端查找集合的命令 在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字段进行订阅)如果您不介意更新您的问题并更详细地描述您的问题,那么我也可以更新我的答案。听起来合理吗?我编辑了我的问题并添加了更多细节。很抱歉,没有相关信息。