/*! \brief Called when a player asks to select a kart. * \param event : Event providing the information. * * Format of the data : * Byte 0 1 2 * ---------------------------------------------- * Size | 1 | 1 | N | * Data |player id | N (kart name size) | kart name | * ---------------------------------------------- */ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event) { if(m_state!=SELECTING) { Log::warn("Server", "Received kart selection while in state %d.", m_state); return; } if (!checkDataSize(event, 1)) return; const NetworkString &data = event->data(); STKPeer* peer = event->getPeer(); uint8_t player_id = data.getUInt8(); std::string kart_name; data.decodeString(&kart_name); // check if selection is possible if (!m_selection_enabled) { NetworkString *answer = getNetworkString(2); // selection still not started answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(2); peer->sendPacket(answer); delete answer; return; } // check if somebody picked that kart if (!m_setup->isKartAvailable(kart_name)) { NetworkString *answer = getNetworkString(2); // kart is already taken answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(0); peer->sendPacket(answer); delete answer; return; } // check if this kart is authorized if (!m_setup->isKartAllowed(kart_name)) { NetworkString *answer = getNetworkString(2); // kart is not authorized answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(1); peer->sendPacket(answer); delete answer; return; } // send a kart update to everyone NetworkString *answer = getNetworkString(3+kart_name.size()); // This message must be handled synchronously on the client. answer->setSynchronous(true); // kart update (3), 1, race id answer->addUInt8(LE_KART_SELECTION_UPDATE).addUInt8(player_id) .encodeString(kart_name); sendMessageToPeersChangingToken(answer); delete answer; m_setup->setPlayerKart(player_id, kart_name); } // kartSelectionRequested
/** Sends data to all peers except the specified one. * \param peer Peer which will not receive the message. * \param data Data to sent. * \param reliable If the data should be sent reliable or now. */ void STKHost::sendPacketExcept(STKPeer* peer, const NetworkString& data, bool reliable) { for (unsigned int i = 0; i < m_peers.size(); i++) { STKPeer* p = m_peers[i]; if (!p->isSamePeer(peer)) { p->sendPacket(data, reliable); } } } // sendPacketExcept
/*! \brief Called when a player asks for a connection. * \param event : Event providing the information. * * Format of the data : * Byte 0 1 * --------------------- * Size | 1 |1| | * Data | 4 |n| player name | * --------------------- */ void ServerLobbyRoomProtocol::connectionRequested(Event* event) { STKPeer* peer = event->getPeer(); const NetworkString &data = event->data(); // can we add the player ? if (m_setup->getPlayerCount() >= NetworkConfig::get()->getMaxPlayers() || m_state!=ACCEPTING_CLIENTS ) { NetworkString *message = getNetworkString(2); // Len, error code: 2 = busy, 0 = too many players message->addUInt8(LE_CONNECTION_REFUSED) .addUInt8(m_state!=ACCEPTING_CLIENTS ? 2 : 0); // send only to the peer that made the request peer->sendPacket(message); delete message; Log::verbose("ServerLobbyRoomProtocol", "Player refused"); return; } // Connection accepted. // ==================== std::string name_u8; int len = data.decodeString(&name_u8); core::stringw name = StringUtils::utf8ToWide(name_u8); std::string password; data.decodeString(&password); bool is_authorised = (password==NetworkConfig::get()->getPassword()); // Get the unique global ID for this player. m_next_player_id.lock(); m_next_player_id.getData()++; int new_player_id = m_next_player_id.getData(); m_next_player_id.unlock(); if(m_setup->getLocalMasterID()==0) m_setup->setLocalMaster(new_player_id); // The host id has already been incremented when the peer // was added, so it is the right id now. int new_host_id = STKHost::get()->getNextHostId(); // Notify everybody that there is a new player // ------------------------------------------- NetworkString *message = getNetworkString(3+1+name_u8.size()); // size of id -- id -- size of local id -- local id; message->addUInt8(LE_NEW_PLAYER_CONNECTED).addUInt8(new_player_id) .addUInt8(new_host_id).encodeString(name_u8); STKHost::get()->sendPacketExcept(peer, message); delete message; // Now answer to the peer that just connected // ------------------------------------------ RandomGenerator token_generator; // use 4 random numbers because rand_max is probably 2^15-1. uint32_t token = (uint32_t)((token_generator.get(RAND_MAX) & 0xff) << 24 | (token_generator.get(RAND_MAX) & 0xff) << 16 | (token_generator.get(RAND_MAX) & 0xff) << 8 | (token_generator.get(RAND_MAX) & 0xff)); peer->setClientServerToken(token); peer->setAuthorised(is_authorised); peer->setHostId(new_host_id); const std::vector<NetworkPlayerProfile*> &players = m_setup->getPlayers(); // send a message to the one that asked to connect // Estimate 10 as average name length NetworkString *message_ack = getNetworkString(4 + players.size() * (2+10)); // connection success -- size of token -- token message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt8(new_player_id) .addUInt8(new_host_id).addUInt8(is_authorised); // Add all players so that this user knows (this new player is only added // to the list of players later, so the new player's info is not included) for (unsigned int i = 0; i < players.size(); i++) { message_ack->addUInt8(players[i]->getGlobalPlayerId()) .addUInt8(players[i]->getHostId()) .encodeString(players[i]->getName()); } peer->sendPacket(message_ack); delete message_ack; NetworkPlayerProfile* profile = new NetworkPlayerProfile(name, new_player_id, new_host_id); m_setup->addPlayer(profile); NetworkingLobby::getInstance()->addPlayer(profile); Log::verbose("ServerLobbyRoomProtocol", "New player."); } // connectionRequested