我正在尝试使用Firestore数据库创建游戏,为了避免和客户端作弊,我想处理云功能内部的大多数操作。
我当前的Firestore结构如下:
matches: {
matchID1: {
//fields
matchname: "Test match",
timestamp: 12/6/2018 16:41:05 PM,
players: [playerID123, playerID345, playerID678],
//subcollections
attackPool: {
attackID123: {
playerID123: "punch"
}
attackID345: {
playerID123: "kick"
},
attackID678: {
playerID123: "headbutt"
}
}
}
}
匹配文档应可由客户端读取,但AttackPool仅可由客户端写入。
我这样构造数据,以便用户可以通过调用以下内容来获取他们所涉及的所有匹配项:
db.collection("matches").where("players", "array-contains", currentUserID)
,但这不会透露由于它们位于子集合中而受到的任何攻击,因此其他玩家的举动必须保密。在所有玩家攻击之后,比赛结束。
我的想法是然后创建云功能,以监视何时将条目写入AttackPool,届时它将捕获AttackPool中的所有攻击并达到父级比赛并抓住所有玩家。然后该功能将检查玩家数组中的每个玩家是否在AttackPool中都有一个条目,如果是,它将确定比赛已完成,确定获胜者,并分出奖励和积分。
到目前为止,这就是我的云功能:
exports.watchMatchAndAttackUpdates = functions.firestore
.document("matches/{matchId}/attackPool/{attackId}")
.onWrite((change, context) => {
//Get all attacks in attack pool
change.after.ref.parent.get().then(function(querySnapshot) {
const attackers = [];
querySnapshot.forEach(function(doc) {
attackers.push(doc.data())
});
//Get match data
change.after.ref.parent.parent.get().then(res => {
const matchData = res.data();
const players = matchData.players;
//Compare arrays to check that all players moved
//If so, complete match, divvy rewards
});
});
});
但是,我在这一点上停了下来,因为这一切似乎都确实是错误的。从get()请求隐藏集合的嵌套AttackPool似乎还可以,但是现在我的云函数具有多个DB调用,并且在多个级别/集合之间进行比较。必须有更好的方法。
所以我的问题是,构造这些集合的正确方法是什么?如果这是最好的方法,那么检查所有玩家是否发动进攻的最好方法是什么?