Merge branch 'hilnius'
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14638 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
commit
ec13bcf802
29
data/gui/karts_online.stkgui
Normal file
29
data/gui/karts_online.stkgui
Normal file
@ -0,0 +1,29 @@
|
||||
<stkgui>
|
||||
|
||||
<div x="1%" y="1%" width="98%" height="99%" layout="vertical-row" >
|
||||
|
||||
<header width="80%"
|
||||
I18N="In the kart selection (player setup) screen"
|
||||
text="Choose a Kart"
|
||||
align="center" text_align="center" />
|
||||
|
||||
<placeholder id="playerskarts" width="100%" align="center" proportion="4">
|
||||
<!-- Contents is added programatically -->
|
||||
</placeholder>
|
||||
|
||||
<spacer height="15" width="25"/>
|
||||
|
||||
<box proportion="2" width="100%" layout="vertical-row" padding="2">
|
||||
<ribbon_grid id="karts" proportion="1" square_items="true" width="100%" align="center"
|
||||
child_width="90" child_height="90" max_rows="3"/>
|
||||
</box>
|
||||
|
||||
<!-- Groups will be added dynamically at runtime -->
|
||||
<tabs width="98%" x="1%" height="25" id="kartgroups">
|
||||
</tabs>
|
||||
<spacer width="100%" height="2%"/>
|
||||
</div>
|
||||
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
</stkgui>
|
Binary file not shown.
@ -157,7 +157,6 @@ src/modes/world_with_rank.cpp
|
||||
src/network/client_network_manager.cpp
|
||||
src/network/event.cpp
|
||||
src/network/game_setup.cpp
|
||||
src/network/http_functions.cpp
|
||||
src/network/network_interface.cpp
|
||||
src/network/network_manager.cpp
|
||||
src/network/network_string.cpp
|
||||
@ -183,6 +182,7 @@ src/network/protocols/start_game_protocol.cpp
|
||||
src/network/protocols/start_server.cpp
|
||||
src/network/protocols/stop_server.cpp
|
||||
src/network/protocols/synchronization_protocol.cpp
|
||||
src/network/race_config.cpp
|
||||
src/network/server_network_manager.cpp
|
||||
src/network/stk_host.cpp
|
||||
src/network/stk_peer.cpp
|
||||
@ -480,7 +480,6 @@ src/modes/world_with_rank.hpp
|
||||
src/network/event.hpp
|
||||
src/network/client_network_manager.hpp
|
||||
src/network/game_setup.hpp
|
||||
src/network/http_functions.hpp
|
||||
src/network/network_interface.hpp
|
||||
src/network/network_manager.hpp
|
||||
src/network/network_string.hpp
|
||||
@ -506,6 +505,7 @@ src/network/protocols/start_game_protocol.hpp
|
||||
src/network/protocols/start_server.hpp
|
||||
src/network/protocols/stop_server.hpp
|
||||
src/network/protocols/synchronization_protocol.hpp
|
||||
src/network/race_config.hpp
|
||||
src/network/remote_kart_info.hpp
|
||||
src/network/server_network_manager.hpp
|
||||
src/network/singleton.hpp
|
||||
|
@ -182,6 +182,162 @@ void GroupUserConfigParam::addChild(UserConfigParam* child)
|
||||
} // addChild
|
||||
|
||||
|
||||
// ============================================================================
|
||||
template<typename T>
|
||||
ListUserConfigParam<T>::ListUserConfigParam(const char* param_name,
|
||||
const char* comment)
|
||||
{
|
||||
m_param_name = param_name;
|
||||
all_params.push_back(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
} // ListUserConfigParam
|
||||
|
||||
// ============================================================================
|
||||
template<typename T>
|
||||
ListUserConfigParam<T>::ListUserConfigParam(const char* param_name,
|
||||
const char* comment,
|
||||
int nb_elements,
|
||||
...)
|
||||
{
|
||||
m_param_name = param_name;
|
||||
all_params.push_back(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
|
||||
// add the default list
|
||||
va_list arguments;
|
||||
va_start ( arguments, nb_elements );
|
||||
for ( int i = 0; i < nb_elements; i++ )
|
||||
m_elements.push_back(va_arg ( arguments, T ));
|
||||
va_end ( arguments ); // Cleans up the list
|
||||
} // ListUserConfigParam
|
||||
|
||||
// ============================================================================
|
||||
template<typename T>
|
||||
ListUserConfigParam<T>::ListUserConfigParam(const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment)
|
||||
{
|
||||
m_param_name = param_name;
|
||||
group->addChild(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
} // ListUserConfigParam
|
||||
|
||||
// ============================================================================
|
||||
template<typename T>
|
||||
ListUserConfigParam<T>::ListUserConfigParam(const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment,
|
||||
int nb_elements,
|
||||
...)
|
||||
{
|
||||
m_param_name = param_name;
|
||||
group->addChild(this);
|
||||
if(comment != NULL) m_comment = comment;
|
||||
|
||||
// add the default list
|
||||
va_list arguments;
|
||||
va_start ( arguments, nb_elements );
|
||||
for ( int i = 0; i < nb_elements; i++ )
|
||||
m_elements.push_back(va_arg ( arguments, T ));
|
||||
va_end ( arguments ); // Cleans up the list
|
||||
} // ListUserConfigParam
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
void ListUserConfigParam<T>::write(XMLWriter& stream) const
|
||||
{
|
||||
const int elts_amount = m_elements.size();
|
||||
|
||||
// comment
|
||||
if(m_comment.size() > 0) stream << " <!-- " << m_comment.c_str();
|
||||
stream << L" -->\n <" << m_param_name.c_str() << "\n";
|
||||
|
||||
stream << L" Size=\"" << elts_amount << "\"\n";
|
||||
// actual elements
|
||||
for (int n=0; n<elts_amount; n++)
|
||||
{
|
||||
stream << L" " << n << "=\"" << m_elements[n] << "\"\n";
|
||||
}
|
||||
stream << L" >\n";
|
||||
stream << L" </" << m_param_name.c_str() << ">\n\n";
|
||||
} // write
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Write your own convert function depending on the type of list you use.
|
||||
void convert(std::string str, char** str2)
|
||||
{
|
||||
*str2 = (char*)(malloc(str.size()+1));
|
||||
strcpy(*str2, str.c_str());
|
||||
}
|
||||
// Write your own equals function depending on the type of list you use.
|
||||
bool equals(char* str1, char* str2)
|
||||
{
|
||||
return (strcmp(str1, str2) == 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ListUserConfigParam<T>::findYourDataInAChildOf(const XMLNode* node)
|
||||
{
|
||||
const XMLNode* child = node->getNode( m_param_name );
|
||||
if (child == NULL)
|
||||
{
|
||||
//std::cerr << "/!\\ User Config : Couldn't find parameter group "
|
||||
// << paramName << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int attr_count = 0;
|
||||
child->get( "Size", &attr_count);
|
||||
for (int n=0; n<attr_count; n++)
|
||||
{
|
||||
T elt;
|
||||
std::ostringstream oss;
|
||||
oss << n;
|
||||
std::string str;
|
||||
child->get( oss.str(), &str);
|
||||
convert(str, &elt);
|
||||
// check if the element is already there :
|
||||
bool there = false;
|
||||
for (unsigned int i = 0; i < m_elements.size(); i++)
|
||||
{
|
||||
if (equals(m_elements[i], elt))
|
||||
{
|
||||
there = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!there)
|
||||
{
|
||||
Log::info("ListUserConfigParam", "New data : %s, \"%s\"", str.c_str(), elt);
|
||||
m_elements.push_back(elt);
|
||||
}
|
||||
}
|
||||
|
||||
} // findYourDataInAChildOf
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
void ListUserConfigParam<T>::findYourDataInAnAttributeOf(const XMLNode* node)
|
||||
{
|
||||
} // findYourDataInAnAttributeOf
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
void ListUserConfigParam<T>::addElement(T element)
|
||||
{
|
||||
m_elements.push_back(element);
|
||||
} // findYourDataInAnAttributeOf
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
irr::core::stringw ListUserConfigParam<T>::toString() const
|
||||
{
|
||||
return "";
|
||||
} // toString
|
||||
|
||||
|
||||
|
||||
// ============================================================================
|
||||
IntUserConfigParam::IntUserConfigParam(int default_value,
|
||||
const char* param_name,
|
||||
|
@ -99,6 +99,45 @@ public:
|
||||
irr::core::stringw toString() const;
|
||||
}; // GroupUserConfigParam
|
||||
|
||||
// ============================================================================
|
||||
template<typename T>
|
||||
class ListUserConfigParam : public UserConfigParam
|
||||
{
|
||||
std::vector<T> m_elements;
|
||||
|
||||
public:
|
||||
ListUserConfigParam(const char* param_name,
|
||||
const char* comment = NULL);
|
||||
ListUserConfigParam(const char* param_name,
|
||||
const char* comment,
|
||||
int nb_elts,
|
||||
...);
|
||||
ListUserConfigParam(const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment = NULL);
|
||||
ListUserConfigParam(const char* param_name,
|
||||
GroupUserConfigParam* group,
|
||||
const char* comment,
|
||||
int nb_elts,
|
||||
...);
|
||||
|
||||
void write(XMLWriter& stream) const;
|
||||
void findYourDataInAChildOf(const XMLNode* node);
|
||||
void findYourDataInAnAttributeOf(const XMLNode* node);
|
||||
|
||||
void addElement(T element);
|
||||
|
||||
irr::core::stringw toString() const;
|
||||
|
||||
operator std::vector<T>() const
|
||||
{ return m_elements; }
|
||||
float& operator=(const std::vector<T>& v)
|
||||
{ m_elements = std::vector<T>(v); return m_elements; }
|
||||
float& operator=(const ListUserConfigParam& v)
|
||||
{ m_elements = std::vector<T>(v); return m_elements; }
|
||||
}; // ListUserConfigParam
|
||||
typedef ListUserConfigParam<char*> StringListUserConfigParam;
|
||||
|
||||
// ============================================================================
|
||||
class IntUserConfigParam : public UserConfigParam
|
||||
{
|
||||
@ -489,12 +528,44 @@ namespace UserConfigParams
|
||||
PARAM_PREFIX IntUserConfigParam m_server_port
|
||||
PARAM_DEFAULT( IntUserConfigParam(7321, "server_port",
|
||||
"Information about the port to listen on.") );
|
||||
|
||||
|
||||
PARAM_PREFIX IntUserConfigParam m_server_max_players
|
||||
PARAM_DEFAULT( IntUserConfigParam(16, "server_max_players",
|
||||
"Maximum number of players on the server.") );
|
||||
|
||||
|
||||
|
||||
PARAM_PREFIX StringListUserConfigParam m_stun_servers
|
||||
PARAM_DEFAULT( StringListUserConfigParam("Stun_servers", "The stun servers"
|
||||
" that will be used to know the public address.",
|
||||
24,
|
||||
"provserver.televolution.net",
|
||||
"sip1.lakedestiny.cordiaip.com",
|
||||
"stun1.voiceeclipse.net",
|
||||
"stun01.sipphone.com",
|
||||
"stun.callwithus.com",
|
||||
"stun.counterpath.net",
|
||||
"stun.endigovoip.com",
|
||||
"stun.ekiga.net",
|
||||
"stun.ideasip.com" ,
|
||||
"stun.internetcalls.com",
|
||||
"stun.ipns.com",
|
||||
"stun.noc.ams-ix.net",
|
||||
"stun.phonepower.com",
|
||||
"stun.phoneserve.com",
|
||||
"stun.rnktel.com",
|
||||
"stun.softjoys.com",
|
||||
"stunserver.org",
|
||||
"stun.sipgate.net",
|
||||
"stun.stunprotocol.org",
|
||||
"stun.voip.aebc.com",
|
||||
"stun.voipbuster.com",
|
||||
"stun.voxalot.com",
|
||||
"stun.voxgratia.org",
|
||||
"stun.xten.com") );
|
||||
|
||||
PARAM_PREFIX StringUserConfigParam m_packets_log_filename
|
||||
PARAM_DEFAULT( StringUserConfigParam("packets_log.txt", "packets_log_filename",
|
||||
"Where to log received and sent packets.") );
|
||||
|
||||
// ---- Graphic Quality
|
||||
PARAM_PREFIX GroupUserConfigParam m_graphics_quality
|
||||
PARAM_DEFAULT( GroupUserConfigParam("GFX",
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/wiimote.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include "wiiuse.h"
|
||||
@ -110,7 +111,7 @@ void WiimoteManager::launchDetection(int timeout)
|
||||
wiiuse_rumble(wiimote_handle, 1);
|
||||
}
|
||||
|
||||
irr_driver->getDevice()->sleep(200);
|
||||
StkTime::sleep(200);
|
||||
|
||||
for(unsigned int i=0 ; i < m_wiimotes.size(); i++)
|
||||
{
|
||||
@ -284,7 +285,7 @@ void WiimoteManager::threadFunc()
|
||||
}
|
||||
}
|
||||
|
||||
irr_driver->getDevice()->sleep(1); // 'cause come on, the whole CPU is not ours :)
|
||||
StkTime::sleep(1); // 'cause come on, the whole CPU is not ours :)
|
||||
} // end while
|
||||
} // threadFunc
|
||||
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "io/file_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/network_world.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
@ -309,7 +311,14 @@ void ItemManager::checkItemHit(AbstractKart* kart)
|
||||
// we pass the kart and the position separately.
|
||||
if((*i)->hitKart(kart->getXYZ(), kart))
|
||||
{
|
||||
collectedItem(*i, kart);
|
||||
// if we're not playing online, pick the item.
|
||||
if (!NetworkWorld::getInstance()->isRunning())
|
||||
collectedItem(*i, kart);
|
||||
else if (NetworkManager::getInstance()->isServer())
|
||||
{
|
||||
collectedItem(*i, kart);
|
||||
NetworkWorld::getInstance()->collectedItem(*i, kart);
|
||||
}
|
||||
} // if hit
|
||||
} // for m_all_items
|
||||
} // checkItemHit
|
||||
|
@ -393,13 +393,21 @@ void Powerup::hitBonusBox(const Item &item, int add_info)
|
||||
|
||||
// Check if two bouncing balls are collected less than getRubberBallTimer()
|
||||
//seconds apart. If yes, then call getRandomPowerup again. If no, then break.
|
||||
for(int i=0; i<20; i++)
|
||||
if (add_info<0)
|
||||
{
|
||||
new_powerup = powerup_manager->getRandomPowerup(position, &n);
|
||||
if(new_powerup != PowerupManager::POWERUP_RUBBERBALL ||
|
||||
( World::getWorld()->getTime() - powerup_manager->getBallCollectTime()) >
|
||||
RubberBall::getTimeBetweenRubberBalls() )
|
||||
break;
|
||||
for(int i=0; i<20; i++)
|
||||
{
|
||||
new_powerup = powerup_manager->getRandomPowerup(position, &n);
|
||||
if(new_powerup != PowerupManager::POWERUP_RUBBERBALL ||
|
||||
( World::getWorld()->getTime() - powerup_manager->getBallCollectTime()) >
|
||||
RubberBall::getTimeBetweenRubberBalls() )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // set powerup manually
|
||||
{
|
||||
new_powerup = (PowerupManager::PowerupType)((add_info>>4)&0x0f); // highest 4 bits for the type
|
||||
n = (add_info&0x0f); // last 4 bits for the amount
|
||||
}
|
||||
|
||||
if(new_powerup == PowerupManager::POWERUP_RUBBERBALL)
|
||||
|
@ -272,7 +272,7 @@ public:
|
||||
* \param add_info Additional info, used in networking games to force
|
||||
* a specific item to be used (instead of a random item) to keep
|
||||
* all karts in synch. */
|
||||
virtual void collectedItem(Item *item, int random_attachment) = 0;
|
||||
virtual void collectedItem(Item *item, int add_info) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current position of this kart in the race. */
|
||||
virtual int getPosition() const = 0;
|
||||
|
17
src/main.cpp
17
src/main.cpp
@ -120,6 +120,7 @@
|
||||
# ifdef __CYGWIN__
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define _WINSOCKAPI_
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
@ -176,6 +177,12 @@
|
||||
#include "network/protocols/server_lobby_room_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/server_network_manager.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/server_lobby_room_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "online/profile_manager.hpp"
|
||||
#include "online/servers_manager.hpp"
|
||||
#include "race/grand_prix_manager.hpp"
|
||||
@ -1147,6 +1154,7 @@ int handleCmdLine(int argc, char **argv)
|
||||
irr::core::stringw s;
|
||||
Online::CurrentUser::SignInRequest* request =
|
||||
Online::CurrentUser::get()->requestSignIn(login, password, false, false);
|
||||
|
||||
Online::HTTPManager::get()->synchronousRequest(request);
|
||||
|
||||
if (request->isSuccess())
|
||||
@ -1425,6 +1433,9 @@ int main(int argc, char *argv[] )
|
||||
// load the network manager
|
||||
// If the server has been created (--server option), this will do nothing (just a warning):
|
||||
NetworkManager::getInstance<ClientNetworkManager>();
|
||||
if (NetworkManager::getInstance()->isServer())
|
||||
ServerNetworkManager::getInstance()->setMaxPlayers(
|
||||
UserConfigParams::m_server_max_players);
|
||||
NetworkManager::getInstance()->run();
|
||||
if (NetworkManager::getInstance()->isServer())
|
||||
{
|
||||
@ -1453,11 +1464,8 @@ int main(int argc, char *argv[] )
|
||||
if (players[n].getName() == UserConfigParams::m_default_player.toString())
|
||||
unlock_manager->setCurrentSlot(players[n].getUniqueID());
|
||||
|
||||
main_loop->run();
|
||||
throw "salut";
|
||||
}
|
||||
|
||||
if(!UserConfigParams::m_no_start_screen)
|
||||
else if(!UserConfigParams::m_no_start_screen)
|
||||
{
|
||||
StateManager::get()->pushScreen(StoryModeLobbyScreen::getInstance());
|
||||
#ifdef ENABLE_WIIUSE
|
||||
@ -1616,6 +1624,7 @@ int main(int argc, char *argv[] )
|
||||
// so we don't crash later when StateManager tries to access input devices.
|
||||
StateManager::get()->resetActivePlayers();
|
||||
if(input_manager) delete input_manager; // if early crash avoid delete NULL
|
||||
NetworkManager::getInstance()->abort();
|
||||
|
||||
cleanSuperTuxKart();
|
||||
|
||||
|
@ -83,7 +83,7 @@ float MainLoop::getLimitedDt()
|
||||
int wait_time = 1000/max_fps - 1000/current_fps;
|
||||
if(wait_time < 1) wait_time = 1;
|
||||
|
||||
irr_driver->getDevice()->sleep(wait_time);
|
||||
StkTime::sleep(wait_time);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
@ -166,6 +166,10 @@ void MainLoop::run()
|
||||
PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
|
||||
ProtocolManager::getInstance()->update();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F);
|
||||
Online::HTTPManager::get()->update(dt);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
PROFILER_SYNC_FRAME();
|
||||
|
@ -452,7 +452,7 @@ void SoccerWorld::initKartList()
|
||||
// Set kart positions, ordering them by team
|
||||
for(unsigned int n=0; n<kart_amount; n++)
|
||||
{
|
||||
|
||||
|
||||
SoccerTeam team = race_manager->getLocalKartInfo(n).getSoccerTeam();
|
||||
m_karts[n]->setPosition(team_cur_position[team]);
|
||||
team_cur_position[team]++;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "items/powerup_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/controller/controller.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
StandardRace::StandardRace() : LinearWorld()
|
||||
@ -123,5 +124,6 @@ void StandardRace::endRaceEarly()
|
||||
} // Finish the active players
|
||||
endSetKartPositions();
|
||||
setPhase(RESULT_DISPLAY_PHASE);
|
||||
terminateRace();
|
||||
if (!isNetworkWorld() || NetworkManager::getInstance()->isServer())
|
||||
terminateRace();
|
||||
} // endRaceEarly
|
||||
|
@ -118,6 +118,7 @@ World::World() : WorldStatus(), m_clear_color(255,100,101,140)
|
||||
m_schedule_exit_race = false;
|
||||
m_self_destruct = false;
|
||||
m_schedule_tutorial = false;
|
||||
m_is_network_world = false;
|
||||
|
||||
m_stop_music_when_dialog_open = true;
|
||||
|
||||
@ -218,6 +219,7 @@ void World::reset()
|
||||
m_faster_music_active = false;
|
||||
m_eliminated_karts = 0;
|
||||
m_eliminated_players = 0;
|
||||
m_is_network_world = false;
|
||||
|
||||
for ( KartList::iterator i = m_karts.begin(); i != m_karts.end() ; ++i )
|
||||
{
|
||||
@ -435,14 +437,17 @@ void World::terminateRace()
|
||||
int best_finish_time = -1;
|
||||
std::string highscore_who = "";
|
||||
StateManager::ActivePlayer* best_player = NULL;
|
||||
updateHighscores(&best_highscore_rank, &best_finish_time, &highscore_who,
|
||||
if (!this->isNetworkWorld())
|
||||
{
|
||||
updateHighscores(&best_highscore_rank, &best_finish_time, &highscore_who,
|
||||
&best_player);
|
||||
unlock_manager->getCurrentSlot()->raceFinished();
|
||||
}
|
||||
|
||||
unlock_manager->getCurrentSlot()->raceFinished();
|
||||
((MapAchievement *) AchievementsManager::get()->getActive()->getAchievement(1))->increase(getTrack()->getIdent(), 1);
|
||||
AchievementsManager::get()->onRaceEnd();
|
||||
|
||||
|
||||
if (m_race_gui) m_race_gui->clearAllMessages();
|
||||
// we can't delete the race gui here, since it is needed in case of
|
||||
// a restart: the constructor of it creates some textures which assume
|
||||
@ -947,7 +952,9 @@ void World::updateHighscores(int* best_highscore_rank, int* best_finish_time,
|
||||
|
||||
PlayerController *controller = (PlayerController*)(k->getController());
|
||||
|
||||
int highscore_rank = highscores->addData(k->getIdent(),
|
||||
int highscore_rank = 0;
|
||||
if (controller->getPlayer()->getProfile() != NULL) // if we have the player profile here
|
||||
highscore_rank = highscores->addData(k->getIdent(),
|
||||
controller->getPlayer()->getProfile()->getName(),
|
||||
k->getFinishTime());
|
||||
|
||||
|
@ -152,6 +152,9 @@ protected:
|
||||
*/
|
||||
bool m_self_destruct;
|
||||
|
||||
/** Set when the world is online and counts network players. */
|
||||
bool m_is_network_world;
|
||||
|
||||
virtual void onGo();
|
||||
/** Returns true if the race is over. Must be defined by all modes. */
|
||||
virtual bool isRaceOver() = 0;
|
||||
@ -197,7 +200,7 @@ public:
|
||||
* this method in child classes to provide it. */
|
||||
virtual const std::string& getIdent() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of rescue positions on a given track and game
|
||||
/** Returns the number of rescue positions on a given track and game
|
||||
* mode. */
|
||||
virtual unsigned int getNumberOfRescuePositions() const OVERRIDE = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
@ -327,6 +330,10 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void escapePressed();
|
||||
|
||||
/** Set the network mode (true if networked) */
|
||||
void setNetworkWorld(bool is_networked) { m_is_network_world = is_networked; }
|
||||
|
||||
bool isNetworkWorld() const { return m_is_network_world; }
|
||||
}; // World
|
||||
|
||||
#endif
|
||||
|
@ -36,7 +36,6 @@ void* waitInput(void* data)
|
||||
{
|
||||
std::string str = "";
|
||||
bool stop = false;
|
||||
int n = 0;
|
||||
|
||||
while(!stop)
|
||||
{
|
||||
@ -45,14 +44,6 @@ void* waitInput(void* data)
|
||||
{
|
||||
stop = true;
|
||||
}
|
||||
else if (str == "disconnect")
|
||||
{
|
||||
NetworkManager::getInstance()->getPeers()[0]->disconnect();
|
||||
}
|
||||
else if (str == "connect")
|
||||
{
|
||||
ProtocolManager::getInstance()->requestStart(new ConnectToServer());
|
||||
}
|
||||
else if (str == "select")
|
||||
{
|
||||
std::string str2;
|
||||
@ -61,9 +52,48 @@ void* waitInput(void* data)
|
||||
ClientLobbyRoomProtocol* clrp = static_cast<ClientLobbyRoomProtocol*>(protocol);
|
||||
clrp->requestKartSelection(str2);
|
||||
}
|
||||
else if (str == "synchronize")
|
||||
else if (str == "vote")
|
||||
{
|
||||
ProtocolManager::getInstance()->requestStart(new SynchronizationProtocol());
|
||||
std::cout << "Vote for ? (track/laps/reversed/major/minor/race#) :";
|
||||
std::string str2;
|
||||
getline(std::cin, str2);
|
||||
Protocol* protocol = ProtocolManager::getInstance()->getProtocol(PROTOCOL_LOBBY_ROOM);
|
||||
ClientLobbyRoomProtocol* clrp = static_cast<ClientLobbyRoomProtocol*>(protocol);
|
||||
if (str2 == "track")
|
||||
{
|
||||
std::cin >> str2;
|
||||
clrp->voteTrack(str2);
|
||||
}
|
||||
else if (str2 == "laps")
|
||||
{
|
||||
int cnt;
|
||||
std::cin >> cnt;
|
||||
clrp->voteLaps(cnt);
|
||||
}
|
||||
else if (str2 == "reversed")
|
||||
{
|
||||
bool cnt;
|
||||
std::cin >> cnt;
|
||||
clrp->voteReversed(cnt);
|
||||
}
|
||||
else if (str2 == "major")
|
||||
{
|
||||
int cnt;
|
||||
std::cin >> cnt;
|
||||
clrp->voteMajor(cnt);
|
||||
}
|
||||
else if (str2 == "minor")
|
||||
{
|
||||
int cnt;
|
||||
std::cin >> cnt;
|
||||
clrp->voteMinor(cnt);
|
||||
}
|
||||
else if (str2 == "race#")
|
||||
{
|
||||
int cnt;
|
||||
std::cin >> cnt;
|
||||
clrp->voteRaceCount(cnt);
|
||||
}
|
||||
}
|
||||
else if (NetworkManager::getInstance()->getPeers().size() > 0)
|
||||
{
|
||||
@ -87,6 +117,7 @@ ClientNetworkManager::ClientNetworkManager()
|
||||
|
||||
ClientNetworkManager::~ClientNetworkManager()
|
||||
{
|
||||
pthread_cancel(*m_thread_keyboard);
|
||||
}
|
||||
|
||||
void ClientNetworkManager::run()
|
||||
|
@ -16,27 +16,58 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file client_network_manager.hpp
|
||||
* \brief Defines a Client Network manager, that will connect to a server.
|
||||
*/
|
||||
|
||||
#ifndef CLIENT_NETWORK_MANAGER_HPP
|
||||
#define CLIENT_NETWORK_MANAGER_HPP
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
|
||||
/*! \class ClientNetworkManager
|
||||
* \ingroup network
|
||||
*/
|
||||
class ClientNetworkManager : public NetworkManager
|
||||
{
|
||||
friend class Singleton<NetworkManager>;
|
||||
public:
|
||||
/*! \brief Get the instance.
|
||||
* This is a utility function to avoid passing templates parameters
|
||||
* to the getInstance singleton method.
|
||||
*/
|
||||
static ClientNetworkManager* getInstance()
|
||||
{
|
||||
return Singleton<NetworkManager>::getInstance<ClientNetworkManager>();
|
||||
}
|
||||
|
||||
/*! \brief Initializes network.
|
||||
* This starts the threads and initializes network libraries.
|
||||
*/
|
||||
virtual void run();
|
||||
/*! \brief Resets the network socket. */
|
||||
virtual void reset();
|
||||
/*! \brief Sends a packet to the server.
|
||||
* \param data : The network 8-bit string to send.
|
||||
* \param reliable : If set to true, ENet will ensure that the packet is received.
|
||||
*/
|
||||
virtual void sendPacket(const NetworkString& data, bool reliable = true);
|
||||
|
||||
|
||||
/*! \brief Get the peer (the server)
|
||||
* \return The peer with whom we're connected (if it exists). NULL elseway.
|
||||
*/
|
||||
STKPeer* getPeer();
|
||||
/*! \brief Function to know if we're a server.
|
||||
* \return Returns true if we're on a server. False if we're a client.
|
||||
*/
|
||||
virtual bool isServer() { return false; }
|
||||
/*! \brief Function used to notice the manager that we're connected to a server.
|
||||
* \param value : True if we're connected, false elseway.
|
||||
*/
|
||||
void setConnected(bool value) { m_connected = value; }
|
||||
/*! \brief Function to know if we're a server.
|
||||
* \return Returns true if we're on a server. False if we're a client.
|
||||
*/
|
||||
bool isConnected() { return m_connected; }
|
||||
|
||||
protected:
|
||||
@ -44,7 +75,7 @@ class ClientNetworkManager : public NetworkManager
|
||||
virtual ~ClientNetworkManager();
|
||||
|
||||
bool m_connected; //!< Is the user connected to a server
|
||||
pthread_t* m_thread_keyboard;
|
||||
pthread_t* m_thread_keyboard; //!< The thread listening for keyboard console input.
|
||||
};
|
||||
|
||||
#endif // CLIENT_NETWORK_MANAGER_HPP
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,11 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file event.hpp
|
||||
* \brief Contains an interface to store network events, like connections,
|
||||
* disconnections and messages.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_HPP
|
||||
#define EVENT_HPP
|
||||
|
||||
@ -65,11 +70,17 @@ class Event
|
||||
*/
|
||||
void removeFront(int size);
|
||||
|
||||
/*! \brief Get a copy of the data.
|
||||
* \return A copy of the message data. This is empty for events like
|
||||
* connection or disconnections.
|
||||
*/
|
||||
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.
|
||||
};
|
||||
|
||||
|
@ -18,12 +18,16 @@
|
||||
|
||||
#include "network/game_setup.hpp"
|
||||
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GameSetup::GameSetup()
|
||||
{
|
||||
m_race_config = new RaceConfig();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -43,7 +47,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->getID(), profile->race_id);
|
||||
}
|
||||
|
||||
@ -79,6 +83,10 @@ bool GameSetup::removePlayer(uint8_t id)
|
||||
"Remains %u.", m_players.size());
|
||||
return true;
|
||||
}
|
||||
if (m_players[i]->race_id > id)
|
||||
{
|
||||
m_players[i]->race_id--; // all indices in [0;n[ (n = #players)
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -106,6 +114,39 @@ void GameSetup::setPlayerKart(uint8_t id, std::string kart_name)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GameSetup::bindKartsToProfiles()
|
||||
{
|
||||
World::KartList karts = World::getWorld()->getKarts();
|
||||
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
Log::info("GameSetup", "Player %d has id %d and kart %s", i, m_players[i]->race_id, m_players[i]->kart_name.c_str());
|
||||
}
|
||||
for (unsigned int i = 0; i < karts.size(); i++)
|
||||
{
|
||||
Log::info("GameSetup", "Kart %d has id %d and kart %s", i, karts[i]->getWorldKartId(), karts[i]->getIdent().c_str());
|
||||
}
|
||||
for (unsigned int j = 0; j < m_players.size(); j++)
|
||||
{
|
||||
bool found = false;
|
||||
for (unsigned int i = 0 ; i < karts.size(); i++)
|
||||
{
|
||||
if (karts[i]->getIdent() == m_players[j]->kart_name)
|
||||
{
|
||||
m_players[j]->world_kart_id = karts[i]->getWorldKartId();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
Log::error("GameSetup", "Error while binding world kart ids to players profiles.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const NetworkPlayerProfile* GameSetup::getProfile(uint32_t id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
@ -134,6 +175,20 @@ const NetworkPlayerProfile* GameSetup::getProfile(uint8_t id)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const NetworkPlayerProfile* GameSetup::getProfile(std::string kart_name)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->kart_name == kart_name)
|
||||
{
|
||||
return m_players[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GameSetup::isKartAvailable(std::string kart_name)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define GAME_SETUP_HPP
|
||||
|
||||
#include "online/profile.hpp"
|
||||
#include "network/race_config.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@ -39,6 +40,7 @@ class NetworkPlayerProfile
|
||||
uint8_t race_id; //!< The id of the player for the race
|
||||
std::string kart_name; //!< The selected kart.
|
||||
Online::Profile* user_profile; //!< Pointer to the lobby profile
|
||||
uint8_t world_kart_id; //!< the kart id in the World class (pointer to AbstractKart)
|
||||
};
|
||||
|
||||
/*! \class GameSetup
|
||||
@ -55,18 +57,48 @@ class GameSetup
|
||||
bool removePlayer(uint32_t id); //!< Remove a player by id.
|
||||
bool removePlayer(uint8_t id); //!< Remove a player by local id.
|
||||
void setPlayerKart(uint8_t id, std::string kart_name); //!< Set the kart of a player
|
||||
void bindKartsToProfiles(); //!< Sets the right world_kart_id in profiles
|
||||
|
||||
/** \brief Get the players that are in the game
|
||||
* \return A vector containing pointers on the players profiles.
|
||||
*/
|
||||
std::vector<NetworkPlayerProfile*> getPlayers() { return m_players; }
|
||||
int getPlayerCount() { return m_players.size(); }
|
||||
const NetworkPlayerProfile* getProfile(uint32_t id); //!< Get a profile by database id
|
||||
const NetworkPlayerProfile* getProfile(uint8_t id); //!< Get the profile by the lobby id
|
||||
/*! \brief Get a network player profile matching a universal id.
|
||||
* \param id : Global id of the player (the one in the SQL database)
|
||||
* \return The profile of the player matching the id.
|
||||
*/
|
||||
const NetworkPlayerProfile* getProfile(uint32_t id);
|
||||
/*! \brief Get a network player profile matching a kart name.
|
||||
* \param kart_name : Name of the kart used by the player.
|
||||
* \return The profile of the player having the kart kart_name
|
||||
*/
|
||||
const NetworkPlayerProfile* getProfile(uint8_t id);
|
||||
/*! \brief Get a network player profile matching a kart name.
|
||||
* \param kart_name : Name of the kart used by the player.
|
||||
* \return The profile of the player having the kart kart_name.
|
||||
*/
|
||||
const NetworkPlayerProfile* getProfile(std::string kart_name);
|
||||
|
||||
/*! \brief Used to know if a kart is available.
|
||||
* \param kart_name : Name of the kart to check.
|
||||
* \return True if the kart hasn't been selected yet, false elseway.
|
||||
*/
|
||||
bool isKartAvailable(std::string kart_name);
|
||||
/*! \brief Used to know if a kart is playable.
|
||||
* \param kart_name : Name of the kart to check.
|
||||
* \return True if the kart is playable (standard kart).
|
||||
* Currently this is always true as the kart selection screen shows
|
||||
* only the standard karts.
|
||||
*/
|
||||
bool isKartAllowed(std::string kart_name) {return true; }
|
||||
|
||||
RaceConfig* getRaceConfig() { return m_race_config; }
|
||||
|
||||
protected:
|
||||
std::vector<NetworkPlayerProfile*> m_players; //!< Information about players
|
||||
NetworkPlayerProfile m_self_profile; //!< Information about self (client only)
|
||||
RaceConfig* m_race_config;
|
||||
};
|
||||
|
||||
#endif // GAME_SETUP_HPP
|
||||
|
@ -1,67 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "network/http_functions.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <curl/curl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
|
||||
namespace HTTP
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
((std::string*)userp)->append((char*)contents, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
curl = curl_easy_init();
|
||||
if(!curl)
|
||||
Log::error("HTTP", "Error while loading cURL library.\n");
|
||||
}
|
||||
|
||||
std::string getPage(std::string url)
|
||||
{
|
||||
std::string readBuffer;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK)
|
||||
Log::error("HTTP", "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
|
||||
return readBuffer;
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
{
|
||||
curl_easy_cleanup(curl);
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef HTTP_FUNCTIONS_HPP
|
||||
#define HTTP_FUNCTIONS_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace HTTP
|
||||
{
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
std::string getPage(std::string url);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // HTTP_FUNCTIONS_HPP
|
@ -16,6 +16,10 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file network_interface.hpp
|
||||
* \brief Defines an interface to network middle-level functions.
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_INTERFACE_H
|
||||
#define NETWORK_INTERFACE_H
|
||||
|
||||
@ -26,19 +30,24 @@
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
/** \class NetworkInterface
|
||||
* \ingroup network
|
||||
*/
|
||||
class NetworkInterface : public Singleton<NetworkInterface>
|
||||
{
|
||||
friend class Singleton<NetworkInterface>;
|
||||
public:
|
||||
|
||||
|
||||
/*! \brief Used to init the network.
|
||||
* \param server : True if we're a server.
|
||||
*/
|
||||
void initNetwork(bool server);
|
||||
|
||||
|
||||
protected:
|
||||
// protected functions
|
||||
NetworkInterface();
|
||||
virtual ~NetworkInterface();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // NETWORK_INTERFACE_H
|
||||
|
@ -76,6 +76,13 @@ void NetworkManager::reset()
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkManager::abort()
|
||||
{
|
||||
m_localhost->stopListening();
|
||||
reset();
|
||||
ProtocolManager::getInstance()->abort();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool NetworkManager::connect(TransportAddress peer)
|
||||
@ -116,7 +123,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());
|
||||
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,10 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file network_manager.hpp
|
||||
* \brief Instantiates the generic functionnalities of a network manager.
|
||||
*/
|
||||
|
||||
#ifndef NETWORKMANAGER_HPP
|
||||
#define NETWORKMANAGER_HPP
|
||||
|
||||
@ -30,22 +34,55 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
/** \class NetworkManager
|
||||
* \brief Gives the general functions to use network communication.
|
||||
* This class is in charge of storing the peers connected to this host.
|
||||
* It also stores the host, and brings the functions to send messages to peers.
|
||||
* It automatically dispatches the events or packets it receives. This class
|
||||
* also stores the public address when known and the player login.
|
||||
* Here are defined some functions that will be specifically implemented by
|
||||
* the ServerNetworkManager and the ClientNetworkManager.
|
||||
*/
|
||||
class NetworkManager : public Singleton<NetworkManager>
|
||||
{
|
||||
friend class Singleton<NetworkManager>;
|
||||
public:
|
||||
/** \brief Function to start the Network Manager (start threads) */
|
||||
virtual void run();
|
||||
/** \brief Function to reset the Network Manager.
|
||||
* This function resets the peers and the listening host.
|
||||
*/
|
||||
virtual void reset();
|
||||
/** \brief Function that aborts the NetworkManager.
|
||||
* This function will stop the listening, delete the host and stop
|
||||
* threads that are related to networking.
|
||||
*/
|
||||
virtual void abort();
|
||||
|
||||
// network management functions
|
||||
/** \brief Try to establish a connection to a given transport address.
|
||||
* \param peer : The transport address which you want to connect to.
|
||||
* \return True if we're successfully connected. False elseway.
|
||||
*/
|
||||
virtual bool connect(TransportAddress peer);
|
||||
/** \brief Changes the socket working mode.
|
||||
* Sockets can be in two modes : The ENet mode and a mode we will call
|
||||
* the 'Raw' mode. In the ENet mode, the socket will be read as
|
||||
* \param peer : The transport address which you want to connect to.
|
||||
* \return True if we're successfully connected. False elseway.
|
||||
*/
|
||||
virtual void setManualSocketsMode(bool manual);
|
||||
|
||||
// message/packets related functions
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void sendPacket(const NetworkString& data, bool reliable = true) = 0;
|
||||
virtual void sendPacket(STKPeer* peer, const NetworkString& data, bool reliable = true);
|
||||
virtual void sendPacketExcept(STKPeer* peer, const NetworkString& data, bool reliable = true);
|
||||
virtual void sendPacket(const NetworkString& data,
|
||||
bool reliable = true) = 0;
|
||||
virtual void sendPacket(STKPeer* peer,
|
||||
const NetworkString& data,
|
||||
bool reliable = true);
|
||||
virtual void sendPacketExcept(STKPeer* peer,
|
||||
const NetworkString& data,
|
||||
bool reliable = true);
|
||||
|
||||
// Game related functions
|
||||
virtual GameSetup* setupNewGame(); //!< Creates a new game setup and returns it
|
||||
|
@ -1,3 +1,25 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// 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.
|
||||
|
||||
/*! \file network_string.hpp
|
||||
* \brief Defines functions to easily manipulate 8-bit network destinated strings.
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_STRING_HPP
|
||||
#define NETWORK_STRING_HPP
|
||||
|
||||
@ -10,6 +32,10 @@
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
/** \class NetworkString
|
||||
* \brief Describes a chain of 8-bit unsigned integers.
|
||||
* This class allows you to easily create and parse 8-bit strings.
|
||||
*/
|
||||
class NetworkString
|
||||
{
|
||||
union {
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "network/network_world.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/synchronization_protocol.hpp"
|
||||
#include "network/protocols/controller_events_protocol.hpp"
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
#include "modes/world.hpp"
|
||||
|
||||
#include "karts/controller/controller.hpp"
|
||||
@ -10,6 +12,7 @@
|
||||
NetworkWorld::NetworkWorld()
|
||||
{
|
||||
m_running = false;
|
||||
m_has_run = false;
|
||||
}
|
||||
|
||||
NetworkWorld::~NetworkWorld()
|
||||
@ -18,6 +21,8 @@ NetworkWorld::~NetworkWorld()
|
||||
|
||||
void NetworkWorld::update(float dt)
|
||||
{
|
||||
if (!m_has_run)
|
||||
m_has_run = true;
|
||||
SynchronizationProtocol* protocol = static_cast<SynchronizationProtocol*>(
|
||||
ProtocolManager::getInstance()->getProtocol(PROTOCOL_SYNCHRONIZATION));
|
||||
if (protocol) // if this protocol exists, that's that we play online
|
||||
@ -27,8 +32,40 @@ void NetworkWorld::update(float dt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
World::getWorld()->setNetworkWorld(true);
|
||||
}
|
||||
World::getWorld()->updateWorld(dt);
|
||||
if (World::getWorld()->getPhase() >= WorldStatus::RESULT_DISPLAY_PHASE) // means it's the end
|
||||
{
|
||||
// consider the world finished.
|
||||
stop();
|
||||
Log::info("NetworkWorld", "The game is considered finish.");
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkWorld::start()
|
||||
{
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
void NetworkWorld::stop()
|
||||
{
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
bool NetworkWorld::isRaceOver()
|
||||
{
|
||||
if (!World::getWorld())
|
||||
return false;
|
||||
return (World::getWorld()->getPhase() > WorldStatus::RACE_PHASE);
|
||||
}
|
||||
|
||||
void NetworkWorld::collectedItem(Item *item, AbstractKart *kart)
|
||||
{
|
||||
assert(NetworkManager::getInstance()->isServer()); // this is only called in the server
|
||||
GameEventsProtocol* protocol = static_cast<GameEventsProtocol*>(
|
||||
ProtocolManager::getInstance()->getProtocol(PROTOCOL_GAME_EVENTS));
|
||||
protocol->collectedItem(item,kart);
|
||||
}
|
||||
|
||||
void NetworkWorld::controllerAction(Controller* controller, PlayerAction action, int value)
|
||||
@ -38,3 +75,4 @@ void NetworkWorld::controllerAction(Controller* controller, PlayerAction action,
|
||||
if (protocol)
|
||||
protocol->controllerAction(controller, action, value);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,24 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// 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.
|
||||
|
||||
/*! \file network_world.hpp
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_WORLD_HPP
|
||||
#define NETWORK_WORLD_HPP
|
||||
|
||||
@ -8,6 +29,7 @@
|
||||
class Controller;
|
||||
class KartUpdateProtocol;
|
||||
class AbstractKart;
|
||||
class Item;
|
||||
|
||||
/*! \brief Manages the world updates during an online game
|
||||
* This function's update is to be called instead of the normal World update
|
||||
@ -18,16 +40,19 @@ class NetworkWorld : public Singleton<NetworkWorld>
|
||||
public:
|
||||
void update(float dt);
|
||||
|
||||
void start() { m_running = true; }
|
||||
void stop() { m_running = false; }
|
||||
void start();
|
||||
void stop();
|
||||
bool isRunning() { return m_running; }
|
||||
bool isRaceOver();
|
||||
|
||||
void collectedItem(Item *item, AbstractKart *kart);
|
||||
void controllerAction(Controller* controller, PlayerAction action, int value);
|
||||
|
||||
std::string m_self_kart;
|
||||
protected:
|
||||
bool m_running;
|
||||
float m_race_time;
|
||||
bool m_has_run;
|
||||
|
||||
private:
|
||||
NetworkWorld();
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
|
||||
Protocol::Protocol(CallbackObject* callback_object, PROTOCOL_TYPE type)
|
||||
{
|
||||
@ -52,3 +53,47 @@ PROTOCOL_TYPE Protocol::getProtocolType()
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
bool Protocol::checkDataSizeAndToken(Event* event, int minimum_size)
|
||||
{
|
||||
NetworkString data = event->data();
|
||||
if (data.size() < minimum_size || data[0] != 4)
|
||||
{
|
||||
Log::warn("Protocol", "Receiving a badly "
|
||||
"formated message. Size is %d and first byte %d",
|
||||
data.size(), data[0]);
|
||||
return false;
|
||||
}
|
||||
STKPeer* peer = *(event->peer);
|
||||
uint32_t token = data.gui32(1);
|
||||
if (token != peer->getClientServerToken())
|
||||
{
|
||||
Log::warn("Protocol", "Peer sending bad token. Request "
|
||||
"aborted.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Protocol::isByteCorrect(Event* event, int byte_nb, int value)
|
||||
{
|
||||
NetworkString data = event->data();
|
||||
if (data[byte_nb] != value)
|
||||
{
|
||||
Log::info("Protocol", "Bad byte at pos %d. %d "
|
||||
"should be %d", byte_nb, data[byte_nb], value);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Protocol::sendMessageToPeersChangingToken(NetworkString prefix, NetworkString message)
|
||||
{
|
||||
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
prefix.ai8(4).ai32(peers[i]->getClientServerToken());
|
||||
prefix += message;
|
||||
m_listener->sendMessage(this, peers[i], prefix);
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,10 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file protocol.hpp
|
||||
* \brief Generic protocols declarations.
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOL_HPP
|
||||
#define PROTOCOL_HPP
|
||||
|
||||
@ -61,55 +65,60 @@ 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();
|
||||
|
||||
/// functions to check incoming data easily
|
||||
bool checkDataSizeAndToken(Event* event, int minimum_size);
|
||||
bool isByteCorrect(Event* event, int byte_nb, int value);
|
||||
void sendMessageToPeersChangingToken(NetworkString prefix, NetworkString message);
|
||||
|
||||
|
||||
protected:
|
||||
ProtocolManager* m_listener; //!< The protocol listener
|
||||
PROTOCOL_TYPE m_type; //!< The type of the protocol
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "network/protocol.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstdlib>
|
||||
@ -31,21 +31,23 @@
|
||||
void* protocolManagerUpdate(void* data)
|
||||
{
|
||||
ProtocolManager* manager = static_cast<ProtocolManager*>(data);
|
||||
while(!manager->exit())
|
||||
while(manager && !manager->exit())
|
||||
{
|
||||
manager->update();
|
||||
irr_driver->getDevice()->sleep(20);
|
||||
StkTime::sleep(2);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void* protocolManagerAsynchronousUpdate(void* data)
|
||||
{
|
||||
ProtocolManager* manager = static_cast<ProtocolManager*>(data);
|
||||
while(!manager->exit())
|
||||
manager->m_asynchronous_thread_running = true;
|
||||
while(manager && !manager->exit())
|
||||
{
|
||||
manager->asynchronousUpdate();
|
||||
irr_driver->getDevice()->sleep(20);
|
||||
StkTime::sleep(2);
|
||||
}
|
||||
manager->m_asynchronous_thread_running = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -73,8 +75,14 @@ ProtocolManager::ProtocolManager()
|
||||
}
|
||||
|
||||
ProtocolManager::~ProtocolManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ProtocolManager::abort()
|
||||
{
|
||||
pthread_mutex_unlock(&m_exit_mutex); // will stop the update function
|
||||
pthread_join(*m_asynchronous_update_thread, NULL); // wait the thread to finish
|
||||
pthread_mutex_lock(&m_events_mutex);
|
||||
pthread_mutex_lock(&m_protocols_mutex);
|
||||
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
|
||||
@ -83,7 +91,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 +113,50 @@ 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.arrival_time = StkTime::getTimeSinceEpoch();
|
||||
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 for %d that has no destination protocol.", searchedProtocol);
|
||||
pthread_mutex_unlock(&m_events_mutex);
|
||||
}
|
||||
|
||||
@ -274,36 +325,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 || (StkTime::getTimeSinceEpoch()-event->arrival_time) >= TIME_TO_KEEP_EVENTS)
|
||||
{
|
||||
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 +382,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);
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define TIME_TO_KEEP_EVENTS 1.0
|
||||
|
||||
/*!
|
||||
* \enum PROTOCOL_STATE
|
||||
* \brief Defines the three states that a protocol can have.
|
||||
@ -78,6 +80,16 @@ 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;
|
||||
double arrival_time;
|
||||
std::vector<int> protocols_ids;
|
||||
} EventProcessingInfo;
|
||||
|
||||
/*!
|
||||
* \class ProtocolManager
|
||||
* \brief Manages the protocols at runtime.
|
||||
@ -93,8 +105,11 @@ typedef struct ProtocolRequest
|
||||
class ProtocolManager : public Singleton<ProtocolManager>
|
||||
{
|
||||
friend class Singleton<ProtocolManager>;
|
||||
|
||||
friend void* protocolManagerAsynchronousUpdate(void* data);
|
||||
public:
|
||||
|
||||
/*! \brief Stops the protocol manager. */
|
||||
virtual void abort();
|
||||
/*!
|
||||
* \brief Function that processes incoming events.
|
||||
* This function is called by the network manager each time there is an
|
||||
@ -269,7 +284,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 +296,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.
|
||||
*/
|
||||
@ -311,6 +326,8 @@ class ProtocolManager : public Singleton<ProtocolManager>
|
||||
pthread_t* m_update_thread;
|
||||
/*! Asynchronous update thread.*/
|
||||
pthread_t* m_asynchronous_update_thread;
|
||||
/*! True if the thread is running. */
|
||||
bool m_asynchronous_thread_running;
|
||||
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,9 @@
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/protocols/start_game_protocol.hpp"
|
||||
#include "network/network_world.hpp"
|
||||
|
||||
#include "modes/world_with_rank.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/network_kart_selection.hpp"
|
||||
@ -43,6 +46,7 @@ ClientLobbyRoomProtocol::~ClientLobbyRoomProtocol()
|
||||
void ClientLobbyRoomProtocol::setup()
|
||||
{
|
||||
m_setup = NetworkManager::getInstance()->setupNewGame(); // create a new setup
|
||||
m_setup->getRaceConfig()->setPlayerCount(16); //FIXME : this has to be changed when logging into the server
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
@ -53,7 +57,67 @@ void ClientLobbyRoomProtocol::requestKartSelection(std::string kart_name)
|
||||
NetworkString request;
|
||||
// 0x02 : kart selection request, size_token (4), token, size kart name, kart name
|
||||
request.ai8(0x02).ai8(4).ai32(m_server->getClientServerToken()).ai8(kart_name.size()).as(kart_name);
|
||||
m_listener->sendMessage(this, request);
|
||||
m_listener->sendMessage(this, request, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteMajor(uint8_t major)
|
||||
{
|
||||
NetworkString request;
|
||||
// 0xc0 : major vote, size_token (4), token, size major(1),major
|
||||
request.ai8(0xc0).ai8(4).ai32(m_server->getClientServerToken()).ai8(1).ai8(major);
|
||||
m_listener->sendMessage(this, request, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteRaceCount(uint8_t count)
|
||||
{
|
||||
NetworkString request;
|
||||
// 0xc0 : race count vote, size_token (4), token, size race count(1), count
|
||||
request.ai8(0xc1).ai8(4).ai32(m_server->getClientServerToken()).ai8(1).ai8(count);
|
||||
m_listener->sendMessage(this, request, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteMinor(uint8_t minor)
|
||||
{
|
||||
NetworkString request;
|
||||
// 0xc0 : minor vote, size_token (4), token, size minor(1),minor
|
||||
request.ai8(0xc2).ai8(4).ai32(m_server->getClientServerToken()).ai8(1).ai8(minor);
|
||||
m_listener->sendMessage(this, request, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteTrack(std::string track, uint8_t track_nb)
|
||||
{
|
||||
NetworkString request;
|
||||
// 0xc0 : major vote, size_token (4), token, size track, track, size #track, #track
|
||||
request.ai8(0xc3).ai8(4).ai32(m_server->getClientServerToken()).ai8(track.size()).as(track).ai8(1).ai8(track_nb);
|
||||
m_listener->sendMessage(this, request, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteReversed(bool reversed, uint8_t track_nb)
|
||||
{
|
||||
NetworkString request;
|
||||
// 0xc0 : major vote, size_token (4), token, size reversed(1),reversed, size #track, #track
|
||||
request.ai8(0xc4).ai8(4).ai32(m_server->getClientServerToken()).ai8(1).ai8(reversed).ai8(1).ai8(track_nb);
|
||||
m_listener->sendMessage(this, request, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteLaps(uint8_t laps, uint8_t track_nb)
|
||||
{
|
||||
NetworkString request;
|
||||
// 0xc0 : major vote, size_token (4), token, size laps(1),laps, size #track, #track
|
||||
request.ai8(0xc5).ai8(4).ai32(m_server->getClientServerToken()).ai8(1).ai8(laps).ai8(1).ai8(track_nb);
|
||||
m_listener->sendMessage(this, request, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -67,21 +131,50 @@ void ClientLobbyRoomProtocol::leave()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::notifyEvent(Event* event)
|
||||
bool ClientLobbyRoomProtocol::notifyEvent(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];
|
||||
if (message_type != 0x03 &&
|
||||
message_type != 0x06)
|
||||
return false; // don't treat the event
|
||||
|
||||
Log::info("ClientLobbyRoomProtocol", "Message of type %d", message_type);
|
||||
event->removeFront(1);
|
||||
Log::info("ClientLobbyRoomProtocol", "Synchronous message of type %d", message_type);
|
||||
if (message_type == 0x03) // kart selection update
|
||||
kartSelectionUpdate(event);
|
||||
else if (message_type == 0x06) // end of race
|
||||
raceFinished(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool ClientLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
|
||||
{
|
||||
assert(m_setup); // assert that the setup exists
|
||||
if (event->type == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
NetworkString data = event->data();
|
||||
assert(data.size()); // assert that data isn't empty
|
||||
uint8_t message_type = data[0];
|
||||
if (message_type == 0x03 ||
|
||||
message_type == 0x06)
|
||||
return false; // don't treat the event
|
||||
|
||||
event->removeFront(1);
|
||||
Log::info("ClientLobbyRoomProtocol", "Asynchronous message of type %d", message_type);
|
||||
if (message_type == 0x01) // new player connected
|
||||
newPlayer(event);
|
||||
else if (message_type == 0x02) // player disconnected
|
||||
disconnectedPlayer(event);
|
||||
else if (message_type == 0x03) // kart selection update
|
||||
kartSelectionUpdate(event);
|
||||
else if (message_type == 0x04) // start race
|
||||
startGame(event);
|
||||
else if (message_type == 0x05) // start selection phase
|
||||
@ -92,10 +185,24 @@ void ClientLobbyRoomProtocol::notifyEvent(Event* event)
|
||||
connectionAccepted(event);
|
||||
else if (message_type == 0x82) // kart selection refused
|
||||
kartSelectionRefused(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);
|
||||
|
||||
return true;
|
||||
} // message
|
||||
else if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
return true;
|
||||
} // connection
|
||||
else if (event->type == EVENT_TYPE_DISCONNECTED) // means we left essentially
|
||||
{
|
||||
@ -105,7 +212,9 @@ void ClientLobbyRoomProtocol::notifyEvent(Event* event)
|
||||
m_listener->requestTerminate(this);
|
||||
NetworkManager::getInstance()->reset();
|
||||
NetworkManager::getInstance()->removePeer(*event->peer); // prolly the same as m_server
|
||||
return true;
|
||||
} // disconnection
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -127,7 +236,8 @@ void ClientLobbyRoomProtocol::update()
|
||||
ns.ai8(1).ai8(4).ai32(Online::CurrentUser::get()->getID());
|
||||
m_listener->sendMessage(this, ns);
|
||||
m_state = REQUESTING_CONNECTION;
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
case REQUESTING_CONNECTION:
|
||||
break;
|
||||
case CONNECTED:
|
||||
@ -137,10 +247,20 @@ void ClientLobbyRoomProtocol::update()
|
||||
NetworkKartSelectionScreen* screen = NetworkKartSelectionScreen::getInstance();
|
||||
StateManager::get()->pushScreen(screen);
|
||||
m_state = SELECTING_KARTS;
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
case SELECTING_KARTS:
|
||||
break;
|
||||
case PLAYING:
|
||||
{
|
||||
if (NetworkWorld::getInstance<NetworkWorld>()->isRaceOver()) // race is now over, kill race protocols and return to connected state
|
||||
{
|
||||
Log::info("ClientLobbyRoomProtocol", "Game finished.");
|
||||
m_state = RACE_FINISHED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RACE_FINISHED:
|
||||
break;
|
||||
case DONE:
|
||||
m_state = EXITING;
|
||||
@ -165,14 +285,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()->getID())
|
||||
{
|
||||
@ -207,12 +328,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.");
|
||||
@ -237,14 +359,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()->getID())
|
||||
{
|
||||
Log::info("ClientLobbyRoomProtocol", "The server accepted the connection.");
|
||||
@ -252,15 +375,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()->getProfile();
|
||||
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");
|
||||
@ -268,17 +391,19 @@ 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::Profile* new_user = new Online::Profile(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
|
||||
@ -303,13 +428,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.");
|
||||
@ -337,13 +463,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.");
|
||||
@ -371,24 +498,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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -405,13 +534,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.");
|
||||
"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;
|
||||
@ -437,13 +567,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.");
|
||||
"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;
|
||||
@ -455,3 +586,221 @@ void ClientLobbyRoomProtocol::startSelection(Event* event)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when all karts have finished the 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 | token | 1 | Kart 1 ID | 1 | kart id 2 | ... |
|
||||
* ---------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::raceFinished(Event* event)
|
||||
{
|
||||
if (event->data().size() < 5)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Not enough data provided.");
|
||||
return;
|
||||
}
|
||||
NetworkString data = event->data();
|
||||
if ((*event->peer)->getClientServerToken() != data.gui32(1))
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad token");
|
||||
return;
|
||||
}
|
||||
data.removeFront(5);
|
||||
Log::error("ClientLobbyRoomProtocol", "Server notified that the race is finished.");
|
||||
|
||||
// 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.");
|
||||
|
||||
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.");
|
||||
|
||||
// finish the race
|
||||
WorldWithRank* ranked_world = (WorldWithRank*)(World::getWorld());
|
||||
ranked_world->beginSetKartPositions();
|
||||
ranked_world->setPhase(WorldStatus::RESULT_DISPLAY_PHASE);
|
||||
int position = 1;
|
||||
while(data.size()>0)
|
||||
{
|
||||
if (data.size() < 2)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Incomplete field.");
|
||||
return;
|
||||
}
|
||||
if (data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Badly formatted field.");
|
||||
return;
|
||||
}
|
||||
uint8_t kart_id = data[1];
|
||||
ranked_world->setKartPosition(kart_id,position);
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart %d has finished #%d", kart_id, position);
|
||||
data.removeFront(2);
|
||||
position++;
|
||||
}
|
||||
ranked_world->endSetKartPositions();
|
||||
m_state = RACE_FINISHED;
|
||||
ranked_world->terminateRace();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \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 | player id | 1 | major mode vote |
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerMajorVote(Event* event)
|
||||
{
|
||||
NetworkString data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerMajorVote(data[6], data[8]);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \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 8 9
|
||||
* ----------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | 1 | races count |
|
||||
* ----------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerRaceCountVote(Event* event)
|
||||
{
|
||||
NetworkString data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerRaceCountVote(data[6], data[8]);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \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 8 9
|
||||
* --------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | 1 | minor mode vote |
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerMinorVote(Event* event)
|
||||
{
|
||||
NetworkString data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerMinorVote(data[6], data[8]);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when a player votes for a track.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 N+8 N+9 N+10
|
||||
* ---------------------------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | N | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | N | track name | 1 | track number (gp) |
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerTrackVote(Event* event)
|
||||
{
|
||||
NetworkString data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 10))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
int N = data[7];
|
||||
std::string track_name = data.gs(8, N);
|
||||
if (!isByteCorrect(event, N+8, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerTrackVote(data[6], track_name, data[N+9]);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \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 10 11
|
||||
* -------------------------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | 1 | reversed | 1 | track number (gp) |
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerReversedVote(Event* event)
|
||||
{
|
||||
NetworkString data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 11))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 9, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerReversedVote(data[6], data[8]!=0, data[10]);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \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 10 11
|
||||
* ---------------------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | 1 | laps | 1 | track number (gp) |
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerLapsVote(Event* event)
|
||||
{
|
||||
NetworkString data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerLapsVote(data[6], data[8], data[10]);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -10,10 +10,17 @@ class ClientLobbyRoomProtocol : public LobbyRoomProtocol
|
||||
virtual ~ClientLobbyRoomProtocol();
|
||||
|
||||
void requestKartSelection(std::string kart_name);
|
||||
void voteMajor(uint8_t major);
|
||||
void voteRaceCount(uint8_t count);
|
||||
void voteMinor(uint8_t minor);
|
||||
void voteTrack(std::string track, uint8_t track_nb = 0);
|
||||
void voteReversed(bool reversed, uint8_t track_nb = 0);
|
||||
void voteLaps(uint8_t laps, uint8_t track_nb = 0);
|
||||
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() {}
|
||||
@ -27,6 +34,14 @@ class ClientLobbyRoomProtocol : public LobbyRoomProtocol
|
||||
void kartSelectionUpdate(Event* event);
|
||||
void startGame(Event* event);
|
||||
void startSelection(Event* event);
|
||||
void raceFinished(Event* event);
|
||||
// race votes
|
||||
void playerMajorVote(Event* event);
|
||||
void playerRaceCountVote(Event* event);
|
||||
void playerMinorVote(Event* event);
|
||||
void playerTrackVote(Event* event);
|
||||
void playerReversedVote(Event* event);
|
||||
void playerLapsVote(Event* event);
|
||||
|
||||
TransportAddress m_server_address;
|
||||
STKPeer* m_server;
|
||||
@ -40,6 +55,7 @@ class ClientLobbyRoomProtocol : public LobbyRoomProtocol
|
||||
KART_SELECTION,
|
||||
SELECTING_KARTS, // in the network kart selection screen
|
||||
PLAYING,
|
||||
RACE_FINISHED,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -85,8 +86,28 @@ void ConnectToPeer::asynchronousUpdate()
|
||||
{
|
||||
if (m_peer_address.ip != 0 && m_peer_address.port != 0)
|
||||
{
|
||||
// we're in the same lan (same public ip address) !!
|
||||
if (m_peer_address.ip == NetworkManager::getInstance()->getPublicAddress().ip)
|
||||
{
|
||||
// just send a broadcast packet with the string aloha_stk inside, the client will know our ip address and will connect
|
||||
STKHost* host = NetworkManager::getInstance()->getHost();
|
||||
TransportAddress broadcast_address;
|
||||
broadcast_address.ip = -1; // 255.255.255.255
|
||||
broadcast_address.port = m_peer_address.port; // 0b10101100000101101101111111111111; // for test
|
||||
char data[] = "aloha_stk\0";
|
||||
host->sendRawPacket((uint8_t*)(data), 10, broadcast_address);
|
||||
Log::info("ConnectToPeer", "Broadcast aloha sent.");
|
||||
StkTime::sleep(1);
|
||||
broadcast_address.ip = 0x7f000001; // 127.0.0.1 (localhost)
|
||||
broadcast_address.port = m_peer_address.port;
|
||||
host->sendRawPacket((uint8_t*)(data), 10, broadcast_address);
|
||||
Log::info("ConnectToPeer", "Broadcast aloha to self.");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_peer_address, 2.0));
|
||||
}
|
||||
m_state = CONNECTING;
|
||||
m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_peer_address, 2.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -96,9 +117,12 @@ void ConnectToPeer::asynchronousUpdate()
|
||||
}
|
||||
break;
|
||||
case CONNECTING: // waiting the peer to connect
|
||||
break;
|
||||
case CONNECTED:
|
||||
{
|
||||
m_listener->requestTerminate( m_listener->getProtocol(m_current_protocol_id)); // kill the ping protocol because we're connected
|
||||
// the ping protocol is there for NAT traversal (disabled when connecting to LAN peer)
|
||||
if (m_peer_address != NetworkManager::getInstance()->getPublicAddress())
|
||||
m_listener->requestTerminate( m_listener->getProtocol(m_current_protocol_id)); // kill the ping protocol because we're connected
|
||||
m_state = DONE;
|
||||
break;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -31,6 +31,12 @@
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
# include <iphlpapi.h>
|
||||
#else
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToServer::ConnectToServer() :
|
||||
@ -60,7 +66,7 @@ ConnectToServer::~ConnectToServer()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToServer::notifyEvent(Event* event)
|
||||
bool ConnectToServer::notifyEventAsynchronous(Event* event)
|
||||
{
|
||||
if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
@ -68,6 +74,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;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -132,9 +139,11 @@ void ConnectToServer::asynchronousUpdate()
|
||||
if (m_listener->getProtocolState(m_current_protocol_id)
|
||||
== PROTOCOL_STATE_TERMINATED) // we know the server address
|
||||
{
|
||||
Log::info("ConnectToServer", "Server's address known");
|
||||
if (m_server_address.ip == m_public_address.ip) // we're in the same lan (same public ip address) !!
|
||||
Log::info("ConnectToServer", "Server appears to be in the same LAN.");
|
||||
m_state = REQUESTING_CONNECTION;
|
||||
m_current_protocol_id = m_listener->requestStart(new RequestConnection(m_server_id));
|
||||
Log::info("ConnectToServer", "Server's address known");
|
||||
}
|
||||
break;
|
||||
case REQUESTING_CONNECTION:
|
||||
@ -145,11 +154,90 @@ void ConnectToServer::asynchronousUpdate()
|
||||
if (m_server_address.ip == 0 || m_server_address.port == 0)
|
||||
{ // server data not correct, hide address and stop
|
||||
m_state = HIDING_ADDRESS;
|
||||
Log::error("ConnectToServer", "Server address is "ADDRESS_FORMAT, ADDRESS_ARGS(m_server_address.ip, m_server_address.port));
|
||||
m_current_protocol_id = m_listener->requestStart(new HidePublicAddress());
|
||||
return;
|
||||
}
|
||||
m_state = CONNECTING;
|
||||
m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_server_address, 2.0));
|
||||
if (m_server_address.ip == m_public_address.ip) // we're in the same lan (same public ip address) !!
|
||||
{
|
||||
// just send a broadcast packet, the client will know our ip address and will connect
|
||||
STKHost* host = NetworkManager::getInstance()->getHost();
|
||||
host->stopListening(); // stop the listening
|
||||
TransportAddress sender;
|
||||
|
||||
TransportAddress broadcast_address;
|
||||
broadcast_address.ip = -1; // 255.255.255.255
|
||||
broadcast_address.port = 7321; // 0b10101100000101101101111111111111; // for test
|
||||
char data2[] = "aloha_stk\0";
|
||||
host->sendRawPacket((uint8_t*)(data2), 10, broadcast_address);
|
||||
|
||||
Log::info("ConnectToServer", "Waiting broadcast message.");
|
||||
const uint8_t* received_data = host->receiveRawPacket(&sender); // get the sender
|
||||
|
||||
host->startListening(); // start listening again
|
||||
const char data[] = "aloha_stk\0";
|
||||
if (strcmp(data, (char*)(received_data)) == 0)
|
||||
{
|
||||
Log::info("ConnectToServer", "LAN Server found : %u:%u", sender.ip, sender.port);
|
||||
#ifndef WIN32
|
||||
// just check if the ip is ours : if so, then just use localhost (127.0.0.1)
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
struct sockaddr_in *sa;
|
||||
getifaddrs (&ifap); // get the info
|
||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family==AF_INET)
|
||||
{
|
||||
sa = (struct sockaddr_in *) ifa->ifa_addr;
|
||||
if (ntohl(sa->sin_addr.s_addr) == sender.ip) // this interface is ours
|
||||
sender.ip = 0x7f000001; // 127.0.0.1
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifap);
|
||||
#else
|
||||
// Query the list of all IP addresses on the local host
|
||||
// First call to GetIpAddrTable with 0 bytes buffer
|
||||
// will return insufficient buffer error, and size
|
||||
// will contain the number of bytes needed for all
|
||||
// data. Repeat the process of querying the size
|
||||
// using GetIpAddrTable in a while loop since it
|
||||
// can happen that an interface comes online between
|
||||
// the previous call to GetIpAddrTable and the next
|
||||
// call.
|
||||
MIB_IPADDRTABLE *table = NULL;
|
||||
unsigned long size = 0;
|
||||
int error = GetIpAddrTable(table, &size, 0);
|
||||
// Also add a count to limit the while loop - in
|
||||
// case that something strange is going on.
|
||||
int count = 0;
|
||||
while(error==ERROR_INSUFFICIENT_BUFFER && count < 10)
|
||||
{
|
||||
delete table; // deleting NULL is legal
|
||||
table = (MIB_IPADDRTABLE*)new char[size];
|
||||
error = GetIpAddrTable(table, &size, 0);
|
||||
count ++;
|
||||
} // while insufficient buffer
|
||||
for(unsigned int i=0; i<table->dwNumEntries; i++)
|
||||
{
|
||||
int ip = ntohl(table->table[i].dwAddr);
|
||||
if(sender.ip == ip) // this interface is ours
|
||||
{
|
||||
sender.ip = 0x7f000001; // 127.0.0.1
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete table;
|
||||
|
||||
#endif
|
||||
m_server_address = sender;
|
||||
m_state = CONNECTING;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = CONNECTING;
|
||||
m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_server_address, 2.0));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONNECTING: // waiting the server to answer our connection
|
||||
@ -159,7 +247,7 @@ void ConnectToServer::asynchronousUpdate()
|
||||
{
|
||||
timer = StkTime::getRealTime();
|
||||
NetworkManager::getInstance()->connect(m_server_address);
|
||||
Log::info("ConnectToServer", "Trying to connect");
|
||||
Log::info("ConnectToServer", "Trying to connect to %u:%u", m_server_address.ip, m_server_address.port);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -184,6 +272,9 @@ void ConnectToServer::asynchronousUpdate()
|
||||
break;
|
||||
case DONE:
|
||||
m_listener->requestTerminate(this);
|
||||
m_state = EXITING;
|
||||
break;
|
||||
case EXITING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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,30 +61,31 @@ 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();
|
||||
|
||||
ns.removeFront(4);
|
||||
uint8_t client_index = -1;
|
||||
while (ns.size() >= 9)
|
||||
{
|
||||
uint8_t controller_index = ns.gui8();
|
||||
client_index = controller_index;
|
||||
uint8_t serialized_1 = ns.gui8(1), serialized_2 = ns.gui8(2), serialized_3 = ns.gui8(3);
|
||||
uint8_t serialized_1 = ns.gui8(1);
|
||||
PlayerAction action = (PlayerAction)(ns.gui8(4));
|
||||
int action_value = ns.gui32(5);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -162,6 +164,7 @@ void ControllerEventsProtocol::controllerAction(Controller* controller,
|
||||
ns.ai8(serialized_1).ai8(serialized_2).ai8(serialized_3);
|
||||
ns.ai8((uint8_t)(action)).ai32(value);
|
||||
|
||||
Log::info("ControllerEventsProtocol", "Action %d value %d", action, value);
|
||||
m_listener->sendMessage(this, ns, false); // send message to server
|
||||
}
|
||||
|
||||
|
@ -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() {}
|
||||
|
||||
|
@ -1,5 +1,13 @@
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/item.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "items/powerup.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
|
||||
GameEventsProtocol::GameEventsProtocol() : Protocol(NULL, PROTOCOL_GAME_EVENTS)
|
||||
{
|
||||
}
|
||||
@ -8,8 +16,49 @@ GameEventsProtocol::~GameEventsProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void GameEventsProtocol::notifyEvent(Event* event)
|
||||
bool GameEventsProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->type != EVENT_TYPE_MESSAGE)
|
||||
return true;
|
||||
NetworkString data = event->data();
|
||||
if (data.size() < 5) // for token and type
|
||||
{
|
||||
Log::warn("GameEventsProtocol", "Too short message.");
|
||||
return true;
|
||||
}
|
||||
if ( (*event->peer)->getClientServerToken() != data.gui32())
|
||||
{
|
||||
Log::warn("GameEventsProtocol", "Bad token.");
|
||||
return true;
|
||||
}
|
||||
int8_t type = data.gui8(4);
|
||||
data.removeFront(5);
|
||||
switch (type)
|
||||
{
|
||||
case 0x01: // item picked
|
||||
{
|
||||
if (data.size() < 6)
|
||||
{
|
||||
Log::warn("GameEventsProtocol", "Too short message.");
|
||||
return true;
|
||||
}
|
||||
uint32_t item_id = data.gui32();
|
||||
uint8_t powerup_type = data.gui8(4);
|
||||
uint8_t kart_race_id = data.gui8(5);
|
||||
// now set the kart powerup
|
||||
AbstractKart* kart = World::getWorld()->getKart(
|
||||
NetworkManager::getInstance()->getGameSetup()->getProfile(kart_race_id)->world_kart_id);
|
||||
ItemManager::get()->collectedItem(
|
||||
ItemManager::get()->getItem(item_id),
|
||||
kart,
|
||||
powerup_type);
|
||||
Log::info("GameEventsProtocol", "Item %d picked by a player.", powerup_type);
|
||||
} break;
|
||||
default:
|
||||
Log::warn("GameEventsProtocol", "Unkown message type.");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameEventsProtocol::setup()
|
||||
@ -19,3 +68,27 @@ void GameEventsProtocol::setup()
|
||||
void GameEventsProtocol::update()
|
||||
{
|
||||
}
|
||||
|
||||
void GameEventsProtocol::collectedItem(Item* item, AbstractKart* kart)
|
||||
{
|
||||
GameSetup* setup = NetworkManager::getInstance()->getGameSetup();
|
||||
assert(setup);
|
||||
const NetworkPlayerProfile* player_profile = setup->getProfile(kart->getIdent()); // use kart name
|
||||
|
||||
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ns;
|
||||
ns.ai32(peers[i]->getClientServerToken());
|
||||
// 0x01 : item picked : send item id, powerup type and kart race id
|
||||
uint8_t powerup = 0;
|
||||
if (item->getType() == Item::ITEM_BANANA)
|
||||
powerup = (int)(kart->getAttachment()->getType());
|
||||
else if (item->getType() == Item::ITEM_BONUS_BOX)
|
||||
powerup = (((int)(kart->getPowerup()->getType()) << 4)&0xf0) + (kart->getPowerup()->getNum()&0x0f);
|
||||
|
||||
ns.ai8(0x01).ai32(item->getItemId()).ai8(powerup).ai8(player_profile->race_id); // send item,
|
||||
m_listener->sendMessage(this, peers[i], ns, true); // reliable
|
||||
Log::info("GameEventsProtocol", "Notified a peer that a kart collected item %d.", (int)(kart->getPowerup()->getType()));
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
class AbstractKart;
|
||||
class Item;
|
||||
|
||||
class GameEventsProtocol : public Protocol
|
||||
{
|
||||
@ -10,11 +12,14 @@ class GameEventsProtocol : public Protocol
|
||||
GameEventsProtocol();
|
||||
virtual ~GameEventsProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual bool notifyEvent(Event* event);
|
||||
virtual bool notifyEventAsynchronous(Event* event) { return false; }
|
||||
virtual void setup();
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {}
|
||||
|
||||
void collectedItem(Item* item, AbstractKart* kart);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "network/protocols/get_peer_address.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/http_functions.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
@ -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;
|
||||
@ -70,7 +65,10 @@ void GetPeerAddress::asynchronousUpdate()
|
||||
{
|
||||
TransportAddress* addr = static_cast<TransportAddress*>(m_callback_object);
|
||||
result->get("ip", &addr->ip);
|
||||
result->get("port", &addr->port);
|
||||
if (addr->ip == NetworkManager::getInstance()->getPublicAddress().ip)
|
||||
result->get("private_port", &addr->port);
|
||||
else
|
||||
result->get("port", &addr->port);
|
||||
Log::debug("GetPeerAddress", "Address gotten successfully.");
|
||||
}
|
||||
else
|
||||
|
@ -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();
|
||||
|
@ -18,14 +18,23 @@
|
||||
|
||||
#include "network/protocols/get_public_address.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "network/network_interface.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/random_generator.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#ifdef WIN32
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
#else
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
int stunRand()
|
||||
{
|
||||
@ -46,11 +55,6 @@ GetPublicAddress::~GetPublicAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void GetPublicAddress::notifyEvent(Event* event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GetPublicAddress::setup()
|
||||
{
|
||||
m_state = NOTHING_DONE;
|
||||
@ -97,16 +101,49 @@ void GetPublicAddress::asynchronousUpdate()
|
||||
bytes[19] = (uint8_t)(m_stun_tansaction_id[2]);
|
||||
bytes[20] = '\0';
|
||||
|
||||
Log::verbose("GetPublicAddress", "Querrying STUN server 132.177.123.6");
|
||||
unsigned int dst = (132<<24)+(177<<16)+(123<<8)+6;
|
||||
NetworkManager::getInstance()->setManualSocketsMode(true);
|
||||
NetworkManager::getInstance()->getHost()->sendRawPacket(bytes, 20, TransportAddress(dst, 3478));
|
||||
m_state = TEST_SENT;
|
||||
// time to pick a random stun server
|
||||
std::vector<char*> stun_servers = UserConfigParams::m_stun_servers;
|
||||
|
||||
RandomGenerator random_gen;
|
||||
int rand_result = random_gen.get(stun_servers.size());
|
||||
Log::verbose("GetPublicAddress", "Using STUN server %s", stun_servers[rand_result]);
|
||||
|
||||
// resolve the name into an IP address
|
||||
struct addrinfo hints, *res, *p;
|
||||
int status;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((status = getaddrinfo(stun_servers[rand_result], NULL, &hints, &res)) != 0) {
|
||||
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
|
||||
return;
|
||||
}
|
||||
for(p = res;p != NULL; p = p->ai_next)
|
||||
{
|
||||
struct sockaddr_in* current_interface = (struct sockaddr_in*)(p->ai_addr);
|
||||
|
||||
m_stun_server_ip = ntohl(current_interface->sin_addr.s_addr);
|
||||
m_transaction_host = new STKHost();
|
||||
m_transaction_host->setupClient(1,1,0,0);
|
||||
m_transaction_host->sendRawPacket(bytes, 20, TransportAddress(m_stun_server_ip, 3478));
|
||||
m_state = TEST_SENT;
|
||||
|
||||
freeaddrinfo(res); // free the linked list
|
||||
return;
|
||||
}
|
||||
freeaddrinfo(res); // free the linked list
|
||||
|
||||
}
|
||||
if (m_state == TEST_SENT)
|
||||
{
|
||||
unsigned int dst = (132<<24)+(177<<16)+(123<<8)+6;
|
||||
uint8_t* data = NetworkManager::getInstance()->getHost()->receiveRawPacket(TransportAddress(dst, 3478));
|
||||
uint8_t* data = m_transaction_host->receiveRawPacket(TransportAddress(m_stun_server_ip, 3478), 2000);
|
||||
if (!data)
|
||||
{
|
||||
m_state = NOTHING_DONE; // will send the test again to an other server
|
||||
return;
|
||||
}
|
||||
assert(data);
|
||||
|
||||
// check that the stun response is a response, contains the magic cookie and the transaction ID
|
||||
@ -184,7 +221,6 @@ void GetPublicAddress::asynchronousUpdate()
|
||||
{
|
||||
Log::debug("GetPublicAddress", "The public address has been found : %i.%i.%i.%i:%i", address>>24&0xff, address>>16&0xff, address>>8&0xff, address&0xff, port);
|
||||
m_state = ADDRESS_KNOWN;
|
||||
NetworkManager::getInstance()->setManualSocketsMode(false);
|
||||
TransportAddress* addr = static_cast<TransportAddress*>(m_callback_object);
|
||||
addr->ip = address;
|
||||
addr->port = port;
|
||||
|
@ -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();
|
||||
@ -44,6 +44,8 @@ class GetPublicAddress : public Protocol
|
||||
STATE m_state;
|
||||
uint32_t m_stun_tansaction_id[3];
|
||||
static const uint32_t m_stun_magic_cookie = 0x2112A442;
|
||||
uint32_t m_stun_server_ip;
|
||||
STKHost* m_transaction_host;
|
||||
};
|
||||
|
||||
#endif // GET_PUBLIC_ADDRESS_HPP
|
||||
|
@ -32,10 +32,6 @@ HidePublicAddress::~HidePublicAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void HidePublicAddress::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void HidePublicAddress::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
ns.removeFront(4);
|
||||
while(ns.size() >= 16)
|
||||
@ -59,6 +59,7 @@ void KartUpdateProtocol::notifyEvent(Event* event)
|
||||
pthread_mutex_unlock(&m_positions_updates_mutex);
|
||||
ns.removeFront(32);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void KartUpdateProtocol::setup()
|
||||
@ -67,6 +68,8 @@ void KartUpdateProtocol::setup()
|
||||
|
||||
void KartUpdateProtocol::update()
|
||||
{
|
||||
if (!World::getWorld())
|
||||
return;
|
||||
static double time = 0;
|
||||
double current_time = StkTime::getRealTime();
|
||||
if (current_time > time + 0.1) // 10 updates per second
|
||||
|
@ -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() {};
|
||||
|
@ -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.
|
||||
};
|
||||
|
@ -31,10 +31,6 @@ PingProtocol::~PingProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void PingProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void PingProtocol::setup()
|
||||
{
|
||||
m_last_ping_time = 0;
|
||||
|
@ -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();
|
||||
|
@ -33,10 +33,6 @@ QuickJoinProtocol::~QuickJoinProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void QuickJoinProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void QuickJoinProtocol::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
|
@ -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();
|
||||
|
@ -32,10 +32,6 @@ RequestConnection::~RequestConnection()
|
||||
{
|
||||
}
|
||||
|
||||
void RequestConnection::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void RequestConnection::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
|
@ -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();
|
||||
|
@ -9,18 +9,29 @@ 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() {};
|
||||
|
||||
void startGame();
|
||||
void startSelection();
|
||||
void checkIncomingConnectionRequests();
|
||||
void checkRaceFinished();
|
||||
|
||||
protected:
|
||||
// connection management
|
||||
void kartDisconnected(Event* event);
|
||||
void connectionRequested(Event* event);
|
||||
// kart selection
|
||||
void kartSelectionRequested(Event* event);
|
||||
// race votes
|
||||
void playerMajorVote(Event* event);
|
||||
void playerRaceCountVote(Event* event);
|
||||
void playerMinorVote(Event* event);
|
||||
void playerTrackVote(Event* event);
|
||||
void playerReversedVote(Event* event);
|
||||
void playerLapsVote(Event* event);
|
||||
|
||||
uint8_t m_next_id; //!< Next id to assign to a peer.
|
||||
std::vector<TransportAddress> m_peers;
|
||||
@ -28,6 +39,7 @@ class ServerLobbyRoomProtocol : public LobbyRoomProtocol
|
||||
uint32_t m_current_protocol_id;
|
||||
TransportAddress m_public_address;
|
||||
bool m_selection_enabled;
|
||||
bool m_in_race;
|
||||
|
||||
enum STATE
|
||||
{
|
||||
|
@ -32,10 +32,6 @@ ShowPublicAddress::~ShowPublicAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void ShowPublicAddress::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void ShowPublicAddress::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
@ -52,7 +48,9 @@ void ShowPublicAddress::asynchronousUpdate()
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("address",addr.ip);
|
||||
m_request->setParameter("port",addr.port);
|
||||
m_request->setParameter("private_port",NetworkManager::getInstance()->getHost()->getPort());
|
||||
m_request->setParameter("action","set");
|
||||
Log::info("ShowPublicAddress", "Showing addr %u and port %d", addr.ip, addr.port);
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
|
@ -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();
|
||||
|
@ -1,20 +1,21 @@
|
||||
#include "network/protocols/start_game_protocol.hpp"
|
||||
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_world.hpp"
|
||||
#include "network/protocols/synchronization_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/kart_selection.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "states_screens/network_kart_selection.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
StartGameProtocol::StartGameProtocol(GameSetup* game_setup) :
|
||||
Protocol(NULL, PROTOCOL_START_GAME)
|
||||
@ -32,20 +33,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 +63,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()
|
||||
@ -93,7 +95,6 @@ void StartGameProtocol::update()
|
||||
m_listener->requestStart(new SynchronizationProtocol());
|
||||
Log::info("StartGameProtocol", "SynchronizationProtocol started.");
|
||||
// race startup sequence
|
||||
|
||||
NetworkWorld::getInstance<NetworkWorld>()->start(); // builds it and starts
|
||||
race_manager->setNumKarts(m_game_setup->getPlayerCount());
|
||||
race_manager->setNumPlayers(m_game_setup->getPlayerCount());
|
||||
@ -115,7 +116,11 @@ void StartGameProtocol::update()
|
||||
PlayerProfile* profileToUse = unlock_manager->getCurrentPlayer();
|
||||
assert(profileToUse);
|
||||
InputDevice* device = input_manager->getDeviceList()->getLatestUsedDevice();
|
||||
int new_player_id = StateManager::get()->createActivePlayer( profileToUse, device , players[i]->user_profile);
|
||||
int new_player_id = 0;
|
||||
if (StateManager::get()->getActivePlayers().size() >= 0) // more than one player, we're the first
|
||||
new_player_id = 0;
|
||||
else
|
||||
new_player_id = StateManager::get()->createActivePlayer( profileToUse, device , players[i]->user_profile);
|
||||
device->setPlayer(StateManager::get()->getActivePlayer(new_player_id));
|
||||
input_manager->getDeviceList()->setSinglePlayer(StateManager::get()->getActivePlayer(new_player_id));
|
||||
|
||||
@ -162,6 +167,7 @@ void StartGameProtocol::update()
|
||||
// now the synchronization protocol exists.
|
||||
Log::info("StartGameProtocol", "Starting the race loading.");
|
||||
race_manager->startSingleRace("jungle", 1, false);
|
||||
World::getWorld()->setNetworkWorld(true);
|
||||
m_state = LOADING;
|
||||
}
|
||||
}
|
||||
@ -174,6 +180,8 @@ void StartGameProtocol::update()
|
||||
}
|
||||
else if (m_state == READY)
|
||||
{
|
||||
// set karts into the network game setup
|
||||
NetworkManager::getInstance()->getGameSetup()->bindKartsToProfiles();
|
||||
m_state = EXITING;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
@ -31,10 +31,6 @@ StartServer::~StartServer()
|
||||
{
|
||||
}
|
||||
|
||||
void StartServer::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void StartServer::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
@ -51,8 +47,10 @@ void StartServer::asynchronousUpdate()
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("address",addr.ip);
|
||||
m_request->setParameter("port",addr.port);
|
||||
m_request->setParameter("private_port",NetworkManager::getInstance()->getHost()->getPort());
|
||||
m_request->setParameter("max_players",UserConfigParams::m_server_max_players);
|
||||
m_request->setParameter("action","start-server");
|
||||
Log::info("ShowPublicAddress", "Showing addr %u and port %d", addr.ip, addr.port);
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
|
@ -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();
|
||||
|
@ -31,8 +31,9 @@ StopServer::~StopServer()
|
||||
{
|
||||
}
|
||||
|
||||
void StopServer::notifyEvent(Event* event)
|
||||
bool StopServer::notifyEventAsynchronous(Event* event)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void StopServer::setup()
|
||||
@ -52,6 +53,7 @@ void StopServer::asynchronousUpdate()
|
||||
m_request->setParameter("address",addr.ip);
|
||||
m_request->setParameter("port",addr.port);
|
||||
m_request->setParameter("action","stop-server");
|
||||
Log::info("StopServer", "address %u, port %d", addr.ip, addr.port);
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
|
@ -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();
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/protocols/kart_update_protocol.hpp"
|
||||
#include "network/protocols/controller_events_protocol.hpp"
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -30,19 +31,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 +53,7 @@ void SynchronizationProtocol::notifyEvent(Event* event)
|
||||
if (talk_id > peers.size())
|
||||
{
|
||||
Log::warn("SynchronizationProtocol", "The ID isn't known.");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,18 +68,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 +94,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 = StkTime::getRealTime();
|
||||
m_total_diff[peer_id] += current_time - m_pings[peer_id][sequence];
|
||||
@ -103,6 +105,7 @@ void SynchronizationProtocol::notifyEvent(Event* event)
|
||||
|
||||
Log::debug("SynchronizationProtocol", "Ping is %u", m_average_ping[peer_id]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -131,6 +134,7 @@ void SynchronizationProtocol::asynchronousUpdate()
|
||||
Log::info("SynchronizationProtocol", "Countdown finished. Starting now.");
|
||||
m_listener->requestStart(new KartUpdateProtocol());
|
||||
m_listener->requestStart(new ControllerEventsProtocol());
|
||||
m_listener->requestStart(new GameEventsProtocol());
|
||||
m_listener->requestTerminate(this);
|
||||
return;
|
||||
}
|
||||
|
@ -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();
|
||||
|
369
src/network/race_config.cpp
Normal file
369
src/network/race_config.cpp
Normal file
@ -0,0 +1,369 @@
|
||||
#include "network/race_config.hpp"
|
||||
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
/** \brief Gets the element with the highest count in a std::map<S,int>.
|
||||
* \param histogram : A pointer to the histogram.
|
||||
* \return The key of type S that has the highest second value.
|
||||
*/
|
||||
template<typename S>
|
||||
S getHighestInHistogram(std::map<S,int>* histogram)
|
||||
{
|
||||
S best_item;
|
||||
uint8_t highest_count;
|
||||
for (typename std::map<S, int>::iterator it = histogram->begin();
|
||||
it != histogram->end(); it++)
|
||||
{
|
||||
if (it->second > highest_count)
|
||||
{
|
||||
highest_count = it->second;
|
||||
best_item = it->first;
|
||||
}
|
||||
}
|
||||
return best_item;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//--------------------------------- TrackVote --------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TrackVote::TrackVote()
|
||||
{
|
||||
has_voted_laps = false;
|
||||
has_voted_track = false;
|
||||
has_voted_reversed = false;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void TrackVote::voteTrack(std::string track)
|
||||
{
|
||||
track_info.track = track;
|
||||
has_voted_track = true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void TrackVote::voteReversed(bool reversed)
|
||||
{
|
||||
track_info.reversed = reversed;
|
||||
has_voted_reversed = true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void TrackVote::voteLaps(uint8_t laps)
|
||||
{
|
||||
track_info.laps = laps;
|
||||
has_voted_laps = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//--------------------------------- RaceVote ---------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
RaceVote::RaceVote()
|
||||
{
|
||||
m_has_voted_major = false;
|
||||
m_has_voted_minor = false;
|
||||
m_has_voted_races_count = false;
|
||||
m_major_mode = 0;
|
||||
m_minor_mode = 0;
|
||||
m_races_count = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceVote::voteMajor(uint8_t major)
|
||||
{
|
||||
m_has_voted_major = true;
|
||||
m_major_mode = major;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceVote::voteRaceCount(uint8_t count)
|
||||
{
|
||||
m_has_voted_races_count = true;
|
||||
m_races_count = count;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceVote::voteMinor(uint8_t minor)
|
||||
{
|
||||
m_has_voted_minor = true;
|
||||
m_minor_mode = minor;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceVote::voteTrack(std::string track, uint8_t track_number)
|
||||
{
|
||||
m_tracks_vote[track_number].voteTrack(track);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceVote::voteReversed(bool reversed, uint8_t track_number)
|
||||
{
|
||||
m_tracks_vote[track_number].voteReversed(reversed);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceVote::voteLaps(uint8_t laps, uint8_t track_number)
|
||||
{
|
||||
m_tracks_vote[track_number].voteLaps(laps);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedMajor() const
|
||||
{
|
||||
return m_has_voted_major;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedRacesCount() const
|
||||
{
|
||||
return m_has_voted_races_count;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedMinor() const
|
||||
{
|
||||
return m_has_voted_minor;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedTrack(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].has_voted_track;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedReversed(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].has_voted_reversed;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedLaps(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].has_voted_laps;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uint8_t RaceVote::getMajorVote() const
|
||||
{
|
||||
return m_major_mode;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t RaceVote::getRacesCountVote() const
|
||||
{
|
||||
return m_races_count;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t RaceVote::getMinorVote() const
|
||||
{
|
||||
return m_minor_mode;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string RaceVote::getTrackVote(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].track_info.track;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::getReversedVote(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].track_info.reversed;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t RaceVote::getLapsVote(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].track_info.laps;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//--------------------------------- RaceConfig -------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
RaceConfig::RaceConfig()
|
||||
{
|
||||
m_max_players = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceConfig::setPlayerCount(uint8_t count)
|
||||
{
|
||||
m_max_players = count;
|
||||
m_votes.resize(m_max_players);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceConfig::setPlayerMajorVote(uint8_t player_id, uint8_t major)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted for major %d", player_id, major);
|
||||
m_votes[player_id].voteMajor(major);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceConfig::setPlayerRaceCountVote(uint8_t player_id, uint8_t count)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted for %d races in GP", player_id, count);
|
||||
m_votes[player_id].voteRaceCount(count);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceConfig::setPlayerMinorVote(uint8_t player_id, uint8_t minor)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted for minor %d", player_id, minor);
|
||||
m_votes[player_id].voteMinor(minor);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceConfig::setPlayerTrackVote(uint8_t player_id, std::string track, uint8_t track_nb)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted for track %s", player_id, track.c_str());
|
||||
m_votes[player_id].voteTrack(track, track_nb);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceConfig::setPlayerReversedVote(uint8_t player_id, bool reversed, uint8_t track_nb)
|
||||
{
|
||||
if (reversed)
|
||||
Log::info("RaceConfig", "Player %d voted map %d to be reversed", player_id, track_nb);
|
||||
else
|
||||
Log::info("RaceConfig", "Player %d voted map %d NOT to be reversed", player_id, track_nb);
|
||||
m_votes[player_id].voteReversed(reversed, track_nb);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceConfig::setPlayerLapsVote(uint8_t player_id, uint8_t lap_count, uint8_t track_nb)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted map %d to have %d laps", player_id, track_nb, lap_count);
|
||||
m_votes[player_id].voteLaps(lap_count, track_nb);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void RaceConfig::computeRaceMode()
|
||||
{
|
||||
// calculate the race type and number of tracks (in GP mode).
|
||||
std::map<int,int> major_histogram;
|
||||
std::map<int,int> races_count_histogram;
|
||||
std::map<int,int> minor_histogram;
|
||||
for (unsigned int i = 0; i < m_max_players; i++)
|
||||
{
|
||||
// increase the count of votes
|
||||
if (m_votes[i].hasVotedMajor())
|
||||
{
|
||||
try
|
||||
{
|
||||
major_histogram.at(m_votes[i].getMajorVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range& oor) // doesn't exist in the map
|
||||
{
|
||||
major_histogram[m_votes[i].getMajorVote()] = 1;
|
||||
}
|
||||
}
|
||||
else if (m_votes[i].hasVotedRacesCount())
|
||||
{
|
||||
try
|
||||
{
|
||||
races_count_histogram.at(m_votes[i].getRacesCountVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range& oor) // doesn't exist in the map
|
||||
{
|
||||
races_count_histogram[m_votes[i].getRacesCountVote()] = 1;
|
||||
}
|
||||
}
|
||||
else if (m_votes[i].hasVotedMinor())
|
||||
{
|
||||
try
|
||||
{
|
||||
minor_histogram.at(m_votes[i].getMinorVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range& oor) // doesn't exist in the map
|
||||
{
|
||||
minor_histogram[m_votes[i].getMinorVote()] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// now we know :
|
||||
m_major_mode = ((major_histogram.size() > 0) ? getHighestInHistogram<int>(&major_histogram) : 1);
|
||||
m_races_count = ((minor_histogram.size() > 0) ? getHighestInHistogram<int>(&races_count_histogram) : 1);
|
||||
m_minor_mode = ((minor_histogram.size() > 0) ? getHighestInHistogram<int>(&minor_histogram) : 0);
|
||||
|
||||
if (m_major_mode == RaceManager::MAJOR_MODE_GRAND_PRIX)
|
||||
m_tracks.resize(m_races_count);
|
||||
else
|
||||
{
|
||||
m_tracks.resize(1);
|
||||
m_races_count = 1;
|
||||
}
|
||||
|
||||
Log::info("RaceConfig", "Major mode will be %d with %d races. Minor is %d", m_major_mode, m_races_count, m_minor_mode);
|
||||
}
|
||||
void RaceConfig::computeNextTrack()
|
||||
{
|
||||
for (unsigned int j = 0; j < m_races_count; j++)
|
||||
{
|
||||
// first create histograms of the votes
|
||||
std::map<std::string,int> tracks_histogram;
|
||||
std::map<bool,int> reversed_histogram;
|
||||
std::map<int,int> laps_histogram;
|
||||
for (unsigned int i = 0; i < m_max_players; i++)
|
||||
{
|
||||
// increase the count of votes
|
||||
if (m_votes[i].hasVotedTrack())
|
||||
{
|
||||
try // maps
|
||||
{
|
||||
tracks_histogram.at(m_votes[i].getTrackVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range& oor) // doesn't exist in the map
|
||||
{
|
||||
tracks_histogram[m_votes[i].getTrackVote()] = 1;
|
||||
}
|
||||
}
|
||||
else if (m_votes[i].hasVotedReversed())
|
||||
{
|
||||
try // reversed
|
||||
{
|
||||
reversed_histogram.at(m_votes[i].getReversedVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range& oor) // doesn't exist in the map
|
||||
{
|
||||
reversed_histogram[m_votes[i].getReversedVote()] = 1;
|
||||
}
|
||||
}
|
||||
else if (m_votes[i].hasVotedLaps())
|
||||
{
|
||||
try // laps
|
||||
{
|
||||
laps_histogram.at(m_votes[i].getLapsVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range& oor) // doesn't exist in the mapt
|
||||
{
|
||||
laps_histogram[m_votes[i].getLapsVote()] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// now find the highest votes
|
||||
m_tracks[j].track = getHighestInHistogram<std::string>(&tracks_histogram);
|
||||
m_tracks[j].reversed = getHighestInHistogram<bool>(&reversed_histogram);
|
||||
m_tracks[j].laps = getHighestInHistogram<int>(&laps_histogram);
|
||||
if (m_tracks[j].reversed)
|
||||
Log::info("RaceConfig", "Race %d will be on %s with %d laps and reversed", j, m_tracks[j].track.c_str(), m_tracks[j].laps);
|
||||
else
|
||||
Log::info("RaceConfig", "Race %d will be on %s with %d laps", j, m_tracks[j].track.c_str(), m_tracks[j].laps);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const TrackInfo* RaceConfig::getNextTrackInfo() const
|
||||
{
|
||||
return &m_tracks[0];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
98
src/network/race_config.hpp
Normal file
98
src/network/race_config.hpp
Normal file
@ -0,0 +1,98 @@
|
||||
#ifndef RACE_CONFIG_HPP
|
||||
#define RACE_CONFIG_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "utils/types.hpp"
|
||||
|
||||
class TrackInfo
|
||||
{
|
||||
public:
|
||||
TrackInfo() { laps = 0; reversed = false; }
|
||||
std::string track;
|
||||
bool reversed;
|
||||
uint8_t laps;
|
||||
};
|
||||
class TrackVote
|
||||
{
|
||||
public:
|
||||
TrackVote();
|
||||
|
||||
void voteTrack(std::string track);
|
||||
void voteReversed(bool reversed);
|
||||
void voteLaps(uint8_t laps);
|
||||
|
||||
TrackInfo track_info;
|
||||
|
||||
bool has_voted_track;
|
||||
bool has_voted_reversed;
|
||||
bool has_voted_laps;
|
||||
};
|
||||
class RaceVote
|
||||
{
|
||||
public:
|
||||
RaceVote();
|
||||
|
||||
void voteMajor(uint8_t major);
|
||||
void voteRaceCount(uint8_t count);
|
||||
void voteMinor(uint8_t minor);
|
||||
void voteTrack(std::string track, uint8_t track_number = 0);
|
||||
void voteReversed(bool reversed, uint8_t track_number = 0);
|
||||
void voteLaps(uint8_t laps, uint8_t track_number = 0);
|
||||
|
||||
bool hasVotedMajor() const;
|
||||
bool hasVotedRacesCount() const;
|
||||
bool hasVotedMinor() const;
|
||||
bool hasVotedTrack(uint8_t track_number = 0) const;
|
||||
bool hasVotedReversed(uint8_t track_number = 0) const;
|
||||
bool hasVotedLaps(uint8_t track_number = 0) const;
|
||||
|
||||
uint8_t getMajorVote() const;
|
||||
uint8_t getRacesCountVote() const;
|
||||
uint8_t getMinorVote() const;
|
||||
std::string getTrackVote(uint8_t track_number = 0) const;
|
||||
bool getReversedVote(uint8_t track_number = 0) const;
|
||||
uint8_t getLapsVote(uint8_t track_number = 0) const;
|
||||
|
||||
private:
|
||||
uint8_t m_major_mode;
|
||||
uint8_t m_minor_mode;
|
||||
uint8_t m_races_count; //!< Stores the number of races that will be in a GP
|
||||
bool m_has_voted_major;
|
||||
bool m_has_voted_minor;
|
||||
bool m_has_voted_races_count;
|
||||
std::vector<TrackVote> m_tracks_vote;
|
||||
};
|
||||
|
||||
class RaceConfig
|
||||
{
|
||||
public:
|
||||
RaceConfig();
|
||||
|
||||
void setPlayerCount(uint8_t count);
|
||||
void setPlayerMajorVote(uint8_t player_id, uint8_t major);
|
||||
void setPlayerRaceCountVote(uint8_t player_id, uint8_t count);
|
||||
void setPlayerMinorVote(uint8_t player_id, uint8_t minor);
|
||||
void setPlayerTrackVote(uint8_t player_id, std::string track, uint8_t track_nb = 0);
|
||||
void setPlayerReversedVote(uint8_t player_id, bool reversed, uint8_t track_nb = 0);
|
||||
void setPlayerLapsVote(uint8_t player_id, uint8_t lap_count, uint8_t track_nb = 0);
|
||||
|
||||
void computeRaceMode();
|
||||
void computeNextTrack();
|
||||
|
||||
const TrackInfo* getNextTrackInfo() const;
|
||||
bool getReverse() const;
|
||||
bool getLapCount() const;
|
||||
|
||||
protected:
|
||||
std::vector<TrackInfo> m_tracks;
|
||||
int m_minor_mode;
|
||||
int m_major_mode;
|
||||
int m_races_count;
|
||||
|
||||
std::vector<RaceVote> m_votes;
|
||||
uint8_t m_max_players;
|
||||
};
|
||||
|
||||
|
||||
#endif // RACE_CONFIG_HPP
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2008 Joerg Henrichs
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
@ -16,6 +16,9 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file remote_kart_info.hpp
|
||||
*/
|
||||
|
||||
#ifndef HEADER_REMOTE_KART_INFO_HPP
|
||||
#define HEADER_REMOTE_KART_INFO_HPP
|
||||
|
||||
|
@ -62,15 +62,25 @@ void* waitInput2(void* data)
|
||||
assert(protocol);
|
||||
protocol->startSelection();
|
||||
}
|
||||
else if (str == "compute_race")
|
||||
{
|
||||
GameSetup* setup = NetworkManager::getInstance()->getGameSetup();
|
||||
setup->getRaceConfig()->computeRaceMode();
|
||||
}
|
||||
else if (str == "compute_track")
|
||||
{
|
||||
GameSetup* setup = NetworkManager::getInstance()->getGameSetup();
|
||||
setup->getRaceConfig()->computeNextTrack();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t id = ProtocolManager::getInstance()->requestStart(new StopServer());
|
||||
while(ProtocolManager::getInstance()->getProtocolState(id) != PROTOCOL_STATE_TERMINATED)
|
||||
{
|
||||
StkTime::sleep(1);
|
||||
}
|
||||
|
||||
main_loop->abort();
|
||||
exit(0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -16,6 +16,9 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file server_network_manager.hpp
|
||||
*/
|
||||
|
||||
#ifndef SERVER_NETWORK_MANAGER_HPP
|
||||
#define SERVER_NETWORK_MANAGER_HPP
|
||||
|
||||
@ -33,6 +36,9 @@ class ServerNetworkManager : public NetworkManager
|
||||
|
||||
virtual void run();
|
||||
|
||||
void setMaxPlayers(uint8_t count) { m_max_players = count; }
|
||||
uint8_t getMaxPlayers() {return m_max_players;}
|
||||
|
||||
void kickAllPlayers();
|
||||
|
||||
virtual void sendPacket(const NetworkString& data, bool reliable = true);
|
||||
@ -44,6 +50,7 @@ class ServerNetworkManager : public NetworkManager
|
||||
virtual ~ServerNetworkManager();
|
||||
|
||||
pthread_t* m_thread_keyboard;
|
||||
uint8_t m_max_players;
|
||||
|
||||
};
|
||||
|
||||
|
@ -16,22 +16,39 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file singleton.hpp
|
||||
*/
|
||||
|
||||
#ifndef SINGLETON_HPP
|
||||
#define SINGLETON_HPP
|
||||
|
||||
#include "utils/log.hpp"
|
||||
|
||||
/*! \class ProtocolManager
|
||||
* \brief Manages the protocols at runtime.
|
||||
* This has been designed to allow multi-inheritance. This is advised to
|
||||
* re-declare getInstance, but whithout templates parameters in the inheriting
|
||||
* classes.
|
||||
*/
|
||||
template <typename T>
|
||||
class Singleton
|
||||
{
|
||||
protected:
|
||||
/*! \brief Constructor */
|
||||
Singleton () { m_singleton = NULL; }
|
||||
/*! \brief Destructor */
|
||||
virtual ~Singleton ()
|
||||
{
|
||||
Log::info("Singleton", "Destroyed singleton.");
|
||||
}
|
||||
|
||||
public:
|
||||
/*! \brief Used to get the instance, after a dynamic cast.
|
||||
* This is important when making a double-inheritance of this class.
|
||||
* For example, if A is a singleton inherited by B, you can call
|
||||
* B::getInstance<A>() to have the instance returned as a A*.
|
||||
* If the cast fails, a log message will notify it.
|
||||
*/
|
||||
template<typename S>
|
||||
static S *getInstance ()
|
||||
{
|
||||
@ -43,11 +60,13 @@ class Singleton
|
||||
Log::debug("Singleton", "THE SINGLETON HAS NOT BEEN REALOCATED, IT IS NOT OF THE REQUESTED TYPE.");
|
||||
return result;
|
||||
}
|
||||
/*! \brief Used to get the instance. */
|
||||
static T *getInstance()
|
||||
{
|
||||
return (dynamic_cast<T*> (m_singleton));
|
||||
return m_singleton;
|
||||
}
|
||||
|
||||
/*! \brief Used to kill the singleton, if needed. */
|
||||
static void kill ()
|
||||
{
|
||||
if (m_singleton)
|
||||
|
@ -18,9 +18,10 @@
|
||||
|
||||
#include "network/stk_host.hpp"
|
||||
|
||||
#include "graphics/irr_driver.hpp" // get access to irrlicht sleep function
|
||||
#include "config/user_config.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
@ -28,25 +29,53 @@
|
||||
# define inet_ntop InetNtop
|
||||
#else
|
||||
# include <arpa/inet.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
FILE* STKHost::m_log_file = NULL;
|
||||
pthread_mutex_t STKHost::m_log_mutex;
|
||||
|
||||
void STKHost::logPacket(const NetworkString ns, bool incoming)
|
||||
{
|
||||
if (m_log_file == NULL)
|
||||
return;
|
||||
pthread_mutex_lock(&m_log_mutex);
|
||||
if (incoming)
|
||||
fprintf(m_log_file, "[%d\t] <-- ", (int)(StkTime::getRealTime()));
|
||||
else
|
||||
fprintf(m_log_file, "[%d\t] --> ", (int)(StkTime::getRealTime()));
|
||||
for (int i = 0; i < ns.size(); i++)
|
||||
{
|
||||
fprintf(m_log_file, "%d.", ns[i]);
|
||||
}
|
||||
fprintf(m_log_file, "\n");
|
||||
pthread_mutex_unlock(&m_log_mutex);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void* STKHost::receive_data(void* self)
|
||||
{
|
||||
ENetEvent event;
|
||||
ENetHost* host = (((STKHost*)(self))->m_host);
|
||||
while (1)
|
||||
STKHost* myself = (STKHost*)(self);
|
||||
ENetHost* host = myself->m_host;
|
||||
while (!myself->mustStopListening())
|
||||
{
|
||||
while (enet_host_service(host, &event, 20) != 0) {
|
||||
Event* evt = new Event(&event);
|
||||
if (evt->type == EVENT_TYPE_MESSAGE)
|
||||
logPacket(evt->data(), true);
|
||||
if (event.type != ENET_EVENT_TYPE_NONE)
|
||||
NetworkManager::getInstance()->notifyEvent(evt);
|
||||
delete evt;
|
||||
}
|
||||
}
|
||||
myself->m_listening = false;
|
||||
delete myself->m_listening_thread;
|
||||
myself->m_listening_thread = NULL;
|
||||
Log::info("STKHost", "Listening has been stopped");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -56,17 +85,24 @@ STKHost::STKHost()
|
||||
{
|
||||
m_host = NULL;
|
||||
m_listening_thread = NULL;
|
||||
m_log_file = NULL;
|
||||
pthread_mutex_init(&m_exit_mutex, NULL);
|
||||
pthread_mutex_init(&m_log_mutex, NULL);
|
||||
if (UserConfigParams::m_packets_log_filename.toString() != "")
|
||||
m_log_file = fopen(UserConfigParams::m_packets_log_filename.c_str(), "w+");
|
||||
if (!m_log_file)
|
||||
Log::warn("STKHost", "Network packets won't be logged: no file.");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
STKHost::~STKHost()
|
||||
{
|
||||
if (m_listening_thread)
|
||||
stopListening();
|
||||
if (m_log_file)
|
||||
{
|
||||
pthread_cancel(*m_listening_thread);//, SIGKILL); with kill
|
||||
delete m_listening_thread;
|
||||
m_listening_thread = NULL;
|
||||
fclose(m_log_file);
|
||||
Log::warn("STKHost", "Packet logging file has been closed.");
|
||||
}
|
||||
if (m_host)
|
||||
{
|
||||
@ -84,6 +120,13 @@ void STKHost::setupServer(uint32_t address, uint16_t port, int peer_count,
|
||||
addr->host = address;
|
||||
addr->port = port;
|
||||
|
||||
#ifdef WIN32/*
|
||||
addr->host = 0;
|
||||
addr->host += ((unsigned int)(192)<<0); // 192.168.0.11
|
||||
addr->host += ((unsigned int)(168)<<8); // 192.168.0.11
|
||||
addr->host += ((unsigned int)(11)<<24); // 192.168.0.11*/
|
||||
#endif
|
||||
|
||||
m_host = enet_host_create(addr, peer_count, channel_limit,
|
||||
max_incoming_bandwidth, max_outgoing_bandwidth);
|
||||
if (m_host == NULL)
|
||||
@ -114,8 +157,10 @@ void STKHost::setupClient(int peer_count, int channel_limit,
|
||||
|
||||
void STKHost::startListening()
|
||||
{
|
||||
pthread_mutex_lock(&m_exit_mutex); // will let the update function start
|
||||
m_listening_thread = (pthread_t*)(malloc(sizeof(pthread_t)));
|
||||
pthread_create(m_listening_thread, NULL, &STKHost::receive_data, this);
|
||||
m_listening = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -124,8 +169,8 @@ void STKHost::stopListening()
|
||||
{
|
||||
if(m_listening_thread)
|
||||
{
|
||||
pthread_cancel(*m_listening_thread);
|
||||
m_listening_thread = NULL;
|
||||
pthread_mutex_unlock(&m_exit_mutex); // will stop the update function on its next update
|
||||
pthread_join(*m_listening_thread, NULL); // wait the thread to end
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,6 +189,7 @@ void STKHost::sendRawPacket(uint8_t* data, int length, TransportAddress dst)
|
||||
sendto(m_host->socket, (char*)data, length, 0,(sockaddr*)&to, to_len);
|
||||
Log::verbose("STKHost", "Raw packet sent to %i.%i.%i.%i:%u", ((dst.ip>>24)&0xff)
|
||||
, ((dst.ip>>16)&0xff), ((dst.ip>>8)&0xff), ((dst.ip>>0)&0xff), dst.port);
|
||||
STKHost::logPacket(NetworkString(std::string((char*)(data), length)), false);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -161,43 +207,98 @@ uint8_t* STKHost::receiveRawPacket()
|
||||
{
|
||||
i++;
|
||||
len = recv(m_host->socket,(char*)buffer,2048, 0);
|
||||
irr_driver->getDevice()->sleep(1);
|
||||
StkTime::sleep(1);
|
||||
}
|
||||
STKHost::logPacket(NetworkString(std::string((char*)(buffer), len)), true);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t* STKHost::receiveRawPacket(TransportAddress sender)
|
||||
uint8_t* STKHost::receiveRawPacket(TransportAddress* sender)
|
||||
{
|
||||
uint8_t* buffer; // max size needed normally (only used for stun)
|
||||
buffer = (uint8_t*)(malloc(sizeof(uint8_t)*2048));
|
||||
memset(buffer, 0, 2048);
|
||||
|
||||
socklen_t from_len;
|
||||
struct sockaddr addr;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
from_len = sizeof(addr);
|
||||
int len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len);
|
||||
int len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, (struct sockaddr*)(&addr), &from_len);
|
||||
|
||||
int i = 0;
|
||||
// wait to receive the message because enet sockets are non-blocking
|
||||
while(len < 0 || (
|
||||
(uint8_t)(addr.sa_data[2]) != (sender.ip>>24&0xff)
|
||||
&& (uint8_t)(addr.sa_data[3]) != (sender.ip>>16&0xff)
|
||||
&& (uint8_t)(addr.sa_data[4]) != (sender.ip>>8&0xff)
|
||||
&& (uint8_t)(addr.sa_data[5]) != (sender.ip&0xff)))
|
||||
while(len == -1) // nothing received
|
||||
{
|
||||
i++;
|
||||
len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len);
|
||||
irr_driver->getDevice()->sleep(1); // wait 1 millisecond between two checks
|
||||
len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, (struct sockaddr*)(&addr), &from_len);
|
||||
StkTime::sleep(1); // wait 1 millisecond between two checks
|
||||
}
|
||||
if (addr.sa_family == AF_INET)
|
||||
if (len == SOCKET_ERROR)
|
||||
{
|
||||
Log::error("STKHost", "Problem with the socket. Please contact the dev team.");
|
||||
}
|
||||
// we received the data
|
||||
sender->ip = ntohl((uint32_t)(addr.sin_addr.s_addr));
|
||||
sender->port = ntohs(addr.sin_port);
|
||||
|
||||
if (addr.sin_family == AF_INET)
|
||||
{
|
||||
char s[20];
|
||||
inet_ntop(AF_INET, &(((struct sockaddr_in *)&addr)->sin_addr), s, 20);
|
||||
inet_ntop(AF_INET, &(addr.sin_addr), s, 20);
|
||||
Log::info("STKHost", "IPv4 Address of the sender was %s", s);
|
||||
}
|
||||
STKHost::logPacket(NetworkString(std::string((char*)(buffer), len)), true);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t* STKHost::receiveRawPacket(TransportAddress sender, int max_tries)
|
||||
{
|
||||
uint8_t* buffer; // max size needed normally (only used for stun)
|
||||
buffer = (uint8_t*)(malloc(sizeof(uint8_t)*2048));
|
||||
memset(buffer, 0, 2048);
|
||||
|
||||
socklen_t from_len;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
from_len = sizeof(addr);
|
||||
int len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, (struct sockaddr*)(&addr), &from_len);
|
||||
|
||||
int i = 0;
|
||||
// wait to receive the message because enet sockets are non-blocking
|
||||
while(len < 0 || addr.sin_addr.s_addr == sender.ip)
|
||||
{
|
||||
i++;
|
||||
if (len>=0)
|
||||
{
|
||||
Log::info("STKHost", "Message received but the ip address didn't match the expected one.");
|
||||
}
|
||||
len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, (struct sockaddr*)(&addr), &from_len);
|
||||
uint32_t addr1 = addr.sin_addr.s_addr;
|
||||
uint32_t addr2 = sender.ip;
|
||||
uint32_t addr3 = ntohl(addr1);
|
||||
uint32_t addr4 = ntohl(addr2);
|
||||
StkTime::sleep(1); // wait 1 millisecond between two checks
|
||||
if (i >= max_tries && max_tries != -1)
|
||||
{
|
||||
Log::verbose("STKHost", "No answer from the server on %u.%u.%u.%u:%u", (m_host->address.host&0xff),
|
||||
(m_host->address.host>>8&0xff),
|
||||
(m_host->address.host>>16&0xff),
|
||||
(m_host->address.host>>24&0xff),
|
||||
(m_host->address.port));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (addr.sin_family == AF_INET)
|
||||
{
|
||||
char s[20];
|
||||
inet_ntop(AF_INET, &(addr.sin_addr), s, 20);
|
||||
Log::info("STKHost", "IPv4 Address of the sender was %s", s);
|
||||
}
|
||||
STKHost::logPacket(NetworkString(std::string((char*)(buffer), len)), true);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -208,6 +309,7 @@ void STKHost::broadcastPacket(const NetworkString& data, bool reliable)
|
||||
ENetPacket* packet = enet_packet_create(data.c_str(), data.size()+1,
|
||||
(reliable ? ENET_PACKET_FLAG_RELIABLE : ENET_PACKET_FLAG_UNSEQUENCED));
|
||||
enet_host_broadcast(m_host, 0, packet);
|
||||
STKHost::logPacket(data, false);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -216,7 +318,7 @@ bool STKHost::peerExists(TransportAddress peer)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_host->peerCount; i++)
|
||||
{
|
||||
if (m_host->peers[i].address.host == turnEndianness(peer.ip) &&
|
||||
if (m_host->peers[i].address.host == ntohl(peer.ip) &&
|
||||
m_host->peers[i].address.port == peer.port)
|
||||
{
|
||||
return true;
|
||||
@ -231,7 +333,7 @@ bool STKHost::isConnectedTo(TransportAddress peer)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_host->peerCount; i++)
|
||||
{
|
||||
if (m_host->peers[i].address.host == turnEndianness(peer.ip) &&
|
||||
if (m_host->peers[i].address.host == ntohl(peer.ip) &&
|
||||
m_host->peers[i].address.port == peer.port &&
|
||||
m_host->peers[i].state == ENET_PEER_STATE_CONNECTED)
|
||||
{
|
||||
@ -240,3 +342,28 @@ bool STKHost::isConnectedTo(TransportAddress peer)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int STKHost::mustStopListening()
|
||||
{
|
||||
switch(pthread_mutex_trylock(&m_exit_mutex)) {
|
||||
case 0: /* if we got the lock, unlock and return 1 (true) */
|
||||
pthread_mutex_unlock(&m_exit_mutex);
|
||||
return 1;
|
||||
case EBUSY: /* return 0 (false) if the mutex was locked */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint16_t STKHost::getPort() const
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
if (getsockname(m_host->socket, (struct sockaddr *)&sin, &len) == -1)
|
||||
Log::error("STKHost", "Error while using getsockname().");
|
||||
else
|
||||
return ntohs(sin.sin_port);
|
||||
return 0;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ void STKPeer::sendPacket(NetworkString const& data, bool reliable)
|
||||
|
||||
uint32_t STKPeer::getAddress() const
|
||||
{
|
||||
return turnEndianness(m_peer->address.host);
|
||||
return ntohl(m_peer->address.host);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -16,6 +16,10 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file stk_peer.hpp
|
||||
* \brief Defines functions to easily manipulate 8-bit network destinated strings.
|
||||
*/
|
||||
|
||||
#ifndef STK_PEER_HPP
|
||||
#define STK_PEER_HPP
|
||||
|
||||
@ -24,6 +28,10 @@
|
||||
#include "network/game_setup.hpp"
|
||||
#include <enet/enet.h>
|
||||
|
||||
/*! \class STKPeer
|
||||
* \brief Represents a peer.
|
||||
* This class is used to interface the ENetPeer structure.
|
||||
*/
|
||||
class STKPeer
|
||||
{
|
||||
friend class Event;
|
||||
@ -45,7 +53,7 @@ class STKPeer
|
||||
bool exists() const;
|
||||
uint32_t getAddress() const;
|
||||
uint16_t getPort() const;
|
||||
NetworkPlayerProfile* getPlayerProfile() { return *m_player_profile; }
|
||||
NetworkPlayerProfile* getPlayerProfile() { return (m_player_profile)?(*m_player_profile):NULL; }
|
||||
uint32_t getClientServerToken() const { return *m_client_server_token; }
|
||||
bool isClientServerTokenSet() const { return *m_token_set; }
|
||||
|
||||
|
@ -1,9 +1 @@
|
||||
#include "network/types.hpp"
|
||||
|
||||
uint32_t turnEndianness(uint32_t val)
|
||||
{
|
||||
return ((val&0xff000000)>>24)
|
||||
+((val&0x00ff0000)>>8)
|
||||
+((val&0x0000ff00)<<8)
|
||||
+((val&0x000000ff)<<24);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file types.hpp
|
||||
/*! \file types.hpp
|
||||
* \brief Declares the general types that are used by the network.
|
||||
*/
|
||||
#ifndef TYPES_HPP
|
||||
@ -26,6 +26,10 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
/*! functions to write easily addresses in logs. */
|
||||
#define ADDRESS_FORMAT "%d.%d.%d.%d:%d"
|
||||
#define ADDRESS_ARGS(ip,port) ((ip>>24)&0xff),((ip>>16)&0xff),((ip>>8)&0xff),((ip>>0)&0xff),port
|
||||
|
||||
/*! \class CallbackObject
|
||||
* \brief Class that must be inherited to pass objects to protocols.
|
||||
*/
|
||||
@ -34,20 +38,26 @@ class CallbackObject
|
||||
public:
|
||||
CallbackObject() {}
|
||||
~CallbackObject() {}
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*! \class TransportAddress
|
||||
* \brief Describes a transport-layer address.
|
||||
* For IP networks, a transport address is the couple ip:port.
|
||||
*/
|
||||
class TransportAddress : public CallbackObject
|
||||
class TransportAddress : public CallbackObject
|
||||
{
|
||||
public:
|
||||
TransportAddress(uint32_t p_ip = 0, uint16_t p_port = 0)
|
||||
TransportAddress(uint32_t p_ip = 0, uint16_t p_port = 0)
|
||||
{ ip = p_ip; port = p_port; }
|
||||
~TransportAddress() {}
|
||||
|
||||
|
||||
bool operator==(const TransportAddress& other) const
|
||||
{ return other.ip == ip && other.port == port; }
|
||||
|
||||
bool operator!=(const TransportAddress& other) const
|
||||
{ return other.ip != ip || other.port != port; }
|
||||
|
||||
uint32_t ip; //!< The IPv4 address
|
||||
uint16_t port; //!< The port number
|
||||
};
|
||||
@ -55,17 +65,15 @@ class TransportAddress : public CallbackObject
|
||||
/*! \class PlayerLogin
|
||||
* \brief Contains the information needed to authenticate a user.
|
||||
*/
|
||||
class PlayerLogin : public CallbackObject
|
||||
class PlayerLogin : public CallbackObject
|
||||
{
|
||||
public:
|
||||
PlayerLogin() {}
|
||||
~PlayerLogin() { username.clear(); password.clear(); }
|
||||
|
||||
|
||||
std::string username; //!< Username of the player
|
||||
std::string password; //!< Password of the player
|
||||
};
|
||||
|
||||
uint32_t turnEndianness(uint32_t val);
|
||||
|
||||
|
||||
#endif // TYPES_HPP
|
||||
|
@ -36,14 +36,6 @@
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||
// Use Sleep, which takes time in msecs. It must be defined after the
|
||||
// includes, since otherwise irrlicht's sleep function is changed.
|
||||
# define sleep(s) Sleep(1000*(s))
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
using namespace Online;
|
||||
|
||||
namespace Online{
|
||||
@ -183,7 +175,10 @@ namespace Online{
|
||||
void HTTPManager::synchronousRequest(Request *request)
|
||||
{
|
||||
assert(request->isAllowedToAdd());
|
||||
request->setBusy();
|
||||
request->execute();
|
||||
request->callback();
|
||||
request->setDone();
|
||||
} // synchronousRequest
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include <string>
|
||||
#ifdef WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
@ -162,8 +164,8 @@ namespace Online{
|
||||
setProgress(1.0f);
|
||||
else
|
||||
setProgress(-1.0f);
|
||||
curl_easy_cleanup(m_curl_session);
|
||||
Request::afterOperation();
|
||||
curl_easy_cleanup(m_curl_session);
|
||||
}
|
||||
|
||||
size_t HTTPRequest::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
@ -261,8 +263,6 @@ namespace Online{
|
||||
{
|
||||
if(m_curl_code != CURLE_OK)
|
||||
Log::error( "XMLRequest::afterOperation", "curl_easy_perform() failed: %s", curl_easy_strerror(m_curl_code));
|
||||
else
|
||||
Log::info( "XMLRequest::afterOperation", "Received : %s", m_string_buffer.c_str());
|
||||
bool success = false;
|
||||
std::string rec_success;
|
||||
if(m_result->get("success", &rec_success))
|
||||
|
@ -339,7 +339,7 @@ void RaceManager::startNew(bool from_overworld)
|
||||
}
|
||||
|
||||
m_track_number = 0;
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX)
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX && !NetworkWorld::getInstance()->isRunning()) // offline mode only
|
||||
{
|
||||
//We look if Player 1 has a saved version of this GP.
|
||||
// =================================================
|
||||
@ -487,7 +487,7 @@ void RaceManager::next()
|
||||
m_track_number++;
|
||||
if(m_track_number<(int)m_tracks.size())
|
||||
{
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX)
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX && !NetworkWorld::getInstance()->isRunning())
|
||||
{
|
||||
//Saving GP state
|
||||
//We look if Player 1 has already saved this GP.
|
||||
@ -631,7 +631,7 @@ void RaceManager::exitRace(bool delete_world)
|
||||
if (m_major_mode==MAJOR_MODE_GRAND_PRIX && m_track_number==(int)m_tracks.size())
|
||||
{
|
||||
unlock_manager->getCurrentSlot()->grandPrixFinished();
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX)
|
||||
if(m_major_mode==MAJOR_MODE_GRAND_PRIX&& !NetworkWorld::getInstance()->isRunning())
|
||||
{
|
||||
//Delete saved GP
|
||||
SavedGrandPrix* gp =
|
||||
@ -730,7 +730,9 @@ void RaceManager::kartFinishedRace(const AbstractKart *kart, float time)
|
||||
m_kart_status[id].m_overall_time += time;
|
||||
m_kart_status[id].m_last_time = time;
|
||||
m_num_finished_karts ++;
|
||||
if(kart->getController()->isPlayerController()) m_num_finished_players++;
|
||||
if(kart->getController()->isPlayerController() ||
|
||||
kart->getController()->isNetworkController())
|
||||
m_num_finished_players++;
|
||||
} // kartFinishedRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -783,7 +785,7 @@ void RaceManager::startSingleRace(const std::string &track_ident,
|
||||
|
||||
setCoinTarget( 0 ); // Might still be set from a previous challenge
|
||||
if (!NetworkWorld::getInstance<NetworkWorld>()->isRunning()) // if not in a network world
|
||||
race_manager->setupPlayerKartInfo(); // do this setup player kart
|
||||
race_manager->setupPlayerKartInfo(); // do this setup player kart
|
||||
|
||||
startNew(from_overworld);
|
||||
}
|
||||
|
@ -563,6 +563,11 @@ public:
|
||||
return m_kart_status[kart].m_overall_time;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
float getKartRaceTime(int kart) const
|
||||
{
|
||||
return m_kart_status[kart].m_last_time;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
KartType getKartType(int kart) const
|
||||
{
|
||||
return m_kart_status[kart].m_kart_type;
|
||||
@ -708,7 +713,7 @@ public:
|
||||
*/
|
||||
bool allPlayerFinished() const
|
||||
{
|
||||
return m_num_finished_players==m_player_karts.size();
|
||||
return m_num_finished_players == m_player_karts.size();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void kartFinishedRace(const AbstractKart* kart, float time);
|
||||
|
@ -45,6 +45,7 @@ using namespace Online;
|
||||
ServerInfoDialog::ServerInfoDialog(uint32_t server_id, uint32_t host_id, bool from_server_creation)
|
||||
: ModalDialog(0.8f,0.8f), m_server_id(server_id), m_host_id(host_id)
|
||||
{
|
||||
Log::info("ServerInfoDialog", "Server id is %d, Host id is %d", server_id, host_id);
|
||||
m_self_destroy = false;
|
||||
m_enter_lobby = false;
|
||||
m_from_server_creation = from_server_creation;
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "modes/overworld.hpp"
|
||||
#include "online/profile.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::Profile* 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)
|
||||
{
|
||||
@ -420,18 +430,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();
|
||||
|
||||
@ -452,6 +465,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();
|
||||
@ -462,17 +482,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
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -819,75 +837,7 @@ void KartHoverListener::onSelectionChanged(DynamicRibbonWidget* theWidget,
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the displayed model
|
||||
ModelViewWidget* w3 = m_parent->m_kart_widgets[playerID].m_model_view;
|
||||
assert( w3 != NULL );
|
||||
|
||||
if (selectionID == 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_parent->m_kart_widgets[playerID].m_kart_name
|
||||
->setText( _("Random Kart"), false );
|
||||
}
|
||||
// selectionID contains the name of the kart, so check only for substr
|
||||
else if (StringUtils::startsWith(selectionID, ID_LOCKED))
|
||||
{
|
||||
w3->clearModels();
|
||||
w3->addModel(irr_driver->getAnimatedMesh(
|
||||
file_manager->getDataDir() + "/models/chest.b3d" )->getMesh(20),
|
||||
Vec3(0,0,0), Vec3(15.0f, 15.0f, 15.0f) );
|
||||
w3->update(0);
|
||||
|
||||
if (m_parent->m_multiplayer)
|
||||
{
|
||||
m_parent->m_kart_widgets[playerID].m_kart_name
|
||||
->setText(_("Locked"), false );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_parent->m_kart_widgets[playerID].m_kart_name
|
||||
->setText(_("Locked : solve active challenges to gain "
|
||||
"access to more!"), false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const KartProperties *kp =
|
||||
kart_properties_manager->getKart(selectionID);
|
||||
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_parent->m_kart_widgets[playerID].m_kart_name
|
||||
->setText( selectionText.c_str(), false );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "[KartSelectionScreen] WARNING: could not "
|
||||
"find a kart named '%s'\n",
|
||||
selectionID.c_str());
|
||||
}
|
||||
}
|
||||
m_parent->updateKartWidgetModel(playerID, selectionID, selectionText);
|
||||
|
||||
m_parent->m_kart_widgets[playerID].setKartInternalName(selectionID);
|
||||
m_parent->validateKartChoices();
|
||||
@ -900,7 +850,7 @@ void KartHoverListener::onSelectionChanged(DynamicRibbonWidget* theWidget,
|
||||
|
||||
// ============================================================================
|
||||
|
||||
KartSelectionScreen::KartSelectionScreen() : Screen("karts.stkgui")
|
||||
KartSelectionScreen::KartSelectionScreen(const char* filename) : Screen(filename)
|
||||
{
|
||||
m_removed_widget = NULL;
|
||||
m_multiplayer_message = NULL;
|
||||
@ -989,6 +939,8 @@ void KartSelectionScreen::init()
|
||||
Widget* placeholder = getWidget("playerskarts");
|
||||
assert(placeholder != NULL);
|
||||
|
||||
// FIXME : The reserved id value is -1 when we switch from KSS to NKSS and vice-versa
|
||||
|
||||
g_dispatcher->setRootID(placeholder->m_reserved_id);
|
||||
|
||||
g_root_id = placeholder->m_reserved_id;
|
||||
@ -1184,7 +1136,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);
|
||||
@ -1491,6 +1443,83 @@ void KartSelectionScreen::playerConfirm(const int playerID)
|
||||
if (allPlayersReady && (!m_multiplayer || amount > 1)) allPlayersDone();
|
||||
} // playerConfirm
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void KartSelectionScreen::updateKartWidgetModel(uint8_t widget_id,
|
||||
const std::string& selection,
|
||||
const irr::core::stringw& selectionText)
|
||||
{
|
||||
// Update the displayed model
|
||||
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 );
|
||||
}
|
||||
// selection contains the name of the kart, so check only for substr
|
||||
else if (StringUtils::startsWith(selection, ID_LOCKED))
|
||||
{
|
||||
w3->clearModels();
|
||||
w3->addModel(irr_driver->getAnimatedMesh(
|
||||
file_manager->getDataDir() + "/models/chest.b3d" )->getMesh(20),
|
||||
Vec3(0,0,0), Vec3(15.0f, 15.0f, 15.0f) );
|
||||
w3->update(0);
|
||||
|
||||
if (m_multiplayer)
|
||||
{
|
||||
m_kart_widgets[widget_id].m_kart_name
|
||||
->setText(_("Locked"), false );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kart_widgets[widget_id].m_kart_name
|
||||
->setText(_("Locked : solve active challenges to gain "
|
||||
"access to more!"), 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( selectionText.c_str(), false );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "[KartSelectionScreen] WARNING: could not "
|
||||
"find a kart named '%s'\n",
|
||||
selection.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/**
|
||||
* Callback handling events from the kart selection menu
|
||||
|
@ -34,6 +34,10 @@ namespace GUIEngine
|
||||
class BubbleWidget;
|
||||
enum EventPropagation;
|
||||
}
|
||||
namespace Online
|
||||
{
|
||||
class User;
|
||||
}
|
||||
class InputDevice;
|
||||
class PlayerKartWidget;
|
||||
class KartHoverListener;
|
||||
@ -66,7 +70,7 @@ protected:
|
||||
|
||||
bool m_must_delete_on_back; //!< To delete the screen if back is pressed
|
||||
|
||||
KartSelectionScreen();
|
||||
KartSelectionScreen(const char* filename);
|
||||
|
||||
/** Stores whether any player confirmed their choice; then, some things
|
||||
* are "frozen", for instance the selected kart group tab
|
||||
@ -99,7 +103,11 @@ protected:
|
||||
/** Fill the ribbon with the karts from the currently selected group */
|
||||
void setKartsFromCurrentGroup();
|
||||
|
||||
void playerConfirm(const int playerID);
|
||||
virtual void playerConfirm(const int playerID);
|
||||
/** updates model of a kart widget, to have the good selection when the user validates */
|
||||
void updateKartWidgetModel(uint8_t widget_id,
|
||||
const std::string& selection,
|
||||
const irr::core::stringw& selectionText);
|
||||
|
||||
/** Stores a pointer to the current selection screen */
|
||||
static KartSelectionScreen* m_instance_ptr;
|
||||
@ -234,8 +242,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::Profile* 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 +276,7 @@ public:
|
||||
|
||||
PlayerKartWidget(KartSelectionScreen* parent,
|
||||
StateManager::ActivePlayer* associatedPlayer,
|
||||
Online::Profile* associatedUser,
|
||||
core::recti area, const int playerID,
|
||||
std::string kartGroup,
|
||||
const int irrlichtWidgetID=-1);
|
||||
|
@ -279,7 +279,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
}
|
||||
else if (selection == "multiplayer")
|
||||
{
|
||||
KartSelectionScreen* s = NetworkKartSelectionScreen::getInstance();
|
||||
KartSelectionScreen* s = OfflineKartSelectionScreen::getInstance();
|
||||
s->setMultiplayer(true);
|
||||
s->setFromOverworld(false);
|
||||
StateManager::get()->pushScreen( s );
|
||||
|
@ -1,14 +1,24 @@
|
||||
#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 );
|
||||
|
||||
NetworkKartSelectionScreen::NetworkKartSelectionScreen() : KartSelectionScreen()
|
||||
NetworkKartSelectionScreen::NetworkKartSelectionScreen() : KartSelectionScreen("karts_online.stkgui")
|
||||
{
|
||||
KartSelectionScreen::m_instance_ptr = this;
|
||||
}
|
||||
@ -24,16 +34,122 @@ 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");
|
||||
back_button->setImage("gui/main_quit.png");
|
||||
|
||||
m_multiplayer = false;
|
||||
|
||||
// add a widget for each player except self (already exists):
|
||||
GameSetup* setup = NetworkManager::getInstance()->getGameSetup();
|
||||
if (!setup)
|
||||
{
|
||||
Log::error("NetworkKartSelectionScreen", "No network game setup registered.");
|
||||
return;
|
||||
}
|
||||
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");
|
||||
// start at the rightmost of the screen
|
||||
const int shift = irr_driver->getFrameSize().Width;
|
||||
core::recti kartsArea(kartsAreaWidget->m_x + shift,
|
||||
kartsAreaWidget->m_y,
|
||||
kartsAreaWidget->m_x + shift + kartsAreaWidget->m_w,
|
||||
kartsAreaWidget->m_y + kartsAreaWidget->m_h);
|
||||
|
||||
for (unsigned int i = 0; i < players.size(); i++)
|
||||
{
|
||||
if (players[i]->user_profile == Online::CurrentUser::get()->getProfile())
|
||||
{
|
||||
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 = NULL; // player is remote
|
||||
|
||||
std::string selected_kart_group = "standard"; // standard group
|
||||
|
||||
PlayerKartWidget* newPlayerWidget =
|
||||
new PlayerKartWidget(this, aplayer, players[i]->user_profile, kartsArea, m_kart_widgets.size(),
|
||||
selected_kart_group);
|
||||
|
||||
manualAddWidget(newPlayerWidget);
|
||||
m_kart_widgets.push_back(newPlayerWidget);
|
||||
|
||||
newPlayerWidget->add();
|
||||
}
|
||||
|
||||
const int amount = m_kart_widgets.size();
|
||||
Widget* fullarea = getWidget("playerskarts");
|
||||
|
||||
const int splitWidth = fullarea->m_w / amount;
|
||||
|
||||
for (int n=0; n<amount; n++)
|
||||
{
|
||||
m_kart_widgets[n].move( fullarea->m_x + splitWidth*n,
|
||||
fullarea->m_y, splitWidth, fullarea->m_h);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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::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());
|
||||
|
||||
KartSelectionScreen::updateKartWidgetModel(widget_id, kart_name, irr::core::stringw(kart_name.c_str()));
|
||||
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
|
||||
*/
|
||||
@ -42,7 +158,7 @@ void NetworkKartSelectionScreen::eventCallback(GUIEngine::Widget* widget, const
|
||||
{
|
||||
if (name == "karts")
|
||||
{
|
||||
|
||||
KartSelectionScreen::eventCallback(widget, name, playerID);
|
||||
}
|
||||
else if (name == "back")
|
||||
{
|
||||
|
@ -8,15 +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
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
DEFINE_SCREEN_SINGLETON( OfflineKartSelectionScreen );
|
||||
|
||||
OfflineKartSelectionScreen::OfflineKartSelectionScreen() : KartSelectionScreen()
|
||||
OfflineKartSelectionScreen::OfflineKartSelectionScreen() : KartSelectionScreen("karts.stkgui")
|
||||
{
|
||||
KartSelectionScreen::m_instance_ptr = this;
|
||||
}
|
||||
|
@ -46,6 +46,9 @@
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
|
||||
|
||||
using namespace GUIEngine;
|
||||
using namespace Online;
|
||||
|
@ -40,7 +40,11 @@
|
||||
#include "race/highscores.hpp"
|
||||
#include "states_screens/feature_unlocked.hpp"
|
||||
#include "states_screens/main_menu_screen.hpp"
|
||||
#include "states_screens/networking_lobby.hpp"
|
||||
#include "states_screens/network_kart_selection.hpp"
|
||||
#include "states_screens/online_screen.hpp"
|
||||
#include "states_screens/race_setup_screen.hpp"
|
||||
#include "states_screens/server_selection.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
@ -104,6 +108,25 @@ void RaceResultGUI::enableAllButtons()
|
||||
enableGPProgress();
|
||||
}
|
||||
|
||||
// If we're in a network world, change the buttons text
|
||||
if (World::getWorld()->isNetworkWorld())
|
||||
{
|
||||
Log::info("This work was networked", "This is a network world.");
|
||||
top->setVisible(false);
|
||||
middle->setText( _("Continue.") );
|
||||
middle->setVisible(true);
|
||||
middle->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
bottom->setText( _("Quit the server.") );
|
||||
bottom->setVisible(true);
|
||||
if (race_manager->getMajorMode()==RaceManager::MAJOR_MODE_GRAND_PRIX)
|
||||
{
|
||||
middle->setVisible(false); // you have to wait the server to start again
|
||||
bottom->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Log::info("This work was NOT networked", "This is NOT a network world.");
|
||||
|
||||
// If something was unlocked
|
||||
// -------------------------
|
||||
int n = unlock_manager->getCurrentSlot()->getRecentlyCompletedChallenges().size();
|
||||
@ -223,6 +246,30 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// If we're playing online :
|
||||
if (World::getWorld()->isNetworkWorld())
|
||||
{
|
||||
StateManager::get()->popMenu();
|
||||
if (name == "middle") // Continue button (return to server lobby)
|
||||
{
|
||||
race_manager->exitRace();
|
||||
race_manager->setAIKartOverride("");
|
||||
Screen* newStack[] = {MainMenuScreen::getInstance(),
|
||||
OnlineScreen::getInstance(),
|
||||
ServerSelection::getInstance(),
|
||||
NetworkingLobby::getInstance(),
|
||||
NULL};
|
||||
StateManager::get()->resetAndSetStack( newStack );
|
||||
}
|
||||
if (name == "bottom") // Quit server (return to main menu)
|
||||
{
|
||||
race_manager->exitRace();
|
||||
race_manager->setAIKartOverride("");
|
||||
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Next check for GP
|
||||
// -----------------
|
||||
if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX)
|
||||
@ -254,6 +301,7 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
{
|
||||
race_manager->exitRace();
|
||||
race_manager->setAIKartOverride("");
|
||||
NetworkKartSelectionScreen::getInstance()->tearDown(); // be sure to delete the kart selection screen
|
||||
Screen* newStack[] = {MainMenuScreen::getInstance(),
|
||||
RaceSetupScreen::getInstance(),
|
||||
NULL};
|
||||
@ -267,6 +315,7 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
{
|
||||
race_manager->exitRace();
|
||||
race_manager->setAIKartOverride("");
|
||||
NetworkKartSelectionScreen::getInstance()->tearDown(); // be sure to delete the kart selection screen
|
||||
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
|
||||
|
||||
if (race_manager->raceWasStartedFromOverworld())
|
||||
|
@ -1197,7 +1197,7 @@ bool Track::loadMainTrack(const XMLNode &root)
|
||||
convertTrackToBullet(m_all_nodes[i]);
|
||||
}
|
||||
|
||||
// Now convert all objects that are only used for the physics
|
||||
// Now convert all objects that are only used for the physics
|
||||
// (like invisible walls).
|
||||
for(unsigned int i=0; i<m_all_physics_only_nodes.size(); i++)
|
||||
{
|
||||
@ -1317,7 +1317,7 @@ void Track::createWater(const XMLNode &node)
|
||||
// A speed of 0 results in a division by zero, so avoid this.
|
||||
// The actual time for a wave from one maximum to the next is
|
||||
// given by 2*M_PI*speed/1000.
|
||||
Log::warn("Track",
|
||||
Log::warn("Track",
|
||||
"Wave-speed or time is 0, resetting it to the default.");
|
||||
wave_speed =300.0f;
|
||||
}
|
||||
@ -2125,7 +2125,7 @@ bool Track::findGround(AbstractKart *kart)
|
||||
// Material and hit point are not needed;
|
||||
const Material *m;
|
||||
Vec3 hit_point, normal;
|
||||
bool over_ground = m_track_mesh->castRay(kart->getXYZ(), to, &hit_point,
|
||||
bool over_ground = m_track_mesh->castRay(kart->getXYZ(), to, &hit_point,
|
||||
&m, &normal);
|
||||
const Vec3 &xyz = kart->getXYZ();
|
||||
if(!over_ground || !m)
|
||||
@ -2149,7 +2149,7 @@ bool Track::findGround(AbstractKart *kart)
|
||||
// too long.
|
||||
if(xyz.getY() - hit_point.getY() > 5)
|
||||
{
|
||||
Log::warn("physics",
|
||||
Log::warn("physics",
|
||||
"Kart at (%f %f %f) is too high above ground at (%f %f %f)",
|
||||
xyz.getX(),xyz.getY(),xyz.getZ(),
|
||||
hit_point.getX(),hit_point.getY(),hit_point.getZ());
|
||||
|
@ -28,6 +28,7 @@
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user