lot of code refactoring, now protocols can choose whether they receive network messages (and more generally events) in a synchronous mode (along with the main loop) or in an asynchronous mode

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/hilnius@13403 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hilnius 2013-08-01 19:49:57 +00:00
parent a51f7bfb74
commit b394bd9295
49 changed files with 447 additions and 241 deletions

View File

@ -42,10 +42,7 @@ Event::Event(ENetEvent* event)
}
if (type == EVENT_TYPE_MESSAGE)
{
data = NetworkString(std::string((char*)(event->packet->data), event->packet->dataLength-1));
}
else if (event->data)
{
m_data = NetworkString(std::string((char*)(event->packet->data), event->packet->dataLength-1));
}
m_packet = NULL;
@ -80,7 +77,7 @@ Event::Event(ENetEvent* event)
Event::Event(const Event& event)
{
m_packet = NULL;
data = event.data;
m_data = event.m_data;
// copy the peer
peer = event.peer;
type = event.type;
@ -94,6 +91,6 @@ Event::~Event()
void Event::removeFront(int size)
{
data.removeFront(size);
m_data.removeFront(size);
}

View File

@ -65,11 +65,13 @@ class Event
*/
void removeFront(int size);
NetworkString data() const { return m_data; }
EVENT_TYPE type; //!< Type of the event.
NetworkString data; //!< Copy of the data passed by the event.
STKPeer** peer; //!< Pointer to the peer that triggered that event.
private:
NetworkString m_data; //!< Copy of the data passed by the event.
ENetPacket* m_packet; //!< A pointer on the ENetPacket to be deleted.
};

View File

@ -43,7 +43,7 @@ GameSetup::~GameSetup()
void GameSetup::addPlayer(NetworkPlayerProfile* profile)
{
m_players.push_back(profile);
Log::verbose("GameSetup", "New player in the game setup. Global id : %u, "
Log::info("GameSetup", "New player in the game setup. Global id : %u, "
"Race id : %d.", profile->user_profile->getUserID(), profile->race_id);
}

View File

@ -116,7 +116,7 @@ void NetworkManager::notifyEvent(Event* event)
((addr>>24)&0xff),
((addr>>16)&0xff),
((addr>>8)&0xff),
(addr&0xff), event->data.c_str());
(addr&0xff), event->data().c_str());
}

View File

@ -61,53 +61,51 @@ class Protocol
* \param type The type of the protocol.
*/
Protocol(CallbackObject* callback_object, PROTOCOL_TYPE type);
/*!
* \brief Destructor
/*! \brief Destructor
*/
virtual ~Protocol();
/*!
* \brief Notify a protocol matching the Event type of that event.
* \param event : Pointer to the event.
/*! \brief Notify a protocol matching the Event type of that event.
* \param event : Pointer to the event.
* \return True if the event has been treated, false elseway
*/
virtual void notifyEvent(Event* event) = 0;
virtual bool notifyEvent(Event* event) { return false; }
/*!
* \brief Set the protocol listener.
* \param listener : Pointer to the listener.
/*! \brief Notify a protocol matching the Event type of that event.
* This update is done asynchronously :
* \param event : Pointer to the event.
* \return True if the event has been treated, false elseway
*/
virtual bool notifyEventAsynchronous(Event* event) { return false; }
/*! \brief Set the protocol listener.
* \param listener : Pointer to the listener.
*/
void setListener(ProtocolManager* listener);
/*!
* \brief Called when the protocol is going to start. Must be re-defined by subclasses.
/*! \brief Called when the protocol is going to start. Must be re-defined by subclasses.
*/
virtual void setup() = 0;
/*!
* \brief Called when the protocol is paused (by an other entity or by itself).
* This function must be called by the subclasse's pause function if re-defined.
/*! \brief Called when the protocol is paused (by an other entity or by itself).
* This function must be called by the subclasse's pause function if re-defined.
*/
virtual void pause();
/*!
* \brief Called when the protocol is unpaused.
* This function must be called by the subclasse's unpause function if re-defined.
/*! \brief Called when the protocol is unpaused.
* This function must be called by the subclasse's unpause function if re-defined.
*/
virtual void unpause();
/*!
* \brief Called by the protocol listener, synchronously with the main loop. Must be re-defined.
/*! \brief Called by the protocol listener, synchronously with the main loop. Must be re-defined.
*/
virtual void update() = 0;
/*!
* \brief Called by the protocol listener as often as possible. Must be re-defined.
/*! \brief Called by the protocol listener as often as possible. Must be re-defined.
*/
virtual void asynchronousUpdate() = 0;
/*!
* \brief Called when the protocol is to be killed.
/*! \brief Called when the protocol is to be killed.
*/
virtual void kill();
/*!
* \brief Method to get a protocol's type.
* \return The protocol type.
/*! \brief Method to get a protocol's type.
* \return The protocol type.
*/
PROTOCOL_TYPE getProtocolType();
protected:

View File

