2013-07-11 12:03:28 +00:00
|
|
|
//
|
|
|
|
// SuperTuxKart - a fun racing game with go-kart
|
2015-03-30 11:31:42 +11:00
|
|
|
// Copyright (C) 2013-2015 SuperTuxKart-Team
|
2013-07-11 12:03:28 +00:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
|
|
|
// as published by the Free Software Foundation; either version 3
|
|
|
|
// of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
2016-11-23 09:39:33 +11:00
|
|
|
#include "network/protocols/client_lobby.hpp"
|
2013-07-10 20:15:17 +00:00
|
|
|
|
2014-04-10 16:32:58 +10:00
|
|
|
#include "config/player_manager.hpp"
|
2014-03-07 11:02:07 +11:00
|
|
|
#include "modes/world_with_rank.hpp"
|
2015-10-21 17:39:53 +11:00
|
|
|
#include "network/event.hpp"
|
2016-02-11 09:03:51 +11:00
|
|
|
#include "network/network_config.hpp"
|
2015-11-26 07:41:37 +11:00
|
|
|
#include "network/network_player_profile.hpp"
|
2015-10-27 08:23:59 +11:00
|
|
|
#include "network/protocol_manager.hpp"
|
2016-11-28 08:45:17 +11:00
|
|
|
#include "network/protocols/latency_protocol.hpp"
|
2016-02-11 09:03:51 +11:00
|
|
|
#include "network/race_event_manager.hpp"
|
2015-10-27 08:23:59 +11:00
|
|
|
#include "network/stk_host.hpp"
|
|
|
|
#include "network/stk_peer.hpp"
|
2014-03-07 11:02:07 +11:00
|
|
|
#include "online/online_profile.hpp"
|
2015-11-27 23:05:05 +11:00
|
|
|
#include "states_screens/networking_lobby.hpp"
|
2013-07-26 12:49:05 +00:00
|
|
|
#include "states_screens/network_kart_selection.hpp"
|
2016-03-17 17:19:21 +11:00
|
|
|
#include "states_screens/race_result_gui.hpp"
|
2014-03-07 11:02:07 +11:00
|
|
|
#include "states_screens/state_manager.hpp"
|
2013-07-10 20:15:17 +00:00
|
|
|
#include "utils/log.hpp"
|
|
|
|
|
2016-11-18 09:08:37 +11:00
|
|
|
// ============================================================================
|
2016-11-28 18:09:38 +11:00
|
|
|
/** The protocol that manages starting a race with the server. It uses a
|
|
|
|
* finite state machine:
|
|
|
|
\dot
|
|
|
|
digraph interaction {
|
|
|
|
"NONE" -> "LINKED" [label="ENet connection with server established"]
|
|
|
|
"LINKED" -> "REQUESTING_CONNECTION" [label="Request connection from server"]
|
|
|
|
"REQUESTING_CONNECTION" -> CONNECTED [label="Connection accepted by server"]
|
|
|
|
"REQUESTING_CONNECTION" -> "?? TO BE DONE ??" [label="Connection refused by server"]
|
|
|
|
"CONNECTED" -> "KART_SELECTION" [label="Server tells us to start kart selection"]
|
|
|
|
"KART_SELECTION" -> "SELECTING_KARTS" [label="Show kart selection screen"]
|
|
|
|
"SELECTING_KARTS" -> "PLAYING" [label="Server sends start race message"]
|
|
|
|
}
|
|
|
|
\enddot
|
|
|
|
Note that some states are actually managed outside of the client lobby. For
|
|
|
|
example to select race details after selecting a kart is managed by the GUI
|
|
|
|
engine.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2016-11-23 18:39:59 +11:00
|
|
|
ClientLobby::ClientLobby() : LobbyProtocol(NULL)
|
2013-07-10 22:46:23 +00:00
|
|
|
{
|
2016-11-18 09:08:37 +11:00
|
|
|
|
|
|
|
m_server_address.clear();
|
2013-07-10 20:15:17 +00:00
|
|
|
m_server = NULL;
|
2016-03-09 07:46:33 +11:00
|
|
|
setHandleDisconnections(true);
|
2016-11-23 09:39:33 +11:00
|
|
|
} // ClientLobby
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2016-11-23 09:39:33 +11:00
|
|
|
ClientLobby::~ClientLobby()
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-11-23 09:39:33 +11:00
|
|
|
} // ClientLobby
|
2013-07-10 20:15:17 +00:00
|
|
|
|
2016-11-18 09:08:37 +11:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Sets the address of the server.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::setAddress(const TransportAddress &address)
|
2016-11-18 09:08:37 +11:00
|
|
|
{
|
|
|
|
m_server_address.copy(address);
|
|
|
|
} // setAddress
|
2013-07-10 20:15:17 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::setup()
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup = STKHost::get()->setupNewGame(); // create a new game setup
|
2013-07-10 20:15:17 +00:00
|
|
|
m_state = NONE;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // setup
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-11 16:42:35 +11:00
|
|
|
/** Sends the selection of a kart from this client to the server.
|
|
|
|
* \param player_id The global player id of the voting player.
|
|
|
|
* \param kart_name Name of the selected kart.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::requestKartSelection(uint8_t player_id,
|
2016-11-24 08:56:30 +11:00
|
|
|
const std::string &kart_name)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-03-11 16:42:35 +11:00
|
|
|
NetworkString *request = getNetworkString(3+kart_name.size());
|
|
|
|
request->addUInt8(LE_KART_SELECTION).addUInt8(player_id)
|
|
|
|
.encodeString(kart_name);
|
2016-03-01 09:56:33 +11:00
|
|
|
sendToServer(request, /*reliable*/ true);
|
2016-02-28 16:42:32 +11:00
|
|
|
delete request;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // requestKartSelection
|
2013-09-22 20:40:14 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-11 16:42:35 +11:00
|
|
|
/** Sends a vote for a major vote from a client to the server. Note that even
|
|
|
|
* this client will only store the vote when it is received back from the
|
|
|
|
* server.
|
|
|
|
* \param player_id The global player id of the voting player.
|
|
|
|
* \param major Major mode voted for.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::voteMajor(uint8_t player_id, uint32_t major)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-03-11 16:42:35 +11:00
|
|
|
NetworkString *request = getNetworkString(6);
|
|
|
|
request->addUInt8(LE_VOTE_MAJOR).addUInt8(player_id)
|
|
|
|
.addUInt32(major);
|
2016-02-28 16:18:08 +11:00
|
|
|
sendToServer(request, true);
|
2016-02-23 16:29:57 +11:00
|
|
|
delete request;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // voteMajor
|
2013-09-22 20:40:14 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-11 16:42:35 +11:00
|
|
|
/** Sends a vote for the number of tracks from a client to the server. Note
|
|
|
|
* that even this client will only store the vote when it is received back
|
|
|
|
* from the server.
|
|
|
|
* \param player_id The global player id of the voting player.
|
|
|
|
* \param count NUmber of tracks to play.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::voteRaceCount(uint8_t player_id, uint8_t count)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-03-11 16:42:35 +11:00
|
|
|
NetworkString *request = getNetworkString(3);
|
|
|
|
request->addUInt8(LE_VOTE_RACE_COUNT).addUInt8(player_id).addUInt8(count);
|
2016-02-28 16:18:08 +11:00
|
|
|
sendToServer(request, true);
|
2016-02-23 16:29:57 +11:00
|
|
|
delete request;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // voteRaceCount
|
2013-09-22 20:40:14 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-11 16:42:35 +11:00
|
|
|
/** Sends a vote for the minor game mode from a client to the server. Note that
|
|
|
|
* even this client will only store the vote when it is received back from the
|
|
|
|
* server.
|
|
|
|
* \param player_id The global player id of the voting player.
|
|
|
|
* \param minor Voted minor mode.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::voteMinor(uint8_t player_id, uint32_t minor)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-03-11 16:42:35 +11:00
|
|
|
NetworkString *request = getNetworkString(6);
|
|
|
|
request->addUInt8(LE_VOTE_MINOR).addUInt8(player_id).addUInt32(minor);
|
2016-02-28 16:18:08 +11:00
|
|
|
sendToServer(request, true);
|
2016-02-23 16:29:57 +11:00
|
|
|
delete request;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // voteMinor
|
2013-09-22 20:40:14 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-11 16:42:35 +11:00
|
|
|
/** Sends the vote about which track to play at which place in the list of
|
|
|
|
* tracks (like a custom GP definition). Note that even this client will only
|
|
|
|
* store the vote when it is received back from the server.
|
|
|
|
* \param player_id The global player id of the voting player.
|
|
|
|
* \param track Name of the track.
|
|
|
|
* \param At which place in the list of tracks this track should be played.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::voteTrack(uint8_t player_id,
|
2016-03-11 16:42:35 +11:00
|
|
|
const std::string &track,
|
2015-11-19 14:20:10 +11:00
|
|
|
uint8_t track_nb)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
NetworkString *request = getNetworkString(2+1+track.size());
|
2016-03-11 16:42:35 +11:00
|
|
|
request->addUInt8(LE_VOTE_TRACK).addUInt8(player_id).addUInt8(track_nb)
|
|
|
|
.encodeString(track);
|
2016-02-28 16:18:08 +11:00
|
|
|
sendToServer(request, true);
|
2016-02-23 16:29:57 +11:00
|
|
|
delete request;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // voteTrack
|
2013-09-22 20:40:14 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-11 16:42:35 +11:00
|
|
|
/** Sends a vote if a track at a specified place in the list of all tracks
|
|
|
|
* should be played in reverse or not. Note that even this client will only
|
|
|
|
* store the vote when it is received back from the server.
|
|
|
|
* \param player_id Global player id of the voting player.
|
|
|
|
* \param reversed True if the track should be played in reverse.
|
|
|
|
* \param track_nb Index for the track to be voted on in the list of all
|
|
|
|
* tracks.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::voteReversed(uint8_t player_id, bool reversed,
|
2016-03-11 16:42:35 +11:00
|
|
|
uint8_t track_nb)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-02-28 14:58:15 +11:00
|
|
|
NetworkString *request = getNetworkString(9);
|
2016-03-11 16:42:35 +11:00
|
|
|
request->addUInt8(LE_VOTE_REVERSE).addUInt8(player_id).addUInt8(reversed)
|
|
|
|
.addUInt8(track_nb);
|
2016-02-28 16:18:08 +11:00
|
|
|
sendToServer(request, true);
|
2016-02-23 16:29:57 +11:00
|
|
|
delete request;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // voteReversed
|
2013-09-22 20:40:14 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-11 16:42:35 +11:00
|
|
|
/** Vote for the number of laps of the specified track. Note that even this
|
|
|
|
* client will only store the vote when it is received back from the server.
|
|
|
|
* \param player_id Global player id of the voting player.
|
|
|
|
* \param laps Number of laps for the specified track.
|
|
|
|
* \param track_nb Index of the track in the list of all tracks.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::voteLaps(uint8_t player_id, uint8_t laps,
|
2016-03-11 16:42:35 +11:00
|
|
|
uint8_t track_nb)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-02-28 14:58:15 +11:00
|
|
|
NetworkString *request = getNetworkString(10);
|
2016-03-11 16:42:35 +11:00
|
|
|
request->addUInt8(LE_VOTE_LAPS).addUInt8(player_id).addUInt8(laps)
|
|
|
|
.addUInt8(track_nb);
|
2016-02-28 16:18:08 +11:00
|
|
|
sendToServer(request, true);
|
2016-03-03 09:39:14 +11:00
|
|
|
delete request;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // voteLaps
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-17 17:19:21 +11:00
|
|
|
/** Called when a client selects to exit a server.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::leave()
|
2013-07-29 15:27:25 +00:00
|
|
|
{
|
2013-07-29 23:43:28 +00:00
|
|
|
m_server->disconnect();
|
2015-12-01 08:19:48 +11:00
|
|
|
STKHost::get()->removePeer(m_server);
|
2015-10-16 00:52:28 +11:00
|
|
|
m_server_address.clear();
|
2015-12-01 17:43:43 +11:00
|
|
|
ServersManager::get()->unsetJoinedServer();
|
2015-10-12 21:37:22 +11:00
|
|
|
} // leave
|
2013-07-29 15:27:25 +00:00
|
|
|
|
2016-03-17 17:19:21 +11:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Called from the gui when a client clicked on 'continue' on the race result
|
|
|
|
* screen. It notifies the server that this client has exited the screen and
|
|
|
|
* is back at the lobby.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::doneWithResults()
|
2016-03-17 17:19:21 +11:00
|
|
|
{
|
|
|
|
NetworkString *done = getNetworkString(1);
|
|
|
|
done->addUInt8(LE_RACE_FINISHED_ACK);
|
|
|
|
sendToServer(done, /*reliable*/true);
|
|
|
|
delete done;
|
|
|
|
} // doneWithResults
|
|
|
|
|
2013-07-29 15:27:25 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2016-11-23 09:39:33 +11:00
|
|
|
bool ClientLobby::notifyEvent(Event* event)
|
2013-08-01 19:49:57 +00:00
|
|
|
{
|
2016-11-22 17:57:15 +11:00
|
|
|
assert(m_game_setup); // assert that the setup exists
|
2013-08-01 19:55:09 +00:00
|
|
|
|
2016-03-17 17:19:21 +11:00
|
|
|
NetworkString &data = event->data();
|
|
|
|
assert(data.size()); // assert that data isn't empty
|
|
|
|
uint8_t message_type = data.getUInt8();
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby", "Synchronous message of type %d",
|
2016-03-17 17:19:21 +11:00
|
|
|
message_type);
|
|
|
|
switch(message_type)
|
|
|
|
{
|
|
|
|
case LE_KART_SELECTION_UPDATE: kartSelectionUpdate(event); break;
|
2016-11-22 17:57:15 +11:00
|
|
|
case LE_LOAD_WORLD: loadWorld(); break;
|
2016-03-17 17:19:21 +11:00
|
|
|
case LE_RACE_FINISHED: raceFinished(event); break;
|
|
|
|
case LE_EXIT_RESULT: exitResultScreen(event); break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
} // switch
|
|
|
|
return true;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // notifyEvent
|
2013-08-01 19:49:57 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2016-11-23 09:39:33 +11:00
|
|
|
bool ClientLobby::notifyEventAsynchronous(Event* event)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-11-22 17:57:15 +11:00
|
|
|
assert(m_game_setup); // assert that the setup exists
|
2015-10-21 08:07:00 +11:00
|
|
|
if (event->getType() == EVENT_TYPE_MESSAGE)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
NetworkString &data = event->data();
|
2013-08-01 19:49:57 +00:00
|
|
|
assert(data.size()); // assert that data isn't empty
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t message_type = data.getUInt8();
|
2013-08-21 19:04:46 +00:00
|
|
|
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby", "Asynchronous message of type %d",
|
2015-11-19 14:20:10 +11:00
|
|
|
message_type);
|
2015-11-21 10:39:56 +11:00
|
|
|
switch(message_type)
|
|
|
|
{
|
|
|
|
case LE_NEW_PLAYER_CONNECTED: newPlayer(event); break;
|
|
|
|
case LE_PLAYER_DISCONNECTED : disconnectedPlayer(event); break;
|
|
|
|
case LE_START_RACE: startGame(event); break;
|
|
|
|
case LE_START_SELECTION: startSelection(event); break;
|
|
|
|
case LE_CONNECTION_REFUSED: connectionRefused(event); break;
|
|
|
|
case LE_CONNECTION_ACCEPTED: connectionAccepted(event); break;
|
|
|
|
case LE_KART_SELECTION_REFUSED: kartSelectionRefused(event); break;
|
|
|
|
case LE_VOTE_MAJOR : playerMajorVote(event); break;
|
|
|
|
case LE_VOTE_RACE_COUNT: playerRaceCountVote(event); break;
|
|
|
|
case LE_VOTE_MINOR: playerMinorVote(event); break;
|
|
|
|
case LE_VOTE_TRACK: playerTrackVote(event); break;
|
|
|
|
case LE_VOTE_REVERSE: playerReversedVote(event); break;
|
|
|
|
case LE_VOTE_LAPS: playerLapsVote(event); break;
|
|
|
|
} // switch
|
2013-08-21 19:04:46 +00:00
|
|
|
|
2013-08-01 19:55:09 +00:00
|
|
|
return true;
|
2013-07-10 20:15:17 +00:00
|
|
|
} // message
|
2015-11-19 14:20:10 +11:00
|
|
|
else if (event->getType() == EVENT_TYPE_DISCONNECTED)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2015-11-28 12:33:01 +11:00
|
|
|
// This means we left essentially.
|
|
|
|
// We can't delete STKHost from this thread, since the main
|
|
|
|
// thread might still test if STKHost exists and then call
|
|
|
|
// the ProtocolManager, which might already have been deleted.
|
2016-03-09 07:46:33 +11:00
|
|
|
// So only signal that STKHost should exit, which will be tested
|
2015-11-28 12:33:01 +11:00
|
|
|
// from the main thread.
|
|
|
|
STKHost::get()->requestShutdown();
|
2013-08-01 19:55:09 +00:00
|
|
|
return true;
|
2013-07-10 20:15:17 +00:00
|
|
|
} // disconnection
|
2013-08-01 19:55:09 +00:00
|
|
|
return false;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // notifyEventAsynchronous
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::update(float dt)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
|
|
|
switch (m_state)
|
|
|
|
{
|
|
|
|
case NONE:
|
2015-10-26 18:31:32 +11:00
|
|
|
if (STKHost::get()->isConnectedTo(m_server_address))
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
|
|
|
m_state = LINKED;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LINKED:
|
|
|
|
{
|
2015-11-27 08:24:02 +11:00
|
|
|
core::stringw name;
|
|
|
|
if(PlayerManager::getCurrentOnlineState()==PlayerProfile::OS_SIGNED_IN)
|
|
|
|
name = PlayerManager::getCurrentOnlineUserName();
|
|
|
|
else
|
|
|
|
name = PlayerManager::getCurrentPlayer()->getName();
|
|
|
|
|
|
|
|
std::string name_u8 = StringUtils::wideToUtf8(name);
|
2016-02-11 09:03:51 +11:00
|
|
|
const std::string &password = NetworkConfig::get()->getPassword();
|
2016-02-28 14:58:15 +11:00
|
|
|
NetworkString *ns = getNetworkString(6+1+name_u8.size()
|
2016-02-23 16:29:57 +11:00
|
|
|
+1+password.size());
|
2015-11-20 16:41:54 +11:00
|
|
|
// 4 (size of id), global id
|
2016-02-23 16:29:57 +11:00
|
|
|
ns->addUInt8(LE_CONNECTION_REQUESTED).encodeString(name)
|
2016-02-11 09:03:51 +11:00
|
|
|
.encodeString(NetworkConfig::get()->getPassword());
|
2016-02-28 16:18:08 +11:00
|
|
|
sendToServer(ns);
|
2016-02-23 16:29:57 +11:00
|
|
|
delete ns;
|
2013-07-10 20:15:17 +00:00
|
|
|
m_state = REQUESTING_CONNECTION;
|
2013-08-21 19:04:46 +00:00
|
|
|
}
|
|
|
|
break;
|
2013-07-10 20:15:17 +00:00
|
|
|
case REQUESTING_CONNECTION:
|
|
|
|
break;
|
|
|
|
case CONNECTED:
|
|
|
|
break;
|
2013-07-26 23:47:43 +00:00
|
|
|
case KART_SELECTION:
|
2013-07-27 23:13:03 +00:00
|
|
|
{
|
2015-11-19 14:20:10 +11:00
|
|
|
NetworkKartSelectionScreen* screen =
|
|
|
|
NetworkKartSelectionScreen::getInstance();
|
2014-09-23 16:43:50 +10:00
|
|
|
screen->push();
|
2013-07-26 23:47:43 +00:00
|
|
|
m_state = SELECTING_KARTS;
|
2016-11-25 22:17:24 +11:00
|
|
|
|
2016-11-28 08:45:17 +11:00
|
|
|
Protocol *p = new LatencyProtocol();
|
2016-11-25 22:17:24 +11:00
|
|
|
p->requestStart();
|
2016-11-28 08:45:17 +11:00
|
|
|
Log::info("LobbyProtocol", "LatencyProtocol started.");
|
2013-08-21 19:04:46 +00:00
|
|
|
}
|
|
|
|
break;
|
2013-07-26 12:49:05 +00:00
|
|
|
case SELECTING_KARTS:
|
|
|
|
break;
|
|
|
|
case PLAYING:
|
2016-03-17 17:19:21 +11:00
|
|
|
break;
|
2013-08-21 13:54:50 +00:00
|
|
|
case RACE_FINISHED:
|
|
|
|
break;
|
2013-07-10 20:15:17 +00:00
|
|
|
case DONE:
|
2013-07-18 15:58:46 +00:00
|
|
|
m_state = EXITING;
|
2015-10-24 12:39:17 +11:00
|
|
|
ProtocolManager::getInstance()->requestTerminate(this);
|
2013-07-10 20:15:17 +00:00
|
|
|
break;
|
2013-07-18 17:56:32 +00:00
|
|
|
case EXITING:
|
|
|
|
break;
|
2013-07-10 20:15:17 +00:00
|
|
|
}
|
2015-10-12 21:37:22 +11:00
|
|
|
} // update
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*! \brief Called when a new player is connected to the server
|
|
|
|
* \param event : Event providing the information.
|
2013-07-10 22:46:23 +00:00
|
|
|
*
|
2013-07-10 20:15:17 +00:00
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0 1 2
|
|
|
|
* -------------------------------------
|
|
|
|
* Size | 1 | 1 | |
|
|
|
|
* Data | player_id | hostid | player name |
|
|
|
|
* -------------------------------------
|
2013-07-10 20:15:17 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::newPlayer(Event* event)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if (!checkDataSize(event, 2)) return;
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2015-11-27 08:55:21 +11:00
|
|
|
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t player_id = data.getUInt8();
|
|
|
|
uint8_t host_id = data.getUInt8();
|
2015-11-27 08:55:21 +11:00
|
|
|
core::stringw name;
|
2016-03-13 13:49:43 +11:00
|
|
|
data.decodeStringW(&name);
|
2015-12-01 07:57:42 +11:00
|
|
|
// FIXME need adjusting when splitscreen is used/
|
|
|
|
if(STKHost::get()->getGameSetup()->isLocalMaster(player_id))
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::error("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"The server notified me that I'm a new player in the "
|
|
|
|
"room (not normal).");
|
2013-07-10 20:15:17 +00:00
|
|
|
}
|
2016-11-22 17:57:15 +11:00
|
|
|
else if (m_game_setup->getProfile(player_id) == NULL)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::verbose("ClientLobby", "New player connected.");
|
2016-03-11 16:42:35 +11:00
|
|
|
NetworkPlayerProfile* profile =
|
|
|
|
new NetworkPlayerProfile(name, player_id, host_id);
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->addPlayer(profile);
|
2015-11-27 23:05:05 +11:00
|
|
|
NetworkingLobby::getInstance()->addPlayer(profile);
|
2013-07-10 20:15:17 +00:00
|
|
|
}
|
2013-07-11 15:35:31 +00:00
|
|
|
else
|
|
|
|
{
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::error("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"One of the player notified in the list is myself.");
|
2013-07-11 15:35:31 +00:00
|
|
|
}
|
2015-10-12 21:37:22 +11:00
|
|
|
} // newPlayer
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*! \brief Called when a new player is disconnected
|
|
|
|
* \param event : Event providing the information.
|
2013-07-10 22:46:23 +00:00
|
|
|
*
|
2013-07-10 20:15:17 +00:00
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0
|
2016-03-11 16:42:35 +11:00
|
|
|
* --------------
|
|
|
|
* Size | 1 |
|
|
|
|
* Data | player id *|
|
|
|
|
* --------------
|
2013-07-10 20:15:17 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::disconnectedPlayer(Event* event)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if (!checkDataSize(event, 1)) return;
|
|
|
|
|
2016-03-11 16:42:35 +11:00
|
|
|
NetworkString &data = event->data();
|
|
|
|
while(data.size()>0)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-03-13 13:49:43 +11:00
|
|
|
const NetworkPlayerProfile *profile =
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->getProfile(data.getUInt8());
|
|
|
|
if (m_game_setup->removePlayer(profile))
|
2016-03-11 16:42:35 +11:00
|
|
|
{
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby",
|
2016-03-11 16:42:35 +11:00
|
|
|
"Player %d removed successfully.",
|
|
|
|
profile->getGlobalPlayerId());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::error("ClientLobby",
|
2016-03-11 16:42:35 +11:00
|
|
|
"The disconnected peer wasn't known.");
|
|
|
|
}
|
|
|
|
} // while
|
|
|
|
|
2015-12-01 08:19:48 +11:00
|
|
|
STKHost::get()->removePeer(event->getPeer());
|
2015-10-12 21:37:22 +11:00
|
|
|
} // disconnectedPlayer
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*! \brief Called when the server accepts the connection.
|
|
|
|
* \param event : Event providing the information.
|
2013-07-10 22:46:23 +00:00
|
|
|
*
|
2013-07-10 20:15:17 +00:00
|
|
|
* Format of the data :
|
2016-02-26 16:38:59 +11:00
|
|
|
* Byte 0 1 2 3
|
|
|
|
* ---------------------------------------------------------
|
2016-03-01 09:56:33 +11:00
|
|
|
* Size | 1 | 1 | 1 | |
|
|
|
|
* Data | player_id| hostid | authorised |playernames* |
|
2016-02-26 16:38:59 +11:00
|
|
|
* ---------------------------------------------------------
|
2013-07-10 20:15:17 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::connectionAccepted(Event* event)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
// At least 3 bytes should remain now
|
|
|
|
if(!checkDataSize(event, 3)) return;
|
|
|
|
|
2016-02-28 14:58:15 +11:00
|
|
|
NetworkString &data = event->data();
|
2015-10-21 08:11:35 +11:00
|
|
|
STKPeer* peer = event->getPeer();
|
2013-07-10 20:15:17 +00:00
|
|
|
|
2015-11-27 08:24:02 +11:00
|
|
|
// Accepted
|
|
|
|
// ========
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby",
|
2015-11-27 08:24:02 +11:00
|
|
|
"The server accepted the connection.");
|
2013-07-12 14:08:33 +00:00
|
|
|
|
2015-11-27 08:24:02 +11:00
|
|
|
// self profile
|
|
|
|
irr::core::stringw name;
|
|
|
|
if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN)
|
|
|
|
name = PlayerManager::getCurrentOnlineUserName();
|
2013-07-11 13:39:36 +00:00
|
|
|
else
|
2015-11-27 08:24:02 +11:00
|
|
|
name = PlayerManager::getCurrentPlayer()->getName();
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t my_player_id = data.getUInt8();
|
|
|
|
uint8_t my_host_id = data.getUInt8();
|
|
|
|
uint8_t authorised = data.getUInt8();
|
2016-02-11 09:03:51 +11:00
|
|
|
// Store this client's authorisation status in the peer information
|
|
|
|
// for the server.
|
|
|
|
event->getPeer()->setAuthorised(authorised!=0);
|
2016-01-11 17:08:06 +11:00
|
|
|
STKHost::get()->setMyHostId(my_host_id);
|
|
|
|
|
2016-03-11 16:42:35 +11:00
|
|
|
NetworkPlayerProfile* profile =
|
|
|
|
new NetworkPlayerProfile(name, my_player_id, my_host_id);
|
2015-12-01 07:57:42 +11:00
|
|
|
STKHost::get()->getGameSetup()->setLocalMaster(my_player_id);
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->setNumLocalPlayers(1);
|
2015-11-27 08:24:02 +11:00
|
|
|
// connection token
|
2016-02-26 16:38:59 +11:00
|
|
|
uint32_t token = data.getToken();
|
2015-11-27 08:24:02 +11:00
|
|
|
peer->setClientServerToken(token);
|
|
|
|
|
|
|
|
// Add all players
|
|
|
|
// ===============
|
2016-02-26 16:38:59 +11:00
|
|
|
while (data.size() > 0)
|
2015-11-27 08:24:02 +11:00
|
|
|
{
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t player_id = data.getUInt8();
|
|
|
|
uint8_t host_id = data.getUInt8();
|
2015-11-27 08:24:02 +11:00
|
|
|
irr::core::stringw name;
|
2016-03-13 13:49:43 +11:00
|
|
|
int bytes_read = data.decodeStringW(&name);
|
2016-02-26 16:38:59 +11:00
|
|
|
|
2015-11-27 08:24:02 +11:00
|
|
|
NetworkPlayerProfile* profile2 =
|
2016-03-11 16:42:35 +11:00
|
|
|
new NetworkPlayerProfile(name, player_id, host_id);
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->addPlayer(profile2);
|
2016-01-05 17:32:46 +11:00
|
|
|
// Inform the network lobby of all players so that the GUI can
|
|
|
|
// show all currently connected players.
|
2015-11-27 23:05:05 +11:00
|
|
|
NetworkingLobby::getInstance()->addPlayer(profile2);
|
2015-11-27 08:24:02 +11:00
|
|
|
}
|
|
|
|
|
2016-01-14 08:20:14 +11:00
|
|
|
// Add self after other players so that player order is identical
|
|
|
|
// on server and all clients.
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->addPlayer(profile);
|
2016-01-14 08:20:14 +11:00
|
|
|
NetworkingLobby::getInstance()->addPlayer(profile);
|
2015-11-27 08:24:02 +11:00
|
|
|
m_server = event->getPeer();
|
|
|
|
m_state = CONNECTED;
|
2015-10-12 21:37:22 +11:00
|
|
|
} // connectionAccepted
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*! \brief Called when the server refuses the connection.
|
|
|
|
* \param event : Event providing the information.
|
2013-07-10 22:46:23 +00:00
|
|
|
*
|
2013-07-10 20:15:17 +00:00
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0
|
|
|
|
* ----------------
|
|
|
|
* Size | 1 |
|
|
|
|
* Data | refusal code |
|
|
|
|
* ----------------
|
2013-07-10 20:15:17 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::connectionRefused(Event* event)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if (!checkDataSize(event, 1)) return;
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2016-03-01 09:56:33 +11:00
|
|
|
|
2016-03-13 13:49:43 +11:00
|
|
|
switch (data.getUInt8()) // the second byte
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
|
|
|
case 0:
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"Connection refused : too many players.");
|
2013-07-10 20:15:17 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby", "Connection refused : banned.");
|
2013-07-10 20:15:17 +00:00
|
|
|
break;
|
2015-11-24 07:55:58 +11:00
|
|
|
case 2:
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby", "Client busy.");
|
2015-11-24 07:55:58 +11:00
|
|
|
break;
|
2013-07-10 20:15:17 +00:00
|
|
|
default:
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby", "Connection refused.");
|
2013-07-10 20:15:17 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-10-12 21:37:22 +11:00
|
|
|
} // connectionRefused
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*! \brief Called when the server refuses the kart selection request.
|
|
|
|
* \param event : Event providing the information.
|
2013-07-10 22:46:23 +00:00
|
|
|
*
|
2013-07-10 20:15:17 +00:00
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0
|
|
|
|
* ----------------
|
|
|
|
* Size | 1 |
|
|
|
|
* Data | refusal code |
|
|
|
|
* ----------------
|
2013-07-10 20:15:17 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::kartSelectionRefused(Event* event)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if(!checkDataSize(event, 1)) return;
|
|
|
|
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2013-07-10 20:15:17 +00:00
|
|
|
|
2016-03-13 13:49:43 +11:00
|
|
|
switch (data.getUInt8()) // the error code
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
|
|
|
case 0:
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"Kart selection refused : already taken.");
|
2013-07-10 20:15:17 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"Kart selection refused : not available.");
|
2013-07-10 20:15:17 +00:00
|
|
|
break;
|
|
|
|
default:
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby", "Kart selection refused.");
|
2013-07-10 20:15:17 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-10-12 21:37:22 +11:00
|
|
|
} // kartSelectionRefused
|
2013-07-10 20:15:17 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2013-07-10 22:46:23 +00:00
|
|
|
/*! \brief Called when the server tells to update a player's kart.
|
2013-07-10 20:15:17 +00:00
|
|
|
* \param event : Event providing the information.
|
2013-07-10 22:46:23 +00:00
|
|
|
*
|
2013-07-10 20:15:17 +00:00
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0 1 2 3 N+3
|
2015-12-10 17:35:31 +11:00
|
|
|
* --------------------------------------------------
|
2016-03-01 09:56:33 +11:00
|
|
|
* Size | 1 | 1 | N |
|
|
|
|
* Data | player id | N (kart name size) | kart name |
|
2015-12-10 17:35:31 +11:00
|
|
|
* --------------------------------------------------
|
2013-07-10 20:15:17 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::kartSelectionUpdate(Event* event)
|
2013-07-10 20:15:17 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if(!checkDataSize(event, 3)) return;
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t player_id = data.getUInt8();
|
2015-11-27 08:55:21 +11:00
|
|
|
std::string kart_name;
|
2016-03-13 13:49:43 +11:00
|
|
|
data.decodeString(&kart_name);
|
2016-11-22 17:57:15 +11:00
|
|
|
if (!m_game_setup->isKartAvailable(kart_name))
|
2013-07-10 22:46:23 +00:00
|
|
|
{
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::error("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"The updated kart is taken already.");
|
2013-07-10 22:46:23 +00:00
|
|
|
}
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->setPlayerKart(player_id, kart_name);
|
2015-11-20 17:02:47 +11:00
|
|
|
NetworkKartSelectionScreen::getInstance()->playerSelected(player_id,
|
|
|
|
kart_name);
|
2015-10-12 21:37:22 +11:00
|
|
|
} // kartSelectionUpdate
|
2013-07-10 22:46:23 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2013-07-14 21:19:22 +00:00
|
|
|
|
2016-11-25 22:17:24 +11:00
|
|
|
/*! \brief Called when the server broadcasts to start the race.
|
2016-11-18 09:08:37 +11:00
|
|
|
race needs to be started.
|
2016-03-01 09:56:33 +11:00
|
|
|
* \param event : Event providing the information (no additional information
|
|
|
|
* in this case).
|
2013-07-14 21:19:22 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::startGame(Event* event)
|
2013-07-14 21:19:22 +00:00
|
|
|
{
|
2016-02-28 16:42:32 +11:00
|
|
|
m_state = PLAYING;
|
2016-11-25 22:17:24 +11:00
|
|
|
// Triggers the world finite state machine to go from WAIT_FOR_SERVER_PHASE
|
|
|
|
// to READY_PHASE.
|
2016-11-22 17:57:15 +11:00
|
|
|
World::getWorld()->setReadyToRace();
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby", "Starting new game");
|
2015-10-12 21:37:22 +11:00
|
|
|
} // startGame
|
2013-07-14 21:19:22 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-11-25 22:17:24 +11:00
|
|
|
/** Called from WorldStatus when reaching the READY phase, i.e. when the race
|
|
|
|
* was started. It is going to inform the server of the race start. This
|
|
|
|
* allows the server to wait for all clients to start, so the server will
|
|
|
|
* be running behind the client with the biggest latency, which should
|
|
|
|
* make it likely that at local time T on the server all messages from
|
|
|
|
* all clients at their local time T have arrived.
|
|
|
|
*/
|
|
|
|
void ClientLobby::startingRaceNow()
|
|
|
|
{
|
|
|
|
NetworkString *ns = getNetworkString(2);
|
|
|
|
ns->addUInt8(LE_STARTED_RACE);
|
|
|
|
sendToServer(ns, /*reliable*/true);
|
2016-11-28 08:45:17 +11:00
|
|
|
terminateLatencyProtocol();
|
2016-11-25 22:17:24 +11:00
|
|
|
} // startingRaceNow
|
2013-07-26 12:49:05 +00:00
|
|
|
|
2016-11-25 22:17:24 +11:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-07-26 12:49:05 +00:00
|
|
|
/*! \brief Called when the kart selection starts.
|
2016-03-01 09:56:33 +11:00
|
|
|
* \param event : Event providing the information (no additional information
|
|
|
|
* in this case).
|
2013-07-26 12:49:05 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::startSelection(Event* event)
|
2013-07-26 12:49:05 +00:00
|
|
|
{
|
2016-02-28 16:42:32 +11:00
|
|
|
m_state = KART_SELECTION;
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby", "Kart selection starts now");
|
2015-10-12 21:37:22 +11:00
|
|
|
} // startSelection
|
2013-07-26 12:49:05 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2013-08-15 12:35:23 +00:00
|
|
|
|
|
|
|
/*! \brief Called when all karts have finished the race.
|
|
|
|
* \param event : Event providing the information.
|
|
|
|
*
|
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0 1
|
|
|
|
* -------------------------------
|
|
|
|
* Size | 1 | 1 | |
|
|
|
|
* Data | Kart 1 ID | kart id 2 | ... |
|
|
|
|
* -------------------------------
|
2013-08-15 12:35:23 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::raceFinished(Event* event)
|
2013-08-15 12:35:23 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if(!checkDataSize(event, 1)) return;
|
|
|
|
|
2016-02-28 14:58:15 +11:00
|
|
|
NetworkString &data = event->data();
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::error("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"Server notified that the race is finished.");
|
2013-08-21 19:04:46 +00:00
|
|
|
|
|
|
|
// stop race protocols
|
2015-11-20 17:02:47 +11:00
|
|
|
Protocol* protocol = ProtocolManager::getInstance()
|
|
|
|
->getProtocol(PROTOCOL_CONTROLLER_EVENTS);
|
2013-08-21 19:04:46 +00:00
|
|
|
if (protocol)
|
2015-10-24 12:39:17 +11:00
|
|
|
ProtocolManager::getInstance()->requestTerminate(protocol);
|
2013-08-21 19:04:46 +00:00
|
|
|
else
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::error("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"No controller events protocol registered.");
|
2013-08-21 19:04:46 +00:00
|
|
|
|
2015-11-20 17:02:47 +11:00
|
|
|
protocol = ProtocolManager::getInstance()
|
|
|
|
->getProtocol(PROTOCOL_KART_UPDATE);
|
2013-08-21 19:04:46 +00:00
|
|
|
if (protocol)
|
2015-10-24 12:39:17 +11:00
|
|
|
ProtocolManager::getInstance()->requestTerminate(protocol);
|
2013-08-21 19:04:46 +00:00
|
|
|
else
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::error("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"No kart update protocol registered.");
|
2013-08-21 19:04:46 +00:00
|
|
|
|
2015-11-20 17:02:47 +11:00
|
|
|
protocol = ProtocolManager::getInstance()
|
|
|
|
->getProtocol(PROTOCOL_GAME_EVENTS);
|
2013-08-21 19:04:46 +00:00
|
|
|
if (protocol)
|
2015-10-24 12:39:17 +11:00
|
|
|
ProtocolManager::getInstance()->requestTerminate(protocol);
|
2013-08-21 19:04:46 +00:00
|
|
|
else
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::error("ClientLobby",
|
2015-11-20 17:02:47 +11:00
|
|
|
"No game events protocol registered.");
|
2013-08-21 19:04:46 +00:00
|
|
|
|
|
|
|
// finish the race
|
2013-08-15 12:35:23 +00:00
|
|
|
WorldWithRank* ranked_world = (WorldWithRank*)(World::getWorld());
|
2013-08-21 19:04:46 +00:00
|
|
|
ranked_world->beginSetKartPositions();
|
|
|
|
ranked_world->setPhase(WorldStatus::RESULT_DISPLAY_PHASE);
|
2013-08-21 13:54:50 +00:00
|
|
|
int position = 1;
|
2013-08-15 12:35:23 +00:00
|
|
|
while(data.size()>0)
|
|
|
|
{
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t kart_id = data.getUInt8();
|
2013-08-15 12:35:23 +00:00
|
|
|
ranked_world->setKartPosition(kart_id,position);
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby", "Kart %d has finished #%d",
|
2015-11-20 17:02:47 +11:00
|
|
|
kart_id, position);
|
2013-08-21 13:54:50 +00:00
|
|
|
position++;
|
2013-08-15 12:35:23 +00:00
|
|
|
}
|
2013-08-21 19:04:46 +00:00
|
|
|
ranked_world->endSetKartPositions();
|
2013-08-21 13:54:50 +00:00
|
|
|
m_state = RACE_FINISHED;
|
2013-08-15 12:35:23 +00:00
|
|
|
ranked_world->terminateRace();
|
2015-10-12 21:37:22 +11:00
|
|
|
} // raceFinished
|
2013-08-15 12:35:23 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-03-17 17:19:21 +11:00
|
|
|
/** Called when the server informs the clients to exit the race result screen.
|
|
|
|
* It exits the race, and goes back to the lobby.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::exitResultScreen(Event *event)
|
2016-03-17 17:19:21 +11:00
|
|
|
{
|
|
|
|
RaceResultGUI::getInstance()->backToLobby();
|
|
|
|
} // exitResultScreen
|
2013-09-22 20:40:14 +00:00
|
|
|
|
2016-03-17 17:19:21 +11:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-09-22 20:40:14 +00:00
|
|
|
/*! \brief Called when a player votes for a major race mode.
|
|
|
|
* \param event : Event providing the information.
|
|
|
|
*
|
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0 1 2
|
|
|
|
* ------------------------------
|
|
|
|
* Size | 1 | 1 |
|
|
|
|
* Data |player id | major mode vote |
|
|
|
|
* ------------------------------
|
2013-09-22 20:40:14 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::playerMajorVote(Event* event)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2016-03-01 09:56:33 +11:00
|
|
|
if (!checkDataSize(event, 2))
|
2013-09-22 20:40:14 +00:00
|
|
|
return;
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t player_id = data.getUInt8();
|
|
|
|
uint8_t mode = data.getUInt8();
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->getRaceConfig()->setPlayerMajorVote(player_id, mode);
|
2015-10-12 21:37:22 +11:00
|
|
|
} // playerMajorVote
|
2013-09-22 20:40:14 +00:00
|
|
|
|
2015-10-12 21:37:22 +11:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-09-22 20:40:14 +00:00
|
|
|
/*! \brief Called when a player votes for the number of races in a GP.
|
|
|
|
* \param event : Event providing the information.
|
|
|
|
*
|
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0 1
|
|
|
|
* ---------------------------
|
|
|
|
* Size | 1 | 1 |
|
|
|
|
* Data | player id | races count |
|
|
|
|
* ---------------------------
|
2013-09-22 20:40:14 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::playerRaceCountVote(Event* event)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if (!checkDataSize(event, 2)) return;
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t player_id = data.getUInt8();
|
|
|
|
uint8_t count = data.getUInt8();
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->getRaceConfig()->setPlayerRaceCountVote(player_id, count);
|
2015-10-12 21:37:22 +11:00
|
|
|
} // playerRaceCountVote
|
2013-09-22 20:40:14 +00:00
|
|
|
|
2015-10-12 21:37:22 +11:00
|
|
|
//-----------------------------------------------------------------------------
|
2013-09-22 20:40:14 +00:00
|
|
|
/*! \brief Called when a player votes for a minor race mode.
|
|
|
|
* \param event : Event providing the information.
|
|
|
|
*
|
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0 1
|
|
|
|
* -------------------------------
|
|
|
|
* Size | 1 | 4 |
|
|
|
|
* Data | player id | minor mode vote |
|
|
|
|
* -------------------------------
|
2013-09-22 20:40:14 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::playerMinorVote(Event* event)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if (!checkDataSize(event, 2)) return;
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t player_id = data.getUInt8();
|
|
|
|
uint8_t minor = data.getUInt8();
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->getRaceConfig()->setPlayerMinorVote(player_id, minor);
|
2015-10-12 21:37:22 +11:00
|
|
|
} // playerMinorVote
|
|
|
|
|
2013-09-22 20:40:14 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*! \brief Called when a player votes for a track.
|
|
|
|
* \param event : Event providing the information.
|
|
|
|
*
|
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0 1 2 3
|
|
|
|
* --------------------------------------------------
|
|
|
|
* Size | 1 | 1 | 1 | N |
|
|
|
|
* Data | player id | track number (gp) | N | track name |
|
|
|
|
* --------------------------------------------------
|
2013-09-22 20:40:14 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::playerTrackVote(Event* event)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if (!checkDataSize(event, 3)) return;
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2015-11-27 08:55:21 +11:00
|
|
|
std::string track_name;
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t player_id = data.getUInt8();
|
|
|
|
uint8_t number = data.getUInt8();
|
|
|
|
int N = data.decodeString(&track_name);
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->getRaceConfig()->setPlayerTrackVote(player_id, track_name,
|
2016-03-13 13:49:43 +11:00
|
|
|
number);
|
2015-10-12 21:37:22 +11:00
|
|
|
} // playerTrackVote
|
|
|
|
|
2013-09-22 20:40:14 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*! \brief Called when a player votes for the reverse mode of a race
|
|
|
|
* \param event : Event providing the information.
|
|
|
|
*
|
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0 1 2
|
|
|
|
* -------------------------------------------
|
|
|
|
* Size | 1 | 1 | 1 |
|
|
|
|
* Data | player id |reversed | track number (gp) |
|
|
|
|
* -------------------------------------------
|
2013-09-22 20:40:14 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::playerReversedVote(Event* event)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if (!checkDataSize(event, 3)) return;
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t player_id = data.getUInt8();
|
|
|
|
uint8_t reversed = data.getUInt8();
|
|
|
|
uint8_t number = data.getUInt8();
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->getRaceConfig()->setPlayerReversedVote(player_id, reversed!=0,
|
2016-03-13 13:49:43 +11:00
|
|
|
number);
|
2015-10-12 21:37:22 +11:00
|
|
|
} // playerReversedVote
|
|
|
|
|
2013-09-22 20:40:14 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*! \brief Called when a player votes for a major race mode.
|
|
|
|
* \param event : Event providing the information.
|
|
|
|
*
|
|
|
|
* Format of the data :
|
2016-03-01 09:56:33 +11:00
|
|
|
* Byte 0 1 2
|
|
|
|
* ----------------------------------------
|
|
|
|
* Size | 1 | 1 | 1 |
|
2016-11-22 17:57:15 +11:00
|
|
|
* Data | player id | laps | track number (gp) |
|
2016-03-01 09:56:33 +11:00
|
|
|
* ----------------------------------------
|
2013-09-22 20:40:14 +00:00
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::playerLapsVote(Event* event)
|
2013-09-22 20:40:14 +00:00
|
|
|
{
|
2016-03-01 09:56:33 +11:00
|
|
|
if (!checkDataSize(event, 3)) return;
|
2016-02-28 14:58:15 +11:00
|
|
|
const NetworkString &data = event->data();
|
2016-03-13 13:49:43 +11:00
|
|
|
uint8_t player_id = data.getUInt8();
|
|
|
|
uint8_t laps = data.getUInt8();
|
|
|
|
uint8_t number = data.getUInt8();
|
2016-11-22 17:57:15 +11:00
|
|
|
m_game_setup->getRaceConfig()->setPlayerLapsVote(player_id, laps, number);
|
2015-10-12 21:37:22 +11:00
|
|
|
} // playerLapsVote
|
|
|
|
|
2013-09-22 20:40:14 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
2016-11-22 17:57:15 +11:00
|
|
|
/** Callback when the world is loaded. The client will inform the server
|
|
|
|
* that the players on this host are ready to start the race. It is called by
|
|
|
|
* the RaceManager after the world is loaded.
|
|
|
|
*/
|
2016-11-23 09:39:33 +11:00
|
|
|
void ClientLobby::finishedLoadingWorld()
|
2016-11-22 17:57:15 +11:00
|
|
|
{
|
|
|
|
assert(STKHost::get()->getPeerCount() == 1);
|
|
|
|
std::vector<NetworkPlayerProfile*> players =
|
|
|
|
STKHost::get()->getMyPlayerProfiles();
|
|
|
|
NetworkString *ns = getNetworkString(2);
|
|
|
|
ns->addUInt8(LE_CLIENT_LOADED_WORLD);
|
|
|
|
ns->addUInt8( uint8_t(players.size()) ) ;
|
|
|
|
for (unsigned int i = 0; i < players.size(); i++)
|
|
|
|
{
|
|
|
|
ns->addUInt8(players[i]->getGlobalPlayerId());
|
2016-11-23 09:39:33 +11:00
|
|
|
Log::info("ClientLobby",
|
2016-11-22 17:57:15 +11:00
|
|
|
"Player %d ready, notifying server.",
|
|
|
|
players[i]->getGlobalPlayerId());
|
|
|
|
} // for i < players.size()
|
|
|
|
sendToServer(ns, /*reliable*/true);
|
|
|
|
delete ns;
|
|
|
|
} // finishedLoadingWorld
|