2015-12-27 3 views
0

Я пытаюсь создать простую многопользовательскую карточную игру в Метеор, и у меня есть два игрока с некоторыми картами. Теперь, когда я подписываюсь на коллекцию Игр, где в игровом документе есть игроки и их карты, все клиенты браузера получают все данные, и это плохо.Метеор: Скрыть части возвращенного документа

Я могу легко создать фильтр на стороне клиента, чтобы отображать только те карточки для этого одного пользователя и скрывать другие карты, но данные уже находятся в браузере, и любой, кто знал, что они делают, может просто увидеть, что данные. Было бы не так сложно написать небольшой клиентский скрипт, чтобы показывать его все время на странице.

я действительно нашел его в чуть менее минуты в консоли, она находится под this.Games._collection._docs._map [ «»], и вы можете видеть все карты для обоих игроков ...

Я увидел в учебнике Todo App, что мы можем отфильтровать строки для возврата, что хорошо. Но, мне интересно, можно ли фильтровать части возвращенных документов?

Итак, мой вопрос: Есть ли способ опубликовать данные в маске для клиентов?

То, что я имею в виду, например, коллекция игр что-то вроде этого:

game: { 
    player1: { 
    username: "john", 
    cards: "S8 HA D9 CQ C8" 
    } 
    player2: { 
    username: "mike", 
    cards: "HQ D7 SK H8 S7" 
    } 
} 

Клиент для "джон" должен получить так:

game: { 
    player1: { 
    username: "john", 
    cards: "S8 HA D9 CQ C8" 
    } 
    player2: { 
    username: "mike", 
    cards: "XX XX XX XX XX" 
    } 
} 

В то время как клиент для «микрофона» должен получить следующее:

game: { 
    player1: { 
    username: "john", 
    cards: "XX XX XX XX XX" 
    } 
    player2: { 
    username: "mike", 
    cards: "HQ D7 SK H8 S7" 
    } 
} 

Возможно, что-то подобное возможно и по-прежнему реагировать?

Или мне нужно разбить моих игроков на разные коллекции, а затем отфильтровать эти документы, возвращенные именем пользователя/доступом?

Но даже так что я все еще должен был бы маскировать карты, потому что мне еще нужно, чтобы показать , сколько карт «другой» игрок имеет в своих руках, не показывая, какие из них они ..

Я предполагаю, что, если это возможно, это должно быть что-то в

Meteor.publish("games", function() { 
    return Games.find({}); 
}); 

Но я не могу понять, что добавить туда, чтобы сделать его работу, как описано ...


EDIT: Я думаю, this section of the Meteor documentation может помочь мне здесь. Я попытаюсь сделать несколько публикаций из коллекции Игр, в которой публикуются только те данные, которые разрешено видеть всем, например, количество карт, которые есть у каждого игрока, и другое издание, которое показывает карты, только если пользователю разрешено их видеть.


EDIT 2: Hm.Из the Meteor documentation я вижу это:

// server: publish the rooms collection, minus secret info. 
Meteor.publish("rooms", function() { 
    return Rooms.find({}, {fields: {secretInfo: 0}}); 
}); 

// ... and publish secret info for rooms where the logged-in user 
// is an admin. If the client subscribes to both streams, the records 
// are merged together into the same documents in the Rooms collection. 
Meteor.publish("adminSecretInfo", function() { 
    return Rooms.find({admin: this.userId}, {fields: {secretInfo: 1}}); 
}); 

Итак, я попытался сделать то же самое, как это:

Meteor.publish("games", function() { 
    return Games.find({}, { 
     fields: { 
      "player1.cards": 0, 
      "player2.cards": 0 
     } 
    }); 
}); 

Meteor.publish("playerCards1", function() { 
    return Games.find({ "player1.userId": this.userId }, { 
     fields: { 
      "player1.cards": 1 
     } 
    }); 
}); 

Meteor.publish("playerCards2", function() { 
    return Games.find({ "player2.userId": this.userId }, { 
     fields: { 
      "player2.cards": 1 
     } 
    }); 
}); 

С, конечно же, на клиенте:

Meteor.subscribe("games"); 
Meteor.subscribe("playerCards1"); 
Meteor.subscribe("playerCards2"); 
Games = new Mongo.Collection("games"); 

Но карты теперь не прошел вообще. Это как если playerCards1 и playerCards1 публикует не работают ...

+0

попробуйте 'console.log' отлаживать публикацию. Вы можете быть удивлены;) –

+0

ну, он показывает userId, а затем не определен для документа «Игра», поскольку публикация происходит до создания игры ... но когда я перезапускаю один клиент, чтобы запустить его снова, он показывает документ игры правильно на основе критерии поиска ... Итак, я удивлен, что запрос в порядке, но просто не доходит до клиента :( –

+0

на основе вашего предыдущего вопроса о публикации, я предполагаю, что вы ввели код 'subscribe' в файл коллекции. Хорошая привычка. Можете ли вы поместить его в «роутер» или в «Шаблон». <ваш-шаблон-имя> .rendered'? –

ответ

0

я решил его с помощью reactive-publish пакета:

Meteor.publish("games", function() { 
    this.autorun(function (c) { 
     var game = Games.findOne({ 
      $or: [ 
       { "player1.userId": this.userId }, 
       { "player2.userId": this.userId } 
      ] 
     }); 
     if (game) { 
      if (this.userId === game.player1.userId) { 
       return Games.find({}, { fields: { "player2.cards": 0 } }); 
      } 
      if (this.userId === game.player1.userId) { 
       return Games.find({}, { fields: { "player1.cards": 0 } }); 
      } 
      return Games.find({ // this will return only one game 
       $or: [ 
        { "player1.userId": this.userId }, 
        { "player2.userId": this.userId } 
       ] 
      }, { 
        fields: { 
         "player1.cards": 0, 
         "player2.cards": 0 
        } 
       }); 
     } 
     return Games.find({}, { // this will all games 
      fields: { 
       "player1.cards": 0, 
       "player2.cards": 0 
      } 
     }); 
    }); 
}); 

EDIT: Сегодня я понял, что мое первое решение не хорошо, если у вас есть несколько игр в процессе, который является стандартным сценарием, потому что тогда пользователь, сидящий в игроке1 в одной игре, получит карты всех игроков-игроков во всех играх. Поэтому я обновил ответ на правильное решение, которое также устраняет эту проблему.

Смежные вопросы