/*! \brief Called when a player asks to select a kart. * \param event : Event providing the information. * * Format of the data : * Byte 0 1 5 6 N+6 * --------------------------------------------------- * Size | 1 | 4 | 1 | N | * Data | 4 | priv token | N (kart name size) | kart name | * --------------------------------------------------- */ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event) { NetworkString data = event->data(); STKPeer* peer = *(event->peer); if (!checkDataSizeAndToken(event, 6)) return; uint8_t kart_name_size = data.gui8(5); std::string kart_name = data.gs(6, kart_name_size); if (kart_name.size() != kart_name_size) { Log::error("ServerLobbyRoomProtocol", "Kart names sizes differ: told:" "%d, real: %d.", kart_name_size, kart_name.size()); return; } // check if selection is possible if (!m_selection_enabled) { NetworkString answer; answer.ai8(0x82).ai8(1).ai8(2); // selection still not started m_listener->sendMessage(this, peer, answer); return; } // check if somebody picked that kart if (!m_setup->isKartAvailable(kart_name)) { NetworkString answer; answer.ai8(0x82).ai8(1).ai8(0); // kart is already taken m_listener->sendMessage(this, peer, answer); return; } // check if this kart is authorized if (!m_setup->isKartAllowed(kart_name)) { NetworkString answer; answer.ai8(0x82).ai8(1).ai8(1); // kart is not authorized m_listener->sendMessage(this, peer, answer); return; } // send a kart update to everyone NetworkString answer; // kart update (3), 1, race id answer.ai8(0x03).ai8(1).ai8(peer->getPlayerProfile()->race_id); // kart name size, kart name answer.ai8(kart_name.size()).as(kart_name); m_listener->sendMessage(this, answer); m_setup->setPlayerKart(peer->getPlayerProfile()->race_id, kart_name); }
bool StartGameProtocol::notifyEventAsynchronous(Event* event) { NetworkString data = event->data(); if (data.size() < 5) { Log::error("StartGameProtocol", "Too short message."); return true; } uint32_t token = data.gui32(); uint8_t ready = data.gui8(4); STKPeer* peer = (*(event->peer)); if (peer->getClientServerToken() != token) { Log::error("StartGameProtocol", "Bad token received."); return true; } if (m_listener->isServer() && ready) // on server, player is ready { Log::info("StartGameProtocol", "One of the players is ready."); m_player_states[peer->getPlayerProfile()] = READY; m_ready_count++; if (m_ready_count == m_game_setup->getPlayerCount()) { // everybody ready, synchronize SynchronizationProtocol* protocol = static_cast<SynchronizationProtocol*>(m_listener->getProtocol(PROTOCOL_SYNCHRONIZATION)); if (protocol) { protocol->startCountdown(5000); // 5 seconds countdown Log::info("StartGameProtocol", "All players ready, starting countdown."); m_ready = true; return true; } else Log::error("StartGameProtocol", "The Synchronization protocol hasn't been started."); } } else // on the client, we shouldn't even receive messages. { Log::error("StartGameProtocol", "Received a message with bad format."); } return true; }
bool SynchronizationProtocol::notifyEventAsynchronous(Event* event) { if (event->type != EVENT_TYPE_MESSAGE) return true; NetworkString data = event->data(); if (data.size() < 10) { Log::warn("SynchronizationProtocol", "Received a message too short."); return true; } uint8_t talk_id = data.gui8(); uint32_t token = data.gui32(1); uint32_t request = data.gui8(5); uint32_t sequence = data.gui32(6); std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers(); assert(peers.size() > 0); if (m_listener->isServer()) { if (talk_id > peers.size()) { Log::warn("SynchronizationProtocol", "The ID isn't known."); return true; } } uint8_t peer_id = 0; for (unsigned int i = 0; i < peers.size(); i++) { if (peers[i]->isSamePeer(*event->peer)) { peer_id = i; } } if (peers[peer_id]->getClientServerToken() != token) { Log::warn("SynchronizationProtocol", "Bad token from peer %d", talk_id); return true; } if (request) { NetworkString response; response.ai8(data.gui8(talk_id)).ai32(token).ai8(0).ai32(sequence); m_listener->sendMessage(this, peers[peer_id], response, false); Log::verbose("SynchronizationProtocol", "Answering sequence %u", sequence); if (data.size() == 14 && !m_listener->isServer()) // countdown time in the message { uint32_t time_to_start = data.gui32(10); Log::debug("SynchronizationProtocol", "Request to start game in %d.", time_to_start); if (!m_countdown_activated) startCountdown(time_to_start); else m_countdown = (double)(time_to_start/1000.0); } else Log::verbose("SynchronizationProtocol", "No countdown for now."); } else // response { if (sequence >= m_pings[peer_id].size()) { Log::warn("SynchronizationProtocol", "The sequence# %u isn't known.", sequence); return true; } double current_time = StkTime::getRealTime(); m_total_diff[peer_id] += current_time - m_pings[peer_id][sequence]; Log::verbose("SynchronizationProtocol", "InstantPing is %u", (unsigned int)((current_time - m_pings[peer_id][sequence])*1000)); m_successed_pings[peer_id]++; m_average_ping[peer_id] = (int)((m_total_diff[peer_id]/m_successed_pings[peer_id])*1000.0); Log::debug("SynchronizationProtocol", "Ping is %u", m_average_ping[peer_id]); } return true; }