Я разрабатываю веб-приложение, в котором мне нужно поведение в реальном времени для следующего сценария,
Приложение будет иметь два типа пользователей Player
а также Spectator
, Игроки могут присоединиться к игре, а зрители могут просто наблюдать.
Игра будет инициализирована администратором.
Зритель в основном кто-то кто может видеть список людей кто присоединился к игре. Конечно, это должно иметь значение в реальном времени, когда игрок отключается или новый игрок присоединяется к игре, зритель видит список в реальном времени.
Подводя итог, рассмотрим приведенный ниже пример
Spectator_1 joins Clan_101
Spectator_2 joins Clan_201
Player_1 joins Clan_101 // Need to broadcast this event to Spectator_1
Player_2 joins Clan_101 // Need to broadcast this event to Spectator_1
Player_1 disconnects Clan_101 // // Need to broadcast this event to Spectator_1
Player_11 joins Clan_201 // Need to broadcast this event to Spectator_2
Player_12 joins Clan_201 // // Need to broadcast this event to Spectator_2
Рассматривая текущую игру как тему / канал (Ratchet\Wamp\Topic
), Мне нужно транслировать зрителям следующие события player join
а также player left
на игру / тему, на которую подписались зрители.
я использую Храповые WebSockets для PHP на стороне сервера и автобан JS на стороне клиента
Ниже приведен код. Пока я могу отправлять информацию на сервер (с клиента), когда игрок присоединяется к игре или отключается от нее.
Но как мне передать эту информацию зрителей(конец клиента), когда игрок присоединяется или отключается.
player.html
<script src="scripts/autobahn.js" type="text/javascript"></script>
<script src="scripts/jquery-1.11.2.min.js" type="text/javascript"></script>
<script>
ab.connect(
'ws://localhost:8080',
function (session) {
appSession = session;
$('#btnJoinGame').on('click',function(){
session.publish('joingame', ['data','GAME_ID']);
});
});
</script>
spectator.html
<script>
var conn = new ab.Session(
'ws://localhost:8080',
function() {
conn.subscribe('spectator_GAME_ID', function(topic, data) {
console.log(topic);
console.log(data);
});
},
function() {
console.warn('WebSocket connection closed');
}
);
/* OR Using the legacy syntax */
/*
ab.connect(
'ws://localhost:8080',
function (session) {
session.subscribe("t1011", function (topic, event) {
console.log(event);
});
}
);
*/
</script>
Server.php
require __DIR__ . '/vendor/autoload.php';
use Ratchet\Wamp\WampServerInterface;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface as Conn;
class EventHandler implements WampServerInterface, MessageComponentInterface{
public function __construct(React\EventLoop\StreamSelectLoop $loop){
$this->loop = $loop;
}
public function onSubscribe(Conn $conn, $subscription, $params = array()){
$subscription->broadcast($this->data);
}
public function onPublish(Conn $conn, $topic, $params, array $exclude, array $eligible) {
if($topic->getId() === 'joingame'){
if(!isset($this->data[$params[1]])){
$this->data[$params[1]] = array($params[0]);
}else{
array_push($this->data[$params[1]], $params[0]);
}
}
/** DOES'NT WORKS **/
$newtopic = new Ratchet\Wamp\Topic('spectator_GAME_ID');
$this->onSubscribe($conn,$newtopic);
}
/*Omitting other methods for brevity*/
}
$loop = React\EventLoop\Factory::create();
$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
new Ratchet\Server\IoServer(
new Ratchet\Http\HttpServer(
new Ratchet\WebSocket\WsServer(
new Ratchet\Wamp\WampServer(
new EventHandler($loop) // This is my class. Pass in the loop!
)
)
),
$webSock
);
$loop->run();
Прежде всего, этот ответ, вероятно, уже слишком поздно для вас, хотя я отвечу на него для протокола.
После того, как вы установили несколько каналов в своем приложении: spectator_GAME_ID
Вы хотите видеть, кто играет в игру, которую вы смотрите. И причина, по которой вы используете WebSocket, заключается в том, что вы можете видеть изменения в реальном времени.
Прежде всего, вы должны понимать, что все темы — это разные каналы / идентификаторы игр.
Как только вы это поймете и будете использовать код, который представлен на странице примера самого храповика.
$entryData = json_decode($entry, true);
// If the lookup topic object isn't set there is no one to publish to
if (!array_key_exists($entryData['category'], $this->subscribedTopics)) {
return;
}
$topic = $this->subscribedTopics[$entryData['category']];
// re-send the data to all the clients subscribed to that category
$topic->broadcast($entryData);
В их примере они используют категории в своей строке JSON, вы, вероятно, измените это на gameId.
Как только вы это сделаете, вы сможете отправлять данные только тем людям, которые слушают определенный идентификатор игры.
Вторая часть вашего вопроса заключалась в том, чтобы отправить им обновления и узнать, что это за обновление.
Самый простой способ — добавить строку в объект JSON, который отправляется
{
"action": "join",
"gameId": "123", //so that you know to which game to publish it
"userIdThatJoined": "123456789", //whatever other data you need
"userNameThatJoined": "Foo Bar"}
После того, как это будет отправлено, вы должны получить его на стороне клиента и проверить действие; если действие «присоединиться», добавьте этого пользователя в свое имя. Если действие «оставить», удалите этого пользователя из списка.
Вы можете обновить свой дисплей в списке активных игроков с помощью некоторой функции, которая вызывается после обновления, или использовать простой ng-повтор от угла, а затем просто применить к нему новые значения.
Других решений пока нет …