@ -34,7 +34,7 @@ void* protocolManagerUpdate(void* data)
while(!manager->exit())
{
manager->update();
irr_driver->getDevice()->sleep(20);
usleep(20000);
}
return NULL;
}
@ -44,7 +44,7 @@ void* protocolManagerAsynchronousUpdate(void* data)
while(!manager->exit())
{
manager->asynchronousUpdate();
irr_driver->getDevice()->sleep(20);
usleep(20000);
}
return NULL;
}
@ -83,7 +83,7 @@ ProtocolManager::~ProtocolManager()
for (unsigned int i = 0; i < m_protocols.size() ; i++)
delete m_protocols[i].protocol;
for (unsigned int i = 0; i < m_events_to_process.size() ; i++)
delete m_events_to_process[i];
delete m_events_to_process[i].event;
m_protocols.clear();
m_requests.clear();
m_events_to_process.clear();
@ -105,7 +105,49 @@ void ProtocolManager::notifyEvent(Event* event)
{
pthread_mutex_lock(&m_events_mutex);
Event* event2 = new Event(*event);
m_events_to_process.push_back(event2); // add the event to the queue
// register protocols that will receive this event
std::vector<int> protocols_ids;
PROTOCOL_TYPE searchedProtocol = PROTOCOL_NONE;
if (event2->type == EVENT_TYPE_MESSAGE)
{
if (event2->data().size() > 0)
{
searchedProtocol = (PROTOCOL_TYPE)(event2->data()[0]);
event2->removeFront(1);
}
else
{
Log::warn("ProtocolManager", "Not enough data.");
}
}
if (event2->type == EVENT_TYPE_CONNECTED)
{
searchedProtocol = PROTOCOL_CONNECTION;
}
Log::verbose("ProtocolManager", "Received event for protocols of type %d", searchedProtocol);
pthread_mutex_lock(&m_protocols_mutex);
for (unsigned int i = 0; i < m_protocols.size() ; i++)
{
if (m_protocols[i].protocol->getProtocolType() == searchedProtocol || event2->type == EVENT_TYPE_DISCONNECTED) // pass data to protocols even when paused
{
protocols_ids.push_back(m_protocols[i].id);
}
}
pthread_mutex_unlock(&m_protocols_mutex);
if (searchedProtocol == PROTOCOL_NONE) // no protocol was aimed, show the msg to debug
{
Log::debug("ProtocolManager", "NO PROTOCOL : Message is \"%s\"", event2->data().c_str());
}
if (protocols_ids.size() != 0)
{
EventProcessingInfo epi;
epi.event = event2;
epi.protocols_ids = protocols_ids;
m_events_to_process.push_back(epi); // add the event to the queue
}
else
Log::warn("ProtocolManager", "Received an event that has no destination protocol.");
pthread_mutex_unlock(&m_events_mutex);
}
@ -274,36 +316,50 @@ void ProtocolManager::protocolTerminated(ProtocolInfo protocol)
pthread_mutex_unlock(&m_protocols_mutex);
}
void ProtocolManager::propagateEvent(Event* event)
bool ProtocolManager::propagateEvent(EventProcessingInfo* event, bool synchronous)
{
PROTOCOL_TYPE searchedProtocol = PROTOCOL_NONE;
if (event->type == EVENT_TYPE_MESSAGE)
int index = 0;
for (unsigned int i = 0; i < m_protocols.size(); i++)
{
if (event->data.size() > 0)
searchedProtocol = (PROTOCOL_TYPE)(event->data.getAndRemoveUInt8());
if (event->protocols_ids[index] == m_protocols[i].id)
{
bool result = false;
if (synchronous)
result = m_protocols[i].protocol->notifyEvent(event->event);
else
result = m_protocols[i].protocol->notifyEventAsynchronous(event->event);
if (result)
event->protocols_ids.pop_back();
else
index++;
}
}
if (event->type == EVENT_TYPE_CONNECTED)
if (event->protocols_ids.size() == 0)
{
searchedProtocol = PROTOCOL_CONNECTION;
// because we made a copy of the event
delete event->event->peer; // no more need of that
delete event->event;
return true;
}
Log::verbose("ProtocolManager", "Received event for protocols of type %d", searchedProtocol);
for (unsigned int i = 0; i < m_protocols.size() ; i++)
{
if (m_protocols[i].protocol->getProtocolType() == searchedProtocol || event->type == EVENT_TYPE_DISCONNECTED) // pass data to protocols even when paused
m_protocols[i].protocol->notifyEvent(event);
}
if (searchedProtocol == PROTOCOL_NONE) // no protocol was aimed, show the msg to debug
{
Log::debug("ProtocolManager", "NO PROTOCOL : Message is \"%s\"", event->data.c_str());
}
// because we made a copy of the event
delete event->peer; // no more need of that
delete event;
return false;
}
void ProtocolManager::update()
{
// before updating, notice protocols that they have received events
pthread_mutex_lock(&m_events_mutex); // secure threads
int size = m_events_to_process.size();
int offset = 0;
for (int i = 0; i < size; i++)
{
bool result = propagateEvent(&m_events_to_process[i+offset], true);
if (result)
{
m_events_to_process.erase(m_events_to_process.begin()+i+offset,m_events_to_process.begin()+i+offset+1);
offset --;
}
}
pthread_mutex_unlock(&m_events_mutex); // release the mutex
// now update all protocols
pthread_mutex_lock(&m_protocols_mutex);
for (unsigned int i = 0; i < m_protocols.size(); i++)
@ -317,16 +373,19 @@ void ProtocolManager::update()
void ProtocolManager::asynchronousUpdate()
{
// before updating, notice protocols that they have received information
pthread_mutex_lock(&m_events_mutex); // secure threads
int size = m_events_to_process.size();
int offset = 0;
for (int i = 0; i < size; i++)
{
pthread_mutex_lock(&m_events_mutex); // secure threads
Event* event = m_events_to_process.back();
m_events_to_process.pop_back();
pthread_mutex_unlock(&m_events_mutex); // release the mutex
propagateEvent(event);
bool result = propagateEvent(&m_events_to_process[i+offset], false);
if (result)
{
m_events_to_process.erase(m_events_to_process.begin()+i+offset,m_events_to_process.begin()+i+offset+1);
offset --;
}
}
pthread_mutex_unlock(&m_events_mutex); // release the mutex
// now update all protocols that need to be updated in asynchronous mode
pthread_mutex_lock(&m_asynchronous_protocols_mutex);

View File

@ -78,6 +78,15 @@ typedef struct ProtocolRequest
ProtocolInfo protocol_info; //!< The concerned protocol information
} ProtocolRequest;
/*! \struct ProtocolRequest
* \brief Used to pass the event to protocols that need it
*/
typedef struct EventProcessingInfo
{
Event* event;
std::vector<int> protocols_ids;
} EventProcessingInfo;
/*!
* \class ProtocolManager
* \brief Manages the protocols at runtime.
@ -269,7 +278,7 @@ class ProtocolManager : public Singleton<ProtocolManager>
*/
virtual void protocolTerminated(ProtocolInfo protocol);
void propagateEvent(Event* event);
bool propagateEvent(EventProcessingInfo* event, bool synchronous);
// protected members
/*!
@ -281,7 +290,7 @@ class ProtocolManager : public Singleton<ProtocolManager>
/*!
* \brief Contains the network events to pass to protocols.
*/
std::vector<Event*> m_events_to_process;
std::vector<EventProcessingInfo> m_events_to_process;
/*!
* \brief Contains the requests to start/stop etc... protocols.
*/

View File

@ -68,14 +68,22 @@ void ClientLobbyRoomProtocol::leave()
//-----------------------------------------------------------------------------
void ClientLobbyRoomProtocol::notifyEvent(Event* event)
bool ClientLobbyRoomProtocol::notifyEvent(Event* event)
{
return false;
}
//-----------------------------------------------------------------------------
bool ClientLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
{
assert(m_setup); // assert that the setup exists
if (event->type == EVENT_TYPE_MESSAGE)
{
assert(event->data.size()); // assert that data isn't empty
uint8_t message_type = event->data.getAndRemoveUInt8();
NetworkString data = event->data();
assert(data.size()); // assert that data isn't empty
uint8_t message_type = data[0];
event->removeFront(1);
Log::info("ClientLobbyRoomProtocol", "Message of type %d", message_type);
if (message_type == 0x01) // new player connected
newPlayer(event);
@ -107,6 +115,7 @@ void ClientLobbyRoomProtocol::notifyEvent(Event* event)
NetworkManager::getInstance()->reset();
NetworkManager::getInstance()->removePeer(*event->peer); // prolly the same as m_server
} // disconnection
return true;
}
//-----------------------------------------------------------------------------
@ -185,14 +194,15 @@ void ClientLobbyRoomProtocol::update()
*/
void ClientLobbyRoomProtocol::newPlayer(Event* event)
{
if (event->data.size() != 7 || event->data[0] != 4 || event->data[5] != 1) // 7 bytes remains now
NetworkString data = event->data();
if (data.size() != 7 || data[0] != 4 || data[5] != 1) // 7 bytes remains now
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected.");
return;
}
uint32_t global_id = event->data.gui32(1);
uint8_t race_id = event->data.gui8(6);
uint32_t global_id = data.gui32(1);
uint8_t race_id = data.gui8(6);
if (global_id == Online::CurrentUser::get()->getUserID())
{
@ -227,12 +237,13 @@ void ClientLobbyRoomProtocol::newPlayer(Event* event)
*/
void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
{
if (event->data.size() != 2 || event->data[0] != 1)
NetworkString data = event->data();
if (data.size() != 2 || data[0] != 1)
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected.");
return;
}
uint8_t id = event->data[1];
uint8_t id = data[1];
if (m_setup->removePlayer(id))
{
Log::info("ClientLobbyRoomProtocol", "Peer removed successfully.");
@ -257,14 +268,15 @@ void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
*/
void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
{
if (event->data.size() < 12 || event->data[0] != 1 || event->data[2] != 4 || event->data[7] != 4) // 12 bytes remains now
NetworkString data = event->data();
if (data.size() < 12 || data[0] != 1 || data[2] != 4 || data[7] != 4) // 12 bytes remains now
{
Log::error("ClientLobbyRoomProtocol", "A message notifying an accepted connection wasn't formated as expected.");
return;
}
STKPeer* peer = *(event->peer);
uint32_t global_id = event->data.gui32(8);
uint32_t global_id = data.gui32(8);
if (global_id == Online::CurrentUser::get()->getUserID())
{
Log::info("ClientLobbyRoomProtocol", "The server accepted the connection.");
@ -272,15 +284,15 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
// self profile
NetworkPlayerProfile* profile = new NetworkPlayerProfile();
profile->kart_name = "";
profile->race_id = event->data.gui8(1);
profile->race_id = data.gui8(1);
profile->user_profile = Online::CurrentUser::get();
m_setup->addPlayer(profile);
// connection token
uint32_t token = event->data.gui32(3);
uint32_t token = data.gui32(3);
peer->setClientServerToken(token);
// add all players
event->data.removeFront(12); // remove the 12 first bytes
int remaining = event->data.size();
data.removeFront(12); // remove the 12 first bytes
int remaining = data.size();
if (remaining%7 != 0)
{
Log::error("ClientLobbyRoomProtocol", "ConnectionAccepted : Error in the server list");
@ -288,17 +300,17 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
remaining /= 7;
for (int i = 0; i < remaining; i++)
{
if (event->data[0] != 1 || event->data[2] != 4)
if (data[0] != 1 || data[2] != 4)
Log::error("ClientLobbyRoomProtocol", "Bad format in players list.");
uint8_t race_id = event->data[1];
uint32_t global_id = event->data.gui32(3);
uint8_t race_id = data[1];
uint32_t global_id = data.gui32(3);
Online::User* new_user = new Online::User(global_id);
NetworkPlayerProfile* profile2 = new NetworkPlayerProfile();
profile2->race_id = race_id;
profile2->user_profile = new_user;
profile2->kart_name = "";
m_setup->addPlayer(profile2);
event->data.removeFront(7);
data.removeFront(7);
}
// add self
@ -323,13 +335,14 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
*/
void ClientLobbyRoomProtocol::connectionRefused(Event* event)
{
if (event->data.size() != 2 || event->data[0] != 1) // 2 bytes remains now
NetworkString data = event->data();
if (data.size() != 2 || data[0] != 1) // 2 bytes remains now
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a refused connection wasn't formated as expected.");
return;
}
switch (event->data[1]) // the second byte
switch (data[1]) // the second byte
{
case 0:
Log::info("ClientLobbyRoomProtocol", "Connection refused : too many players.");
@ -357,13 +370,14 @@ void ClientLobbyRoomProtocol::connectionRefused(Event* event)
*/
void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
{
if (event->data.size() != 2 || event->data[0] != 1)
NetworkString data = event->data();
if (data.size() != 2 || data[0] != 1)
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a refused kart selection wasn't formated as expected.");
return;
}
switch (event->data[1]) // the error code
switch (data[1]) // the error code
{
case 0:
Log::info("ClientLobbyRoomProtocol", "Kart selection refused : already taken.");
@ -391,24 +405,26 @@ void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
*/
void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event)
{
if (event->data.size() < 3 || event->data[0] != 1)
NetworkString data = event->data();
if (data.size() < 3 || data[0] != 1)
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart selection update wasn't formated as expected.");
return;
}
uint8_t player_id = event->data[1];
uint8_t kart_name_length = event->data[2];
std::string data = event->data.getString(3, kart_name_length);
if (data.size() != kart_name_length)
uint8_t player_id = data[1];
uint8_t kart_name_length = data[2];
std::string kart_name = data.getString(3, kart_name_length);
if (kart_name.size() != kart_name_length)
{
Log::error("ClientLobbyRoomProtocol", "Kart names sizes differ: told: %d, real: %d.", kart_name_length, data.size());
Log::error("ClientLobbyRoomProtocol", "Kart names sizes differ: told: %d, real: %d.", kart_name_length, kart_name.size());
return;
}
if (!m_setup->isKartAvailable(data))
if (!m_setup->isKartAvailable(kart_name))
{
Log::error("ClientLobbyRoomProtocol", "The updated kart is taken already.");
}
m_setup->setPlayerKart(player_id, data);
m_setup->setPlayerKart(player_id, kart_name);
NetworkKartSelectionScreen::getInstance()->playerSelected(player_id, kart_name);
}
//-----------------------------------------------------------------------------
@ -425,13 +441,14 @@ void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event)
*/
void ClientLobbyRoomProtocol::startGame(Event* event)
{
if (event->data.size() < 5 || event->data[0] != 4)
NetworkString data = event->data();
if (data.size() < 5 || data[0] != 4)
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
"selection update wasn't formated as expected.");
return;
}
uint8_t token = event->data.gui32(1);
uint8_t token = data.gui32(1);
if (token == NetworkManager::getInstance()->getPeers()[0]->getClientServerToken())
{
m_state = PLAYING;
@ -457,13 +474,14 @@ void ClientLobbyRoomProtocol::startGame(Event* event)
*/
void ClientLobbyRoomProtocol::startSelection(Event* event)
{
if (event->data.size() < 5 || event->data[0] != 4)
NetworkString data = event->data();
if (data.size() < 5 || data[0] != 4)
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
"selection update wasn't formated as expected.");
return;
}
uint8_t token = event->data.gui32(1);
uint8_t token = data.gui32(1);
if (token == NetworkManager::getInstance()->getPeers()[0]->getClientServerToken())
{
m_state = KART_SELECTION;

View File

@ -13,7 +13,8 @@ class ClientLobbyRoomProtocol : public LobbyRoomProtocol
void sendMessage(std::string message);
void leave();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event);
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void update();
virtual void asynchronousUpdate() {}

View File

@ -46,13 +46,14 @@ ConnectToPeer::~ConnectToPeer()
// ----------------------------------------------------------------------------
void ConnectToPeer::notifyEvent(Event* event)
bool ConnectToPeer::notifyEventAsynchronous(Event* event)
{
if (event->type == EVENT_TYPE_CONNECTED)
{
Log::debug("ConnectToPeer", "Received event notifying peer connection.");
m_state = CONNECTED; // we received a message, we are connected
}
return true;
}
// ----------------------------------------------------------------------------

View File

@ -29,7 +29,7 @@ class ConnectToPeer : public Protocol, public CallbackObject
ConnectToPeer(uint32_t peer_id);
virtual ~ConnectToPeer();
virtual void notifyEvent(Event* event);
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -60,7 +60,7 @@ ConnectToServer::~ConnectToServer()
// ----------------------------------------------------------------------------
void ConnectToServer::notifyEvent(Event* event)
bool ConnectToServer::notifyEventAsynchronous(Event* event)
{
if (event->type == EVENT_TYPE_CONNECTED)
{
@ -68,6 +68,7 @@ void ConnectToServer::notifyEvent(Event* event)
"received an event notifying that he's connected to the peer.");
m_state = CONNECTED; // we received a message, we are connected
}
return true;
}
// ----------------------------------------------------------------------------
@ -184,6 +185,7 @@ void ConnectToServer::asynchronousUpdate()
break;
case DONE:
m_listener->requestTerminate(this);
m_state = EXITING;
break;
}
}

View File

@ -30,7 +30,7 @@ class ConnectToServer : public Protocol, public CallbackObject
ConnectToServer(uint32_t server_id, uint32_t host_id); //!< Specify server id
virtual ~ConnectToServer();
virtual void notifyEvent(Event* event);
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();
@ -53,7 +53,8 @@ class ConnectToServer : public Protocol, public CallbackObject
CONNECTING,
CONNECTED,
HIDING_ADDRESS,
DONE
DONE,
EXITING
};
STATE m_state;
};

