Solved conflicts before merge hilnius branch

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14636 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
deveee 2013-12-05 17:27:23 +00:00
parent 5b5fd87a8b
commit bc46c305f3
4 changed files with 453 additions and 102 deletions

View File

@ -59,6 +59,8 @@
#include "karts/max_speed.hpp"
#include "karts/skidding.hpp"
#include "modes/linear_world.hpp"
#include "network/network_world.hpp"
#include "network/network_manager.hpp"
#include "physics/btKart.hpp"
#include "physics/btKartRaycast.hpp"
#include "physics/btUprightConstraint.hpp"
@ -77,6 +79,12 @@
# pragma warning(disable:4355)
#endif
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define isnan _isnan
#else
# include <math.h>
#endif
/** The kart constructor.
* \param ident The identifier for the kart model to use.
* \param position The position (or rank) for this kart (between 1 and
@ -794,6 +802,8 @@ void Kart::finishedRace(float time)
// in modes that support it, start end animation
setController(new EndController(this, m_controller->getPlayer(),
m_controller));
if (m_controller->isPlayerController()) // if player is on this computer
{
GameSlot *slot = unlock_manager->getCurrentSlot();
const Challenge *challenge = slot->getCurrentChallenge();
// In case of a GP challenge don't make the end animation depend
@ -819,6 +829,7 @@ void Kart::finishedRace(float time)
this, 2.0f);
}
}
}
else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER)
{
// start end animation
@ -1236,6 +1247,8 @@ void Kart::update(float dt)
} // if there is material
// Check if any item was hit.
// check it if we're not in a network world, or if we're on the server (when network mode is on)
if (!NetworkWorld::getInstance()->isRunning() || NetworkManager::getInstance()->isServer())
ItemManager::get()->checkItemHit(this);
static video::SColor pink(255, 255, 133, 253);

View File

@ -19,6 +19,7 @@
#include "network/protocols/server_lobby_room_protocol.hpp"
#include "network/server_network_manager.hpp"
#include "network/network_world.hpp"
#include "network/protocols/get_public_address.hpp"
#include "network/protocols/show_public_address.hpp"
#include "network/protocols/connect_to_peer.hpp"
@ -28,10 +29,12 @@
#include "online/current_user.hpp"
#include "online/http_manager.hpp"
#include "config/user_config.hpp"
#include "modes/world.hpp"
#include "utils/log.hpp"
#include "utils/time.hpp"
#include "utils/random_generator.hpp"
ServerLobbyRoomProtocol::ServerLobbyRoomProtocol() : LobbyRoomProtocol(NULL)
{
}
@ -47,29 +50,45 @@ ServerLobbyRoomProtocol::~ServerLobbyRoomProtocol()
void ServerLobbyRoomProtocol::setup()
{
m_setup = NetworkManager::getInstance()->setupNewGame(); // create a new setup
m_setup->getRaceConfig()->setPlayerCount(16); //FIXME : this has to be moved to when logging into the server
m_next_id = 0;
m_state = NONE;
m_public_address.ip = 0;
m_public_address.port = 0;
m_selection_enabled = false;
m_in_race = false;
Log::info("ServerLobbyRoomProtocol", "Starting the protocol.");
}
//-----------------------------------------------------------------------------
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[0];
event->removeFront(1);
Log::info("ServerLobbyRoomProtocol", "Message received with type %d.", message_type);
if (message_type == 0x01) // player requesting connection
connectionRequested(event);
if (message_type == 0x02) // player requesting kart selection
else if (message_type == 0x02) // player requesting kart selection
kartSelectionRequested(event);
else if (message_type == 0xc0) // vote for major mode
playerMajorVote(event);
else if (message_type == 0xc1) // vote for race count
playerRaceCountVote(event);
else if (message_type == 0xc2) // vote for minor mode
playerMinorVote(event);
else if (message_type == 0xc3) // vote for track
playerTrackVote(event);
else if (message_type == 0xc4) // vote for reversed mode
playerReversedVote(event);
else if (message_type == 0xc5) // vote for laps
playerLapsVote(event);
} // if (event->type == EVENT_TYPE_MESSAGE)
else if (event->type == EVENT_TYPE_CONNECTED)
{
@ -78,6 +97,7 @@ void ServerLobbyRoomProtocol::notifyEvent(Event* event)
{
kartDisconnected(event);
} // if (event->type == EVENT_TYPE_DISCONNECTED)
return true;
}
//-----------------------------------------------------------------------------
@ -107,6 +127,54 @@ void ServerLobbyRoomProtocol::update()
}
break;
case WORKING:
{
checkIncomingConnectionRequests();
if (m_in_race && World::getWorld() && NetworkWorld::getInstance<NetworkWorld>()->isRunning())
checkRaceFinished();
break;
}
case DONE:
m_state = EXITING;
m_listener->requestTerminate(this);
break;
case EXITING:
break;
}
}
//-----------------------------------------------------------------------------
void ServerLobbyRoomProtocol::startGame()
{
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
for (unsigned int i = 0; i < peers.size(); i++)
{
NetworkString ns;
ns.ai8(0x04).ai8(4).ai32(peers[i]->getClientServerToken()); // start game
m_listener->sendMessage(this, peers[i], ns, true); // reliably
}
m_listener->requestStart(new StartGameProtocol(m_setup));
m_in_race = true;
}
//-----------------------------------------------------------------------------
void ServerLobbyRoomProtocol::startSelection()
{
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
for (unsigned int i = 0; i < peers.size(); i++)
{
NetworkString ns;
ns.ai8(0x05).ai8(4).ai32(peers[i]->getClientServerToken()); // start selection
m_listener->sendMessage(this, peers[i], ns, true); // reliably
}
m_selection_enabled = true;
}
//-----------------------------------------------------------------------------
void ServerLobbyRoomProtocol::checkIncomingConnectionRequests()
{
// first poll every 5 seconds
static double last_poll_time = 0;
@ -116,7 +184,7 @@ void ServerLobbyRoomProtocol::update()
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
Online::XMLRequest* request = new Online::XMLRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
request->setParameter("id",Online::CurrentUser::get()->getID());
request->setParameter("id",Online::CurrentUser::get()->getProfile()->getID());
request->setParameter("token",Online::CurrentUser::get()->getToken());
request->setParameter("address",addr.ip);
request->setParameter("port",addr.port);
@ -158,44 +226,83 @@ void ServerLobbyRoomProtocol::update()
m_listener->requestStart(new ConnectToPeer(m_incoming_peers_ids[i]));
}
m_incoming_peers_ids.clear();
break;
}
case DONE:
m_state = EXITING;
m_listener->requestTerminate(this);
break;
case EXITING:
break;
}
}
//-----------------------------------------------------------------------------
void ServerLobbyRoomProtocol::startGame()
void ServerLobbyRoomProtocol::checkRaceFinished()
{
assert(NetworkWorld::getInstance()->isRunning());
assert(World::getWorld());
// if race is over, give the final score to everybody
if (NetworkWorld::getInstance()->isRaceOver())
{
// calculate karts ranks :
int num_players = race_manager->getNumberOfKarts();
std::vector<int> karts_results;
std::vector<float> karts_times;
for (int j = 0; j < num_players; j++)
{
float kart_time = race_manager->getKartRaceTime(j);
for (unsigned int i = 0; i < karts_times.size(); i++)
{
if (kart_time < karts_times[i])
{
karts_times.insert(karts_times.begin()+i, kart_time);
karts_results.insert(karts_results.begin()+i, j);
break;
}
}
}
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
NetworkString queue;
for (unsigned int i = 0; i < karts_results.size(); i++)
{
queue.ai8(1).ai8(karts_results[i]); // kart pos = i+1
Log::info("ServerLobbyRoomProtocol", "Kart %d finished #%d", karts_results[i], i+1);
}
for (unsigned int i = 0; i < peers.size(); i++)
{
NetworkString ns;
ns.ai8(0x04).ai8(4).ai32(peers[i]->getClientServerToken()); // start game
m_listener->sendMessage(this, peers[i], ns, true); // reliably
}
m_listener->requestStart(new StartGameProtocol(m_setup));
ns.ai8(0x06).ai8(4).ai32(peers[i]->getClientServerToken());
NetworkString total = ns + queue;
m_listener->sendMessage(this, peers[i], total, true);
}
Log::info("ServerLobbyRoomProtocol", "End of game message sent");
m_in_race = false;
//-----------------------------------------------------------------------------
// stop race protocols
Protocol* protocol = NULL;
protocol = m_listener->getProtocol(PROTOCOL_CONTROLLER_EVENTS);
if (protocol)
m_listener->requestTerminate(protocol);
else
Log::error("ClientLobbyRoomProtocol", "No controller events protocol registered.");
void ServerLobbyRoomProtocol::startSelection()
{
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
for (unsigned int i = 0; i < peers.size(); i++)
{
NetworkString ns;
ns.ai8(0x05).ai8(4).ai32(peers[i]->getClientServerToken()); // start selection
m_listener->sendMessage(this, peers[i], ns, true); // reliably
protocol = m_listener->getProtocol(PROTOCOL_KART_UPDATE);
if (protocol)
m_listener->requestTerminate(protocol);
else
Log::error("ClientLobbyRoomProtocol", "No kart update protocol registered.");
protocol = m_listener->getProtocol(PROTOCOL_GAME_EVENTS);
if (protocol)
m_listener->requestTerminate(protocol);
else
Log::error("ClientLobbyRoomProtocol", "No game events protocol registered.");
// notify the network world that it is stopped
NetworkWorld::getInstance()->stop();
// exit the race now
race_manager->exitRace();
race_manager->setAIKartOverride("");
}
else
{
//Log::info("ServerLobbyRoomProtocol", "Phase is %d", World::getWorld()->getPhase());
}
m_selection_enabled = true;
}
//-----------------------------------------------------------------------------
@ -232,19 +339,20 @@ 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", "Receiving 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
if (m_setup->getPlayerCount() <
ServerNetworkManager::getInstance()->getMaxPlayers()) //accept
{
// add the player to the game setup
while(m_setup->getProfile(m_next_id)!=NULL)
m_next_id++;
m_next_id = m_setup->getPlayerCount();
// notify everybody that there is a new player
NetworkString message;
// new player (1) -- size of id -- id -- size of local id -- local id;
@ -267,7 +375,7 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
std::vector<NetworkPlayerProfile*> players = m_setup->getPlayers();
for (unsigned int i = 0; i < players.size(); i++)
{
// do not make a duplicate of the player
// do not duplicate the player into the message
if (players[i]->race_id != m_next_id && players[i]->user_profile->getID() != player_id)
message_ack.ai8(1).ai8(players[i]->race_id).ai8(4).ai32(players[i]->user_profile->getID());
}
@ -309,23 +417,13 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
*/
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
{
if (event->data.size() < 6 || event->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]);
return;
}
NetworkString data = event->data();
STKPeer* peer = *(event->peer);
uint32_t token = event->data.gui32(1);
if (token != peer->getClientServerToken())
{
Log::warn("ServerLobbyRoomProtocol", "Peer sending bad token. Request "
"aborted.");
if (!checkDataSizeAndToken(event, 6))
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:"
@ -367,3 +465,195 @@ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
}
//-----------------------------------------------------------------------------
/*! \brief Called when a player votes for a major race mode.
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 5 6 7
* ----------------------------------------
* Size | 1 | 4 | 1 | 1 |
* Data | 4 | priv token | 1 | major mode vote |
* ----------------------------------------
*/
void ServerLobbyRoomProtocol::playerMajorVote(Event* event)
{
NetworkString data = event->data();
STKPeer* peer = *(event->peer);
if (!checkDataSizeAndToken(event, 7))
return;
if (!isByteCorrect(event, 5, 1))
return;
uint8_t player_id = peer->getPlayerProfile()->race_id;
m_setup->getRaceConfig()->setPlayerMajorVote(player_id, data[6]);
// Send the vote to everybody (including the sender)
NetworkString other;
other.ai8(1).ai8(player_id); // add the player id
data.removeFront(5); // remove the token
other += data; // add the data
NetworkString prefix;
prefix.ai8(0xc0); // prefix the token with the ype
sendMessageToPeersChangingToken(prefix, other);
}
//-----------------------------------------------------------------------------
/*! \brief Called when a player votes for the number of races in a GP.
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 5 6 7
* ------------------------------------
* Size | 1 | 4 | 1 | 1 |
* Data | 4 | priv token | 1 | races count |
* ------------------------------------
*/
void ServerLobbyRoomProtocol::playerRaceCountVote(Event* event)
{
NetworkString data = event->data();
STKPeer* peer = *(event->peer);
if (!checkDataSizeAndToken(event, 7))
return;
if (!isByteCorrect(event, 5, 1))
return;
uint8_t player_id = peer->getPlayerProfile()->race_id;
m_setup->getRaceConfig()->setPlayerRaceCountVote(player_id, data[6]);
// Send the vote to everybody (including the sender)
NetworkString other;
other.ai8(1).ai8(player_id); // add the player id
data.removeFront(5); // remove the token
other += data; // add the data
NetworkString prefix;
prefix.ai8(0xc1); // prefix the token with the type
sendMessageToPeersChangingToken(prefix, other);
}
//-----------------------------------------------------------------------------
/*! \brief Called when a player votes for a minor race mode.
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 5 6 7
* ----------------------------------------
* Size | 1 | 4 | 1 | 1 |
* Data | 4 | priv token | 1 | minor mode vote |
* ----------------------------------------
*/
void ServerLobbyRoomProtocol::playerMinorVote(Event* event)
{
NetworkString data = event->data();
STKPeer* peer = *(event->peer);
if (!checkDataSizeAndToken(event, 7))
return;
if (!isByteCorrect(event, 5, 1))
return;
uint8_t player_id = peer->getPlayerProfile()->race_id;
m_setup->getRaceConfig()->setPlayerMinorVote(player_id, data[6]);
// Send the vote to everybody (including the sender)
NetworkString other;
other.ai8(1).ai8(player_id); // add the player id
data.removeFront(5); // remove the token
other += data; // add the data
NetworkString prefix;
prefix.ai8(0xc2); // prefix the token with the ype
sendMessageToPeersChangingToken(prefix, other);
}
//-----------------------------------------------------------------------------
/*! \brief Called when a player votes for a track.
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 5 6 N+6 N+7 N+8
* -----------------------------------------------------------
* Size | 1 | 4 | 1 | N | 1 | 1 |
* Data | 4 | priv token | N | track name | 1 | track number (gp) |
* -----------------------------------------------------------
*/
void ServerLobbyRoomProtocol::playerTrackVote(Event* event)
{
NetworkString data = event->data();
STKPeer* peer = *(event->peer);
if (!checkDataSizeAndToken(event, 8))
return;
int N = data[5];
std::string track_name = data.gs(5, N);
if (!isByteCorrect(event, N+6, 1))
return;
uint8_t player_id = peer->getPlayerProfile()->race_id;
m_setup->getRaceConfig()->setPlayerTrackVote(player_id, track_name, data[N+7]);
// Send the vote to everybody (including the sender)
NetworkString other;
other.ai8(1).ai8(player_id); // add the player id
data.removeFront(5); // remove the token
other += data; // add the data
NetworkString prefix;
prefix.ai8(0xc3); // prefix the token with the ype
sendMessageToPeersChangingToken(prefix, other);
}
//-----------------------------------------------------------------------------
/*! \brief Called when a player votes for the reverse mode of a race
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 5 6 7 8 9
* ---------------------------------------------------------
* Size | 1 | 4 | 1 | 1 | 1 | 1 |
* Data | 4 | priv token | 1 | reversed | 1 | track number (gp) |
* ---------------------------------------------------------
*/
void ServerLobbyRoomProtocol::playerReversedVote(Event* event)
{
NetworkString data = event->data();
STKPeer* peer = *(event->peer);
if (!checkDataSizeAndToken(event, 9))
return;
if (!isByteCorrect(event, 5, 1))
return;
if (!isByteCorrect(event, 7, 1))
return;
uint8_t player_id = peer->getPlayerProfile()->race_id;
m_setup->getRaceConfig()->setPlayerReversedVote(player_id, data[6]!=0, data[8]);
// Send the vote to everybody (including the sender)
NetworkString other;
other.ai8(1).ai8(player_id); // add the player id
data.removeFront(5); // remove the token
other += data; // add the data
NetworkString prefix;
prefix.ai8(0xc4); // prefix the token with the ype
sendMessageToPeersChangingToken(prefix, other);
}
//-----------------------------------------------------------------------------
/*! \brief Called when a player votes for a major race mode.
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 5 6 7 8 9
* -----------------------------------------------------
* Size | 1 | 4 | 1 | 1 | 1 | 1 |
* Data | 4 | priv token | 1 | laps | 1 | track number (gp) |
* -----------------------------------------------------
*/
void ServerLobbyRoomProtocol::playerLapsVote(Event* event)
{
NetworkString data = event->data();
STKPeer* peer = *(event->peer);
if (!checkDataSizeAndToken(event, 9))
return;
if (!isByteCorrect(event, 5, 1))
return;
if (!isByteCorrect(event, 7, 1))
return;
uint8_t player_id = peer->getPlayerProfile()->race_id;
m_setup->getRaceConfig()->setPlayerLapsVote(player_id, data[6], data[8]);
// Send the vote to everybody (including the sender)
NetworkString other;
other.ai8(1).ai8(player_id); // add the player id
data.removeFront(5); // remove the token
other += data; // add the data
NetworkString prefix;
prefix.ai8(0xc5); // prefix the token with the ype
sendMessageToPeersChangingToken(prefix, other);
}
//-----------------------------------------------------------------------------

