流星多人游戏客户端不同步 - 如何调试?

Tom*_*und 5 meteor

我在Meteor中构建了一个简单的实时多人数学游戏,你可以在这里试试:http://mathplay.meteor.com

在本地玩(使用不同的浏览器),一切正常.但是当我和朋友在互联网上玩游戏时,客户经常会失去同步:一个玩家列出的活动问题实际上已经被其他玩家解决了.

我的猜测是,一些应该是仅服务器的代码会在其中一个客户端上执行.有关如何调试此行为的任何建议?

以下是用户提交答案时客户端上发生的情况:

Template.number_input.events[okcancel_events('#answertextbox')] = make_okcancel_handler({
    ok: function (text, event) {
        question = Questions.findOne({ order_number: Session.get("current_question_order_number") });
        if (question.answer == document.getElementById('answertextbox').value) {
            console.log('True');
            Questions.update(question._id, {$set: {text: question.text.substr(0, question.text.length - 1) + question.answer, player: Session.get("player_name")}});
            callGetNewQuestion();
        }
        else {
            console.log('False');
        }
        document.getElementById('answertextbox').value = "";
        document.getElementById('answertextbox').focus();
    }
});
Run Code Online (Sandbox Code Playgroud)

callGetNewQuestion()在客户端和服务器上触发:

getNewQuestion: function () {
    var nr1 = Math.round(Math.random() * 100);
    var nr2 = Math.round(Math.random() * 100);
    question_string = nr1 + " + " + nr2 + " = ?";
    question_answer = (nr1 + nr2);
    current_order_number = Questions.find({}).count() + 1;
    current_question_id = Questions.insert({ order_number: current_order_number, text: question_string, answer: question_answer });
    return Questions.findOne({_id: current_question_id});//current_question_id;
},
Run Code Online (Sandbox Code Playgroud)

完整源代码可供参考:https://github.com/tomsoderlund/MathPlay

Tam*_*man 3

你的问题在于:

callGetNewQuestion()在客户端和服务器上触发此操作

由于时间差异,这将生成一个不同的_id问题,以及一个不同的问题,然后该问题将被服务器生成的问题替换。然而,情况可能并非总是如此。这使得很容易让事情变得不同步,仅仅因为你的客户端正在生成自己的东西。


您需要找到一种更好的方法来确保客户端生成与服务器相同的数据。这可以通过确保随机数生成器以相同的方式播种来完成,从而每次都会给出相同的随机数。这将解决由于值不同而导致的任何闪烁问题。


然后,对于实际的错误,您可能不想这样做:

return Questions.findOne({_id: current_question_id});
Run Code Online (Sandbox Code Playgroud)

但改为执行此操作(仅在客户端上,在服务器上不执行任何操作):

Session.set('current_order', current_order_number); // ORDER! Not the _id / question_id.
Run Code Online (Sandbox Code Playgroud)

这样,您可以将以下内容放入模板助手中:

return Questions.findOne({ order_number: Session.get('current_order') });
Run Code Online (Sandbox Code Playgroud)

本质上,这将以反应方式在 Collection 上工作,而不依赖于返回值。