View File

@ -42,7 +42,7 @@ void ControllerEventsProtocol::setup()
{
peer = peers[j];
}
Log::info("ControllerEventsProtocol", "Compared %s and %s",
Log::info("ControllerEventsProtocol", "Compared %s and %s",
peers[j]->getPlayerProfile()->kart_name.c_str(), karts[i]->getIdent().c_str());
}
}
@ -61,20 +61,21 @@ void ControllerEventsProtocol::setup()
//-----------------------------------------------------------------------------
void ControllerEventsProtocol::notifyEvent(Event* event)
bool ControllerEventsProtocol::notifyEventAsynchronous(Event* event)
{
if (event->data.size() < 17)
NetworkString data = event->data();
if (data.size() < 17)
{
Log::error("ControllerEventsProtocol", "The data supplied was not complete. Size was %d.", event->data.size());
return;
Log::error("ControllerEventsProtocol", "The data supplied was not complete. Size was %d.", data.size());
return true;
}
uint32_t token = event->data.gui32();
NetworkString pure_message = event->data;
uint32_t token = data.gui32();
NetworkString pure_message = data;
pure_message.removeFront(4);
if (token != (*event->peer)->getClientServerToken())
{
Log::error("ControllerEventsProtocol", "Bad token from peer.");
return;
return true;
}
NetworkString ns = pure_message;
float event_timestamp = ns.getFloat();
@ -103,12 +104,12 @@ void ControllerEventsProtocol::notifyEvent(Event* event)
if (ns.size() > 0 && ns.size() != 9)
{
Log::warn("ControllerEventProtocol", "The data seems corrupted. Remains %d", ns.size());
return;
return true;
}
if (client_index < 0)
{
Log::warn("ControllerEventProtocol", "Couldn't have a client id.");
return;
return true;
}
if (m_listener->isServer())
{
@ -124,6 +125,7 @@ void ControllerEventsProtocol::notifyEvent(Event* event)
//Log::info("ControllerEventsProtocol", "Sizes are %d and %d", ns2.size(), pure_message.size());
}
}
return true;
}
//-----------------------------------------------------------------------------

