我试图了解以下情况的正确方法是什么:
多人游戏,每局结构化only
与两名球员。每场比赛/比赛将完全随机化
让我们假设 5 个用户同时“登录”我的应用程序,每个用户都“搜索”匹配项。每个用户都拥有一个名为 opponent
的属性等于对手uniqueID
(初始值等于 ""
。到目前为止一切顺利。
假设用户 1 与用户 3 匹配。用户 1 将更新他自己的 oppoent
对用户 3 的值(value) uniqueID
并且会对用户 3 做同样的事情
问题
1) 如果在同一时刻,用户 2 尝试对用户 3 进行相同操作怎么办? 2) 如果在同一时刻,用户 3 试图对用户 4 这样做怎么办?
要点
是否可以“锁定”用户值?或者一旦他们改变就卡住他们?我走错路了吗?
我在考虑使用 Security Rules
和 Validation
为了创造一致性,但我可能选择了错误的技术(FireBase)。有什么想法吗?
编辑
我已经尝试过的安全规则,由于某种原因仍然允许第三个设备更改“已更改的对手”值。
{
"rules": {
".read": true,
".write": true,
"Users" :
{
"$uid" : {
"opponent" :
{
".write" : "data.val() == 'empty' || data.val() == null",
".validate": "data.val() == null || data.val() == 'empty' || newData.parent().parent().child(newData.val())
.child('opponent').val() == $uid"
}
,".indexOn": "state"
}
}
}
}
最佳答案
您可以使用 Firebase security rules 验证很多事情.
例如,您可以说只有当用户当前没有对手时才能写入对手:
"users": {
"$uid": {
"opponent: {
".write": "!data.exists()"
}
}
}
通过此操作和以下操作:
ref.child('users').child(auth.uid).child('opponent').set('uid:1234');
ref.child('users').child(auth.uid).child('opponent').set('uid:2345');
第二个 set()
操作将失败,因为 opponent
属性此时已经有一个值。
您可以扩展它以验证对手必须相互引用:
"users": {
"$uid": {
"opponent: {
".write": "!data.exists()"
".validate": "newData.parent().parent().child(newData.val())
.child('opponent').val() == $uid"
}
}
}
- 从正在编写的
opponent
,我们向上两层回到users
:newData.parent().parent()
. - 然后我们进入对手的节点:
child(newData.val())
。 - 然后我们验证对手的
opponent
属性是否与我们的 uid 匹配:child('opponent').val() == $uid
。
现在上面的两个写操作都会失败,因为它们一次只设置对手一个。要解决此问题,您需要执行所谓的 multi-location update :
var updates = {};
updates['users/'+auth.uid+'/opponent'] = 'uid:1234';
updates['users/uid:1234/opponent'] = auth.uid;
ref.update(updates);
我们现在向 Firebase 服务器发送单个 update()
命令,将 uid 写入两个对手。这将满足安全规则。
一些注意事项:
- 这些只是帮助您入门的一些示例。虽然它们应该有效,但您需要编写自己的规则来满足您的安全需求。
- 这些规则只处理对手的写作。您可能还想测试游戏结束时会发生什么,您需要清除对手。
关于ios - FireBase - 维护/保证数据一致性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34678083/