У меня одноранговая игра для iPhone, которая работает довольно хорошо. Я создал таблицу для отображения доступных пиров, и я могу подключить (пока) до четырех устройств и играть в полный раунд игры от начала до конца:
одноранговый сборщик http://img715.imageshack.us/img715/6131/picture1tb.png
Но вот моя проблема ...
Я создаю GKSession
на одном устройстве с GKSessionModeClient
, а другое с GKSessionModeServer
. Клиент видит сервер, выбирает для подключения, затем сервер утверждает. Затем сервер может нажать «начать игру», когда все одноранговые узлы подключены.
Если - до запуска игры сервером - клиент нажимает кнопку «назад», чтобы перейти к предыдущему экрану, отображение пользовательского средства выбора одноранговой сети выводится из представления, и сеанс «уничтожается» ...
[_gkSession disconnectFromAllPeers];
[_gkSession setAvailable:NO];
[_gkSession setDelegate:nil];
[_gkSession setDataReceiveHandler:nil withContext:nil];
Теперь, если клиент возвращается к сборщику пиров и снова присоединяется к серверу, я снова получаю состояние GKSessionStateConnected
, но когда я sendDataToAllPeers:
ничего не достигает клиента. Это работает безупречно, если одно устройство запускает игру, и три устройства присоединяются, а затем сервер нажимает «начать игру». Но если кто-то выходит из игры до начала игры, воссоздание сеанса и присоединение завершается неудачно.
Есть идеи? Единственный мой хак, о котором я могу подумать на данный момент, - не дать пользователю нажимать «назад» после подключения к серверу, но это отстой… ему придется полностью выйти из приложения, если он передумает. Я в своем уме с этим, так как приложение работает, и мне нравится, за исключением этой проблемы с подключением. В некотором роде, но я могу видеть раздражение пользователя, если он не может запустить игру без перезапуска приложения, чтобы очистить сеансы.
Сделаю это щедростью, когда смогу. Пожалуйста, помогите!
Edit @ byteclub
- Правильно ли очищает сервер все соответствующие структуры данных, если
клиент уходит до начала игры?
Если клиент покидает игровое лобби после того, как сервер принимает свое соединение, сеанс клиента уничтожается:
- (void)destroySession
{
trace(@"destroySession");
self.gameDelegate = nil;
self.lobbyDelegate = nil;
[_gkSession disconnectFromAllPeers];
[_gkSession setAvailable:NO];
[_gkSession setDelegate:nil];
[_gkSession setDataReceiveHandler:nil withContext:nil];
[_peerList removeAllObjects];
}
Я не вызываю какие-либо методы disconnectFromPeers на устройстве сервера.
* Is the client-disconnect-cleanup procedure different for cases when the
игра уже запущена?
Немного, если клиент отключается, тогда все получают уведомление "равный выход", и игра заканчивается. Я не беспокоюсь о повторном подключении в этом случае. Это в основном в игровом лобби, где клиент может «Отменить», чтобы вернуться на домашний экран, где проблема. Сеанс клиента в этом случае уничтожается. Если они затем вернутся в вестибюль и будет выделен новый GKSession, они все еще смогут подключиться к серверу, но sendDataToAllPeers больше не будет работать после их подключения.
* Do you still have a problem if, before reconnecting, you restart the
клиент, но оставьте сервер работающим
как есть?
Клиент может восстановить соединение в любом случае. Я могу выйти, вернуться, перезапустить приложение и снова подключиться без проблем. Просто sendDataToPeers терпит неудачу, если сервер и клиент оба не будут перезапущены.
* Do you completely destroy GKSession object on the client side
когда пользователь нажимает «назад»?
Да. (см. код выше)
Я понимаю, что это, вероятно, безумно, чтобы отлаживать издалека, но если у вас есть какие-либо предложения относительно того, что я мог бы рассмотреть, я был бы признателен.