View File

@ -16,8 +16,8 @@ class ControllerEventsProtocol : public Protocol
ControllerEventsProtocol();
virtual ~ControllerEventsProtocol();
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void notifyEvent(Event* event);
virtual void update();
virtual void asynchronousUpdate() {}

View File

@ -8,10 +8,6 @@ GameEventsProtocol::~GameEventsProtocol()
{
}
void GameEventsProtocol::notifyEvent(Event* event)
{
}
void GameEventsProtocol::setup()
{
}

View File

@ -10,7 +10,8 @@ class GameEventsProtocol : public Protocol
GameEventsProtocol();
virtual ~GameEventsProtocol();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event) { return true; }
virtual bool notifyEventAsynchronous(Event* event) { return true; }
virtual void setup();
virtual void update();
virtual void asynchronousUpdate() {}

View File

@ -34,11 +34,6 @@ GetPeerAddress::~GetPeerAddress()
{
}
void GetPeerAddress::notifyEvent(Event* event)
{
// nothing there. If we receive events, they must be ignored
}
void GetPeerAddress::setup()
{
m_state = NONE;

View File

@ -28,7 +28,8 @@ class GetPeerAddress : public Protocol
GetPeerAddress(uint32_t peer_id, CallbackObject* callback_object);
virtual ~GetPeerAddress();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event) { return true; }
virtual bool notifyEventAsynchronous(Event* event) { return true; }
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -46,11 +46,6 @@ GetPublicAddress::~GetPublicAddress()
{
}
void GetPublicAddress::notifyEvent(Event* event)
{
}
void GetPublicAddress::setup()
{
m_state = NOTHING_DONE;

View File

@ -27,8 +27,8 @@ class GetPublicAddress : public Protocol
GetPublicAddress(CallbackObject* callback_object);
virtual ~GetPublicAddress();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event) { return true; }
virtual bool notifyEventAsynchronous(Event* event) { return true; }
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -32,10 +32,6 @@ HidePublicAddress::~HidePublicAddress()
{
}
void HidePublicAddress::notifyEvent(Event* event)
{
}
void HidePublicAddress::setup()
{
m_state = NONE;

View File

@ -29,7 +29,8 @@ class HidePublicAddress : public Protocol
HidePublicAddress();
virtual ~HidePublicAddress();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event) { return true; }
virtual bool notifyEventAsynchronous(Event* event) { return true; }
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -28,15 +28,15 @@ KartUpdateProtocol::~KartUpdateProtocol()
{
}
void KartUpdateProtocol::notifyEvent(Event* event)
bool KartUpdateProtocol::notifyEventAsynchronous(Event* event)
{
if (event->type != EVENT_TYPE_MESSAGE)
return;
NetworkString ns = event->data;
return true;
NetworkString ns = event->data();
if (ns.size() < 36)
{
Log::info("KartUpdateProtocol", "Message too short.");
return;
return true;
}
float game_time = ns.getFloat(0);
ns.removeFront(4);
@ -60,6 +60,7 @@ void KartUpdateProtocol::notifyEvent(Event* event)
pthread_mutex_unlock(&m_positions_updates_mutex);
ns.removeFront(32);
}
return true;
}
void KartUpdateProtocol::setup()