View File

@ -23,8 +23,12 @@
#define STK_HOST_HPP
#include "network/types.hpp"
#include "network/network_string.hpp"
// enet.h includes win32.h, which without lean_and_mean includes
// winspool.h, which defines MAX_PRIORITY as a macro, which then
// results in http_manager.hpp not being compilable.
#define WIN32_LEAN_AND_MEAN
#include <enet/enet.h>
@ -60,6 +64,13 @@ class STKHost
/*! \brief Destructor */
virtual ~STKHost();
/*! \brief Log packets into a file
* \param ns : The data in the packet
* \param incoming : True if the packet comes from a peer.
* False if it's sent to a peer.
*/
static void logPacket(const NetworkString ns, bool incoming);
/*! \brief Thread function checking if data is received.
* This function tries to get data from network low-level functions as
* often as possible. When something is received, it generates an
@ -113,6 +124,7 @@ class STKHost
* \return A string containing the data of the received packet.
*/
uint8_t* receiveRawPacket();
uint8_t* receiveRawPacket(TransportAddress* sender);
/*! \brief Receives a packet directly from the network interface and
* filter its address.
* Receive a packet whithout ENet processing it. Checks that the
@ -120,10 +132,13 @@ class STKHost
* parameter. Does not check the port right now.
* \param sender : Transport address of the original sender of the
* wanted packet.
* \param max_tries : Number of times we try to read data from the
* socket. This is aproximately the time we wait in milliseconds.
* -1 means eternal tries.
* \return A string containing the data of the received packet
* matching the sender's ip address.
*/
uint8_t* receiveRawPacket(TransportAddress sender);
uint8_t* receiveRawPacket(TransportAddress sender, int max_tries = -1);
/*! \brief Broadcasts a packet to all peers.
* \param data : Data to send.
*/
@ -137,9 +152,21 @@ class STKHost
* \return True if the peer is known and connected, false elseway.
*/
bool isConnectedTo(TransportAddress peer_address);
/*! \brief Returns true when the thread should stop listening. */
int mustStopListening();
/*! \brief Returns true when the thread has stopped listening. */
bool hasStoppedListening() const { return m_listening; }
uint32_t getAddress() const { return m_host->address.host; }
uint16_t getPort() const;
protected:
ENetHost* m_host; //!< ENet host interfacing sockets.
pthread_t* m_listening_thread; //!< Thread listening network events.
pthread_mutex_t m_exit_mutex; //!< Mutex to kill properly the thread
bool m_listening;
static FILE* m_log_file; //!< Where to log packets
static pthread_mutex_t m_log_mutex; //!< To write in the log only once at a time
};

View File

@ -21,12 +21,14 @@
#include <stdexcept>
#ifdef WIN32
# define WIN32_LEAN_AND_MEAN
# define _WINSOCKAPI_
# include <windows.h>
# include <time.h>
#else
# include <stdint.h>
# include <sys/time.h>
# include <unistd.h>
#endif
#include <string>
@ -80,6 +82,13 @@ public:
#endif
}; // getTimeSinceEpoch
// ------------------------------------------------------------------------
/** Returns a time based on an arbitrary 'epoch' (e.g. could be start
* time of the application, 1.1.1970, ...).
* The value is a double precision floating point value in seconds.
*/
static double getRealTime(long startAt=0);
// ------------------------------------------------------------------------
/**
* \brief Compare two different times.
@ -97,6 +106,18 @@ public:
return 0;
}; // compareTime
// ------------------------------------------------------------------------
/** Sleeps for the specified amount of time.
* \param msec Number of milliseconds to sleep.
*/
static void sleep(int msec)
{
#ifdef WIN32
Sleep(msec);
#else
usleep(msec*1000);
#endif
} // sleep
// ------------------------------------------------------------------------
/**
* \brief Add a interval to a time.