#include "network/protocols/start_game_protocol.hpp" #include "config/player_manager.hpp" #include "input/device_manager.hpp" #include "input/input_manager.hpp" #include "challenges/unlock_manager.hpp" #include "modes/world.hpp" #include "network/network_manager.hpp" #include "network/protocol_manager.hpp" #include "network/game_setup.hpp" #include "network/network_world.hpp" #include "network/protocols/synchronization_protocol.hpp" #include "online/online_profile.hpp" #include "race/race_manager.hpp" #include "states_screens/kart_selection.hpp" #include "states_screens/network_kart_selection.hpp" #include "utils/log.hpp" #include "utils/time.hpp" StartGameProtocol::StartGameProtocol(GameSetup* game_setup) : Protocol(NULL, PROTOCOL_START_GAME) { m_game_setup = game_setup; std::vector players = m_game_setup->getPlayers(); for (unsigned int i = 0; i < players.size(); i++) { m_player_states.insert(std::pair(players[i], LOADING)); } m_ready_count = 0; } StartGameProtocol::~StartGameProtocol() { } 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(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; } void StartGameProtocol::setup() { m_state = NONE; m_ready_count = 0; m_ready = false; Log::info("SynchronizationProtocol", "Ready !"); } bool sort_karts (NetworkPlayerProfile* a, NetworkPlayerProfile* b) { return (a->race_id < b->race_id); } void StartGameProtocol::update() { if (m_state == NONE) { // if no synchronization protocol exists, create one m_listener->requestStart(new SynchronizationProtocol()); Log::info("StartGameProtocol", "SynchronizationProtocol started."); // race startup sequence NetworkWorld::getInstance()->start(); // builds it and starts race_manager->setNumKarts(m_game_setup->getPlayerCount()); race_manager->setNumPlayers(m_game_setup->getPlayerCount()); race_manager->setNumLocalPlayers(1); std::vector players = m_game_setup->getPlayers(); std::sort(players.begin(), players.end(), sort_karts); // have to add self first for (unsigned int i = 0; i < players.size(); i++) { bool is_me = (players[i]->user_profile == PlayerManager::getCurrentOnlineProfile()); if (is_me) { NetworkPlayerProfile* profile = players[i]; RemoteKartInfo rki(profile->race_id, profile->kart_name, profile->user_profile->getUserName(), profile->race_id, !is_me); rki.setGlobalPlayerId(profile->race_id); rki.setLocalPlayerId(is_me?0:1); rki.setHostId(profile->race_id); PlayerProfile* profile_to_use = PlayerManager::getCurrentPlayer(); assert(profile_to_use); InputDevice* device = input_manager->getDeviceList()->getLatestUsedDevice(); int new_player_id = 0; if (StateManager::get()->getActivePlayers().size() >= 1) // more than one player, we're the first new_player_id = 0; else new_player_id = StateManager::get()->createActivePlayer( profile_to_use, device); device->setPlayer(StateManager::get()->getActivePlayer(new_player_id)); input_manager->getDeviceList()->setSinglePlayer(StateManager::get()->getActivePlayer(new_player_id)); race_manager->setPlayerKart(i, rki); race_manager->setLocalKartInfo(new_player_id, profile->kart_name); Log::info("StartGameProtocol", "Self player device added."); // self config NetworkWorld::getInstance()->m_self_kart = profile->kart_name; } } for (unsigned int i = 0; i < players.size(); i++) { bool is_me = (players[i]->user_profile == PlayerManager::getCurrentOnlineProfile()); NetworkPlayerProfile* profile = players[i]; RemoteKartInfo rki(profile->race_id, profile->kart_name, profile->user_profile->getUserName(), profile->race_id, !is_me); rki.setGlobalPlayerId(profile->race_id); // on the server, the race id must be the local one. rki.setLocalPlayerId(m_listener->isServer()?profile->race_id:(is_me?0:1)); rki.setHostId(profile->race_id); Log::info("StartGameProtocol", "Creating kart %s for Player#%d with race_id %d", profile->kart_name.c_str(), i, profile->race_id); if (!is_me) { StateManager::get()->createActivePlayer( NULL, NULL ); race_manager->setPlayerKart(i, rki); } } race_manager->computeRandomKartList(); Log::info("StartGameProtocol", "Player configuration ready."); m_state = SYNCHRONIZATION_WAIT; /* KartSelectionScreen* s = KartSelectionScreen::getInstance(); s->setMultiplayer(false); s->setFromOverworld(false); s->push();*/ } else if (m_state == SYNCHRONIZATION_WAIT) { SynchronizationProtocol* protocol = static_cast (m_listener->getProtocol(PROTOCOL_SYNCHRONIZATION)); if (protocol) { // now the synchronization protocol exists. Log::info("StartGameProtocol", "Starting the race loading."); race_manager->startSingleRace("jungle", 1, false); World::getWorld()->setNetworkWorld(true); m_state = LOADING; } } else if (m_state == LOADING) { if (m_ready) { m_state = READY; } } else if (m_state == READY) { // set karts into the network game setup NetworkManager::getInstance()->getGameSetup()->bindKartsToProfiles(); m_state = EXITING; m_listener->requestTerminate(this); } } void StartGameProtocol::ready() // on clients, means the loading is finished { if (!m_listener->isServer()) // if we're a client { assert(NetworkManager::getInstance()->getPeerCount() == 1); NetworkString ns; ns.ai32(NetworkManager::getInstance()->getPeers()[0]->getClientServerToken()).ai8(1); Log::info("StartGameProtocol", "Player ready, notifying server."); m_listener->sendMessage(this, ns, true); m_state = READY; m_ready = true; return; } else // on the server { } }