View File

@ -14,7 +14,7 @@ class KartUpdateProtocol : public Protocol
KartUpdateProtocol();
virtual ~KartUpdateProtocol();
virtual void notifyEvent(Event* event);
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void update();
virtual void asynchronousUpdate() {};

View File

@ -35,11 +35,10 @@ class LobbyRoomProtocol : public Protocol
public:
LobbyRoomProtocol(CallbackObject* callback_object);
virtual ~LobbyRoomProtocol();
virtual void notifyEvent(Event* event) = 0;
virtual void setup() = 0;
virtual void update() = 0;
protected:
GameSetup* m_setup; //!< The game setup.
};

View File

@ -31,10 +31,6 @@ PingProtocol::~PingProtocol()
{
}
void PingProtocol::notifyEvent(Event* event)
{
}
void PingProtocol::setup()
{
m_last_ping_time = 0;

View File

@ -10,7 +10,8 @@ class PingProtocol : public Protocol
PingProtocol(const TransportAddress& ping_dst, double delay_between_pings);
virtual ~PingProtocol();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event) { return true; }
virtual bool notifyEventAsynchronous(Event* event) { return true; }
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -33,10 +33,6 @@ QuickJoinProtocol::~QuickJoinProtocol()
{
}
void QuickJoinProtocol::notifyEvent(Event* event)
{
}
void QuickJoinProtocol::setup()
{
m_state = NONE;

View File

@ -10,7 +10,8 @@ class QuickJoinProtocol : public Protocol
QuickJoinProtocol(CallbackObject* callback_object, uint32_t* server_id);
virtual ~QuickJoinProtocol();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event) { return true; }
virtual bool notifyEventAsynchronous(Event* event) { return true; }
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -32,10 +32,6 @@ RequestConnection::~RequestConnection()
{
}
void RequestConnection::notifyEvent(Event* event)
{
}
void RequestConnection::setup()
{
m_state = NONE;

View File

@ -10,7 +10,8 @@ class RequestConnection : public Protocol
RequestConnection(uint32_t server_id);
virtual ~RequestConnection();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event) { return true; }
virtual bool notifyEventAsynchronous(Event* event) { return true; }
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -57,14 +57,15 @@ void ServerLobbyRoomProtocol::setup()
//-----------------------------------------------------------------------------
void ServerLobbyRoomProtocol::notifyEvent(Event* event)
bool ServerLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
{
assert(m_setup); // assert that the setup exists
if (event->type == EVENT_TYPE_MESSAGE)
{
assert(event->data.size()); // message not empty
NetworkString data = event->data();
assert(data.size()); // message not empty
uint8_t message_type;
message_type = event->data.getAndRemoveUInt8();
message_type = data.getAndRemoveUInt8();
Log::info("ServerLobbyRoomProtocol", "Message received with type %d.", message_type);
if (message_type == 0x01) // player requesting connection
connectionRequested(event);
@ -78,6 +79,7 @@ void ServerLobbyRoomProtocol::notifyEvent(Event* event)
{
kartDisconnected(event);
} // if (event->type == EVENT_TYPE_DISCONNECTED)
return true;
}
//-----------------------------------------------------------------------------
@ -232,13 +234,14 @@ void ServerLobbyRoomProtocol::kartDisconnected(Event* event)
void ServerLobbyRoomProtocol::connectionRequested(Event* event)
{
STKPeer* peer = *(event->peer);
if (event->data.size() != 5 || event->data[0] != 4)
NetworkString data = event->data();
if (data.size() != 5 || data[0] != 4)
{
Log::warn("ServerLobbyRoomProtocol", "The server is sending a badly formated message. Size is %d and first byte %d", event->data.size(), event->data[0]);
Log::warn("ServerLobbyRoomProtocol", "The server is sending a badly formated message. Size is %d and first byte %d", data.size(), data[0]);
return;
}
uint32_t player_id = 0;
player_id = event->data.getUInt32(1);
player_id = data.getUInt32(1);
// can we add the player ?
if (m_setup->getPlayerCount() < 16) // accept player
{
@ -308,23 +311,24 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
*/
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
{
if (event->data.size() < 6 || event->data[0] != 4)
NetworkString data = event->data();
if (data.size() < 6 || data[0] != 4)
{
Log::warn("ServerLobbyRoomProtocol", "The server is sending a badly "
"formated message. Size is %d and first byte %d",
event->data.size(), event->data[0]);
data.size(), data[0]);
return;
}
STKPeer* peer = *(event->peer);
uint32_t token = event->data.gui32(1);
uint32_t token = data.gui32(1);
if (token != peer->getClientServerToken())
{
Log::warn("ServerLobbyRoomProtocol", "Peer sending bad token. Request "
"aborted.");
return;
}
uint8_t kart_name_size = event->data.gui8(5);
std::string kart_name = event->data.gs(6, kart_name_size);
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:"

View File

@ -9,7 +9,7 @@ class ServerLobbyRoomProtocol : public LobbyRoomProtocol
ServerLobbyRoomProtocol();
virtual ~ServerLobbyRoomProtocol();
virtual void notifyEvent(Event* event);
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void update();
virtual void asynchronousUpdate() {};

View File

@ -32,10 +32,6 @@ ShowPublicAddress::~ShowPublicAddress()
{
}
void ShowPublicAddress::notifyEvent(Event* event)
{
}
void ShowPublicAddress::setup()
{
m_state = NONE;

View File

@ -29,7 +29,8 @@ class ShowPublicAddress : public Protocol
ShowPublicAddress();
virtual ~ShowPublicAddress();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event) { return true; }
virtual bool notifyEventAsynchronous(Event* event) { return true; }
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -32,20 +32,21 @@ StartGameProtocol::~StartGameProtocol()
{
}
void StartGameProtocol::notifyEvent(Event* event)
bool StartGameProtocol::notifyEventAsynchronous(Event* event)
{
if (event->data.size() < 5)
NetworkString data = event->data();
if (data.size() < 5)
{
Log::error("StartGameProtocol", "Too short message.");
return;
return true;
}
uint32_t token = event->data.gui32();
uint8_t ready = event->data.gui8(4);
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;
return true;
}
if (m_listener->isServer() && ready) // on server, player is ready
{
@ -61,17 +62,17 @@ void StartGameProtocol::notifyEvent(Event* event)
protocol->startCountdown(5000); // 5 seconds countdown
Log::info("StartGameProtocol", "All players ready, starting countdown.");
m_ready = true;
return;
return true;
}
else
Log::error("StartGameProtocol", "The Synchronization protocol hasn't been started.");
}
}
else
else // on the client, we shouldn't even receive messages.
{
Log::error("StartGameProtocol", "Received a message with bad format.");
}
// on the client, we shouldn't even receive messages.
return true;
}
void StartGameProtocol::setup()

View File

@ -24,7 +24,7 @@ class StartGameProtocol : public Protocol
StartGameProtocol(GameSetup* game_setup);
virtual ~StartGameProtocol();
virtual void notifyEvent(Event* event);
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void update();
virtual void asynchronousUpdate() {}

View File

@ -31,10 +31,6 @@ StartServer::~StartServer()
{
}
void StartServer::notifyEvent(Event* event)
{
}
void StartServer::setup()
{
m_state = NONE;

View File

@ -14,7 +14,8 @@ class StartServer : public Protocol
StartServer();
virtual ~StartServer();
virtual void notifyEvent(Event* event);
virtual bool notifyEvent(Event* event) { return true; }
virtual bool notifyEventAsynchronous(Event* event) { return true; }
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -31,8 +31,9 @@ StopServer::~StopServer()
{
}
void StopServer::notifyEvent(Event* event)
bool StopServer::notifyEventAsynchronous(Event* event)
{
return true;
}
void StopServer::setup()

View File

@ -13,7 +13,7 @@ class StopServer : public Protocol
StopServer();
virtual ~StopServer();
virtual void notifyEvent(Event* event);
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -30,19 +30,20 @@ SynchronizationProtocol::~SynchronizationProtocol()
//-----------------------------------------------------------------------------
void SynchronizationProtocol::notifyEvent(Event* event)
bool SynchronizationProtocol::notifyEventAsynchronous(Event* event)
{
if (event->type != EVENT_TYPE_MESSAGE)
return;
if (event->data.size() < 10)
return true;
NetworkString data = event->data();
if (data.size() < 10)
{
Log::warn("SynchronizationProtocol", "Received a message too short.");
return;
return true;
}
uint8_t talk_id = event->data.gui8();
uint32_t token = event->data.gui32(1);
uint32_t request = event->data.gui8(5);
uint32_t sequence = event->data.gui32(6);
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();
@ -51,7 +52,7 @@ void SynchronizationProtocol::notifyEvent(Event* event)
if (talk_id > peers.size())
{
Log::warn("SynchronizationProtocol", "The ID isn't known.");
return;
return true;
}
}
@ -66,18 +67,18 @@ void SynchronizationProtocol::notifyEvent(Event* event)
if (peers[peer_id]->getClientServerToken() != token)
{
Log::warn("SynchronizationProtocol", "Bad token from peer %d", talk_id);
return;
return true;
}
if (request)
{
NetworkString response;
response.ai8(event->data.gui8(talk_id)).ai32(token).ai8(0).ai32(sequence);
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 (event->data.size() == 14 && !m_listener->isServer()) // countdown time in the message
if (data.size() == 14 && !m_listener->isServer()) // countdown time in the message
{
uint32_t time_to_start = event->data.gui32(10);
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);
@ -92,7 +93,7 @@ void SynchronizationProtocol::notifyEvent(Event* event)
if (sequence >= m_pings[peer_id].size())
{
Log::warn("SynchronizationProtocol", "The sequence# %u isn't known.", sequence);
return;
return true;
}
double current_time = Time::getRealTime();
m_total_diff[peer_id] += current_time - m_pings[peer_id][sequence];
@ -103,6 +104,7 @@ void SynchronizationProtocol::notifyEvent(Event* event)
Log::debug("SynchronizationProtocol", "Ping is %u", m_average_ping[peer_id]);
}
return true;
}
//-----------------------------------------------------------------------------

View File

@ -11,7 +11,7 @@ class SynchronizationProtocol : public Protocol
SynchronizationProtocol();
virtual ~SynchronizationProtocol();
virtual void notifyEvent(Event* event);
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();

View File

@ -161,7 +161,7 @@ uint8_t* STKHost::receiveRawPacket()
{
i++;
len = recv(m_host->socket,(char*)buffer,2048, 0);
irr_driver->getDevice()->sleep(1);
usleep(1000);
}
return buffer;
}
@ -190,7 +190,7 @@ uint8_t* STKHost::receiveRawPacket(TransportAddress sender)
{
i++;
len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len);
irr_driver->getDevice()->sleep(1); // wait 1 millisecond between two checks
usleep(1000); // wait 1 millisecond between two checks
}
if (addr.sa_family == AF_INET)
{

View File

@ -38,6 +38,7 @@
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
#include "modes/overworld.hpp"
#include "online/user.hpp"
#include "states_screens/race_setup_screen.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
@ -182,17 +183,20 @@ void PlayerNameSpinner::markAsCorrect()
PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
StateManager::ActivePlayer* associatedPlayer,
Online::User* associatedUser,
core::recti area, const int playerID,
std::string kartGroup,
const int irrlichtWidgetID) : Widget(WTYPE_DIV)
{
#ifdef DEBUG
assert(associatedPlayer->ok());
if (associatedPlayer)
assert(associatedPlayer->ok());
m_magic_number = 0x33445566;
#endif
m_ready_text = NULL;
m_parent_screen = parent;
m_associated_user = associatedUser;
m_associatedPlayer = associatedPlayer;
x_speed = 1.0f;
y_speed = 1.0f;
@ -214,13 +218,15 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
target_h = m_h;
// ---- Player identity spinner
m_player_ident_spinner = NULL;
m_player_ident_spinner = new PlayerNameSpinner(parent, m_playerID);
m_player_ident_spinner->m_x = player_name_x;
m_player_ident_spinner->m_y = player_name_y;
m_player_ident_spinner->m_w = player_name_w;
m_player_ident_spinner->m_h = player_name_h;
if (parent->m_multiplayer)
if (parent->m_multiplayer && associatedPlayer)
{
if (associatedPlayer->getDevice()->getType() == DT_KEYBOARD)
{
@ -231,6 +237,10 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
m_player_ident_spinner->setBadge(GAMEPAD_BADGE);
}
}
else if (m_associated_user) // online user, FIXME is that useful ?
{
m_player_ident_spinner->setBadge(OK_BADGE);
}
if (irrlichtWidgetID == -1)
{
@ -415,18 +425,21 @@ void PlayerKartWidget::add()
assert(KartSelectionScreen::getRunningInstance()
->m_kart_widgets.contains(this));
bool mineInList = false;
for (int p=0; p<StateManager::get()->activePlayerCount(); p++)
if (m_associatedPlayer) // if player is local
{
#ifdef DEBUG
assert(StateManager::get()->getActivePlayer(p)->ok());
#endif
if (StateManager::get()->getActivePlayer(p) == m_associatedPlayer)
bool mineInList = false;
for (int p=0; p<StateManager::get()->activePlayerCount(); p++)
{
mineInList = true;
#ifdef DEBUG
assert(StateManager::get()->getActivePlayer(p)->ok());
#endif
if (StateManager::get()->getActivePlayer(p) == m_associatedPlayer)
{
mineInList = true;
}
}
assert(mineInList);
}
assert(mineInList);
//m_player_ID_label->add();
@ -447,6 +460,13 @@ void PlayerKartWidget::add()
m_model_view->update(0);
m_player_ident_spinner->clearLabels();
irr::core::stringw name; // name of the player
if (m_associatedPlayer)
name = m_associatedPlayer->getProfile()->getName();
if (m_associated_user)
name = m_associated_user->getUserName();
if (m_parent_screen->m_multiplayer)
{
const int playerAmount = UserConfigParams::m_all_players.size();
@ -457,17 +477,15 @@ void PlayerKartWidget::add()
}
// select the right player profile in the spinner
m_player_ident_spinner->setValue(m_associatedPlayer->getProfile()
->getName() );
m_player_ident_spinner->setValue(name);
}
else
{
m_player_ident_spinner->addLabel( m_associatedPlayer->getProfile()->getName() );
m_player_ident_spinner->addLabel(name);
m_player_ident_spinner->setVisible(false);
}
assert(m_player_ident_spinner->getStringValue() ==
m_associatedPlayer->getProfile()->getName());
assert(m_player_ident_spinner->getStringValue() == name);
} // add
// ------------------------------------------------------------------------
@ -1179,7 +1197,7 @@ bool KartSelectionScreen::playerJoin(InputDevice* device, bool firstPlayer)
// ---- Create player/kart widget
PlayerKartWidget* newPlayerWidget =
new PlayerKartWidget(this, aplayer, kartsArea, m_kart_widgets.size(),
new PlayerKartWidget(this, aplayer, NULL, kartsArea, m_kart_widgets.size(),
selected_kart_group);
manualAddWidget(newPlayerWidget);

View File

@ -34,6 +34,10 @@ namespace GUIEngine
class BubbleWidget;
enum EventPropagation;
}
namespace Online
{
class User;
}
class InputDevice;
class PlayerKartWidget;
class KartHoverListener;
@ -234,8 +238,9 @@ class PlayerKartWidget : public GUIEngine::Widget,
float x_speed, y_speed, w_speed, h_speed;
/** Object representing this player */
StateManager::ActivePlayer* m_associatedPlayer;
StateManager::ActivePlayer* m_associatedPlayer; // local info
int m_playerID;
Online::User* m_associated_user; // network info
/** Internal name of the spinner; useful to interpret spinner events,
* which contain the name of the activated object */
@ -267,6 +272,7 @@ public:
PlayerKartWidget(KartSelectionScreen* parent,
StateManager::ActivePlayer* associatedPlayer,
Online::User* associatedUser,
core::recti area, const int playerID,
std::string kartGroup,
const int irrlichtWidgetID=-1);

View File

@ -1,11 +1,19 @@
#include "states_screens/network_kart_selection.hpp"
#include "audio/sfx_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "items/item_manager.hpp"
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/client_lobby_room_protocol.hpp"
#include "network/network_manager.hpp"
#include "online/current_user.hpp"
#include "states_screens/state_manager.hpp"
static const char RANDOM_KART_ID[] = "randomkart";
static const char ID_LOCKED[] = "locked/";
using namespace GUIEngine;
DEFINE_SCREEN_SINGLETON( NetworkKartSelectionScreen );
@ -26,8 +34,9 @@ void NetworkKartSelectionScreen::init()
RibbonWidget* tabs = getWidget<RibbonWidget>("kartgroups");
assert( tabs != NULL );
tabs->setVisible(false);
tabs->select( "standard", PLAYER_ID_GAME_MASTER); // select standard kart group
tabs->setDeactivated();
tabs->setVisible(false);
// change the back button image (because it makes the game quit)
IconButtonWidget* back_button = getWidget<IconButtonWidget>("back");
@ -44,7 +53,7 @@ void NetworkKartSelectionScreen::init()
}
std::vector<NetworkPlayerProfile*> players = setup->getPlayers();
Log::info("NKSS", "There are %d players", players.size());
// ---- Get available area for karts
// make a copy of the area, ands move it to be outside the screen
Widget* kartsAreaWidget = getWidget("playerskarts");
@ -58,16 +67,21 @@ void NetworkKartSelectionScreen::init()
for (unsigned int i = 0; i < players.size(); i++)
{
if (players[i]->user_profile == Online::CurrentUser::get())
return; // it is me, don't add again
{
m_id_mapping.insert(m_id_mapping.begin(),players[i]->race_id); //!< first kart widget always me
Log::info("NKSS", "Insert %d at pos 0", players[i]->race_id);
continue; // it is me, don't add again
}
Log::info("NKSS", "Adding %d at pos %d", players[i]->race_id, i);
m_id_mapping.push_back(players[i]->race_id);
StateManager::ActivePlayer* aplayer =
StateManager::get()->getActivePlayer(players[i]->race_id);
StateManager::ActivePlayer* aplayer = NULL; // player is remote
std::string selected_kart_group = "standard"; // standard group
PlayerKartWidget* newPlayerWidget =
new PlayerKartWidget(this, aplayer, kartsArea, m_kart_widgets.size(),
new PlayerKartWidget(this, aplayer, players[i]->user_profile, kartsArea, m_kart_widgets.size(),
selected_kart_group);
manualAddWidget(newPlayerWidget);
@ -91,8 +105,102 @@ void NetworkKartSelectionScreen::init()
void NetworkKartSelectionScreen::playerConfirm(const int playerID)
{
DynamicRibbonWidget* w = getWidget<DynamicRibbonWidget>("karts");
assert(w != NULL);
const std::string selection = w->getSelectionIDString(playerID);
if (StringUtils::startsWith(selection, ID_LOCKED))
{
unlock_manager->playLockSound();
return;
}
if (playerID == PLAYER_ID_GAME_MASTER)
{
UserConfigParams::m_default_kart = selection;
}
if (m_kart_widgets[playerID].getKartInternalName().size() == 0)
{
sfx_manager->quickSound( "anvil" );
return;
}
if(playerID == PLAYER_ID_GAME_MASTER) // self
{
ClientLobbyRoomProtocol* protocol = static_cast<ClientLobbyRoomProtocol*>(
ProtocolManager::getInstance()->getProtocol(PROTOCOL_LOBBY_ROOM));
protocol->requestKartSelection(selection);
}
}
void NetworkKartSelectionScreen::considerKartHovered(uint8_t widget_id, std::string selection)
{
ModelViewWidget* w3 = m_kart_widgets[widget_id].m_model_view;
assert( w3 != NULL );
if (selection == RANDOM_KART_ID)
{
// Random kart
scene::IMesh* model =
ItemManager::getItemModel(Item::ITEM_BONUS_BOX);
w3->clearModels();
w3->addModel( model, Vec3(0.0f, -12.0f, 0.0f),
Vec3(35.0f, 35.0f, 35.0f) );
w3->update(0);
m_kart_widgets[widget_id].m_kart_name->setText(
_("Random Kart"), false );
}
else
{
const KartProperties *kp =
kart_properties_manager->getKart(selection);
if (kp != NULL)
{
const KartModel &kart_model = kp->getMasterKartModel();
//w3->clearModels();
w3->addModel( kart_model.getModel(), Vec3(0,0,0),
Vec3(35.0f, 35.0f, 35.0f),
kart_model.getBaseFrame() );
w3->addModel( kart_model.getWheelModel(0),
kart_model.getWheelGraphicsPosition(0) );
w3->addModel( kart_model.getWheelModel(1),
kart_model.getWheelGraphicsPosition(1) );
w3->addModel( kart_model.getWheelModel(2),
kart_model.getWheelGraphicsPosition(2) );
w3->addModel( kart_model.getWheelModel(3),
kart_model.getWheelGraphicsPosition(3) );
w3->update(0);
m_kart_widgets[widget_id].m_kart_name->setText(
selection.c_str(), false );
}
else
{
fprintf(stderr, "[KartSelectionScreen] WARNING: could not "
"find a kart named '%s'\n",
selection.c_str());
}
}
}
void NetworkKartSelectionScreen::playerSelected(uint8_t race_id, std::string kart_name)
{
uint8_t widget_id = -1;
for (unsigned int i = 0; i < m_id_mapping.size(); i++)
{
Log::info("NKSS", "Checking race id %d : mapped of %d is %d", race_id, i, m_id_mapping[i]);
if (m_id_mapping[i] == race_id)
widget_id = i;
}
assert(widget_id>=0 && widget_id < m_kart_widgets.size());
considerKartHovered(widget_id,kart_name);
m_kart_widgets[widget_id].setKartInternalName(kart_name);
m_kart_widgets[widget_id].markAsReady(); // mark player ready
}
/**
* Callback handling events from the kart selection menu
*/
@ -101,7 +209,7 @@ void NetworkKartSelectionScreen::eventCallback(GUIEngine::Widget* widget, const
{
if (name == "karts")
{
KartSelectionScreen::eventCallback(widget, name, playerID);
}
else if (name == "back")
{

View File

@ -8,16 +8,22 @@ class NetworkKartSelectionScreen : public KartSelectionScreen, public GUIEngine:
{
friend class GUIEngine::ScreenSingleton<NetworkKartSelectionScreen>;
protected:
//!< map the id of the kart widgets to race ids
std::vector<uint8_t> m_id_mapping;
NetworkKartSelectionScreen();
virtual ~NetworkKartSelectionScreen();
virtual void playerConfirm(const int playerID);
void considerKartHovered(uint8_t widget_id, std::string selection);
public:
virtual void init() OVERRIDE;
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name,
const int playerID) OVERRIDE;
virtual bool onEscapePressed() OVERRIDE;
virtual void playerSelected(uint8_t race_id, std::string kart_name);
};
#endif // NETWORK_KART_SELECTION_HPP