Merge branch 'master' of github.com:supertuxkart/stk-code
This commit is contained in:
commit
42d21ba9f9
@ -23,10 +23,13 @@
|
||||
<buttonbar id="menu_toprow" proportion="3" width="90%" align="center">
|
||||
<icon-button id="lan" width="128" height="128"
|
||||
icon="gui/menu_multi.png" focus_icon="gui/menu_multi_focus.png"
|
||||
I18N="Networking menu button" text="Local Networking"/>
|
||||
I18N="Networking menu button" text="Local networking"/>
|
||||
<icon-button id="wan" width="128" height="128"
|
||||
icon="gui/menu_multi.png" focus_icon="gui/menu_multi_focus.png"
|
||||
I18N="Networking menu button" text="Global Networking"/>
|
||||
I18N="Networking menu button" text="Global networking"/>
|
||||
<icon-button id="enter-address" width="128" height="128"
|
||||
icon="gui/online/menu_quick_play.png" focus_icon="gui/online/menu_quick_play_hover.png"
|
||||
I18N="Networking menu button" text="Enter server address"/>
|
||||
<icon-button id="online" width="128" height="128"
|
||||
icon="gui/menu_online.png" focus_icon="gui/menu_online_focus.png"
|
||||
I18N="Networking menu button" text="Your profile"/>
|
||||
|
@ -9,6 +9,10 @@
|
||||
Older versions will be ignored. -->
|
||||
<track-version min="6" max="7"/>
|
||||
|
||||
<!-- Minimum and maxium server versions that be be read by this binary.
|
||||
Older versions will be ignored. -->
|
||||
<server-version min="1" max="1"/>
|
||||
|
||||
<!-- Maximum number of karts to be used at the same time. This limit
|
||||
can easily be increased, but some tracks might not have valid start
|
||||
positions for those additional karts. -->
|
||||
|
@ -141,6 +141,8 @@ void STKConfig::load(const std::string &filename)
|
||||
CHECK_NEG(m_max_kart_version, "<kart-version max=...>" );
|
||||
CHECK_NEG(m_min_track_version, "min-track-version" );
|
||||
CHECK_NEG(m_max_track_version, "max-track-version" );
|
||||
CHECK_NEG(m_min_server_version, "min-server-version" );
|
||||
CHECK_NEG(m_max_server_version, "max-server-version" );
|
||||
CHECK_NEG(m_skid_fadeout_time, "skid-fadeout-time" );
|
||||
CHECK_NEG(m_near_ground, "near-ground" );
|
||||
CHECK_NEG(m_delay_finish_time, "delay-finish-time" );
|
||||
@ -187,6 +189,8 @@ void STKConfig::init_defaults()
|
||||
m_max_kart_version = -100;
|
||||
m_min_track_version = -100;
|
||||
m_max_track_version = -100;
|
||||
m_min_server_version = -100;
|
||||
m_max_server_version = -100;
|
||||
m_max_display_news = -100;
|
||||
m_replay_max_time = -100;
|
||||
m_replay_delta_angle = -100;
|
||||
@ -233,6 +237,12 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
node->get("max", &m_max_track_version);
|
||||
}
|
||||
|
||||
if(const XMLNode *node = root->getNode("server-version"))
|
||||
{
|
||||
node->get("min", &m_min_server_version);
|
||||
node->get("max", &m_max_server_version);
|
||||
}
|
||||
|
||||
if(const XMLNode *kart_node = root->getNode("karts"))
|
||||
kart_node->get("max-number", &m_max_karts);
|
||||
|
||||
|
@ -117,6 +117,8 @@ public:
|
||||
m_max_kart_version; /**<version supported by this binary. */
|
||||
int m_min_track_version, /**<The minimum and maximum .track file */
|
||||
m_max_track_version; /**<version supported by this binary. */
|
||||
int m_min_server_version, /**<The minimum and maximum server */
|
||||
m_max_server_version; /**<version supported by this binary. */
|
||||
int m_max_display_news; /**<How often a news message is displayed
|
||||
before it is ignored. */
|
||||
|
||||
|
@ -708,7 +708,7 @@ namespace UserConfigParams
|
||||
PARAM_DEFAULT(BoolUserConfigParam(false, "log-network-packets",
|
||||
&m_network_group, "If all network packets should be logged"));
|
||||
PARAM_PREFIX BoolUserConfigParam m_random_ports
|
||||
PARAM_DEFAULT(BoolUserConfigParam(true, "randrom-ports",
|
||||
PARAM_DEFAULT(BoolUserConfigParam(true, "random-ports",
|
||||
&m_network_group, "Use random ports for client and server connection"));
|
||||
PARAM_PREFIX BoolUserConfigParam m_lobby_chat
|
||||
PARAM_DEFAULT(BoolUserConfigParam(false, "lobby-chat",
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "graphics/sp/sp_per_object_uniform.hpp"
|
||||
#include "graphics/sp/sp_shader_manager.hpp"
|
||||
#include "graphics/sp/sp_uniform_assigner.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "utils/mini_glm.hpp"
|
||||
|
||||
@ -75,7 +76,7 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
video::SColor* custom_color)
|
||||
{
|
||||
//if the kart is gnu, then don't skid because he floats!
|
||||
if(m_kart.isWheeless())
|
||||
if (m_kart.isWheeless() || RewindManager::get()->isRewinding())
|
||||
return;
|
||||
|
||||
float f = dt / stk_config->m_skid_fadeout_time;
|
||||
|
@ -137,7 +137,14 @@ public:
|
||||
return m_texture_trans;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void setUpdateOffset(int offset) { m_update_offset = offset; }
|
||||
void setUpdateOffset(int offset)
|
||||
{
|
||||
// Avoid skipping of vertex buffer update if this function is called
|
||||
// more than once per frame
|
||||
if (m_update_offset != -1 && offset > m_update_offset)
|
||||
return;
|
||||
m_update_offset = offset;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
bool isVisible() const { return m_visible; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -37,6 +37,7 @@ const std::map<std::string, std::pair<unsigned, SamplerType> >
|
||||
{ "skinning_tex", { 0, ST_TEXTURE_BUFFER } }
|
||||
#endif
|
||||
};
|
||||
bool SPShader::m_sp_shader_debug = false;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void SPShader::addShaderFile(const std::string& name, GLint shader_type,
|
||||
@ -226,20 +227,20 @@ void SPShader::addAllUniforms(RenderPass rp)
|
||||
GLenum type;
|
||||
char name[100] = {};
|
||||
glGetActiveUniform(m_program[rp], i, 99, NULL, &size, &type, name);
|
||||
if (size != 1)
|
||||
if (size != 1 && m_sp_shader_debug)
|
||||
{
|
||||
Log::debug("SPShader", "Array of uniforms is not supported in"
|
||||
" shader %s for %s.", m_name.c_str(), name);
|
||||
continue;
|
||||
}
|
||||
auto ret = supported_types.find(type);
|
||||
if (ret == supported_types.end())
|
||||
if (ret == supported_types.end() && m_sp_shader_debug)
|
||||
{
|
||||
Log::debug("SPShader", "%d type not supported", (unsigned)type);
|
||||
continue;
|
||||
}
|
||||
GLuint location = glGetUniformLocation(m_program[rp], name);
|
||||
if (location == GL_INVALID_INDEX)
|
||||
if (location == GL_INVALID_INDEX && m_sp_shader_debug)
|
||||
{
|
||||
Log::debug("SPShader", "%s uniform not found", name);
|
||||
continue;
|
||||
|
@ -111,6 +111,8 @@ private:
|
||||
const std::array<bool, 6> m_srgb;
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
static bool m_sp_shader_debug;
|
||||
// ------------------------------------------------------------------------
|
||||
SPShader(const std::string& name,
|
||||
const std::function<void(SPShader*)>& init_func,
|
||||
|
@ -52,7 +52,7 @@ void AbstractStateManager::enterGameState()
|
||||
|
||||
if (getCurrentScreen() != NULL) getCurrentScreen()->tearDown();
|
||||
m_menu_stack.clear();
|
||||
m_menu_stack.push_back(RACE_STATE_NAME);
|
||||
m_menu_stack.emplace_back(RACE_STATE_NAME, (Screen*)NULL);
|
||||
setGameState(GAME);
|
||||
GUIEngine::cleanForGame();
|
||||
} // enterGameState
|
||||
@ -83,7 +83,7 @@ void AbstractStateManager::setGameState(GameState state)
|
||||
#pragma mark Push/pop menus
|
||||
#endif
|
||||
|
||||
void AbstractStateManager::pushMenu(std::string name)
|
||||
void AbstractStateManager::pushMenu(Screen* screen)
|
||||
{
|
||||
// currently, only a single in-game menu is supported
|
||||
assert(m_game_mode != INGAME_MENU);
|
||||
@ -94,14 +94,14 @@ void AbstractStateManager::pushMenu(std::string name)
|
||||
if (UserConfigParams::logGUI())
|
||||
{
|
||||
Log::info("AbstractStateManager::pushMenu", "Switching to screen %s",
|
||||
name.c_str());
|
||||
screen->getName().c_str());
|
||||
}
|
||||
|
||||
// Send tear-down event to previous menu
|
||||
if (m_menu_stack.size() > 0 && m_game_mode != GAME)
|
||||
getCurrentScreen()->tearDown();
|
||||
|
||||
m_menu_stack.push_back(name);
|
||||
m_menu_stack.emplace_back(screen->getName(), screen);
|
||||
if (m_game_mode == GAME)
|
||||
{
|
||||
setGameState(INGAME_MENU);
|
||||
@ -110,7 +110,7 @@ void AbstractStateManager::pushMenu(std::string name)
|
||||
{
|
||||
setGameState(MENU);
|
||||
}
|
||||
switchToScreen(name.c_str());
|
||||
switchToScreen(screen);
|
||||
|
||||
onTopMostScreenChanged();
|
||||
} // pushMenu
|
||||
@ -130,7 +130,7 @@ void AbstractStateManager::pushScreen(Screen* screen)
|
||||
}
|
||||
|
||||
if (!screen->isLoaded()) screen->loadFromFile();
|
||||
pushMenu(screen->getName());
|
||||
pushMenu(screen);
|
||||
screen->init();
|
||||
|
||||
onTopMostScreenChanged();
|
||||
@ -162,9 +162,9 @@ void AbstractStateManager::replaceTopMostScreen(Screen* screen, GUIEngine::GameS
|
||||
if (getCurrentScreen() != NULL)
|
||||
getCurrentScreen()->tearDown();
|
||||
|
||||
m_menu_stack[m_menu_stack.size()-1] = name;
|
||||
m_menu_stack[m_menu_stack.size()-1] = std::make_pair(name, screen);
|
||||
setGameState(gameState);
|
||||
switchToScreen(name.c_str());
|
||||
switchToScreen(screen);
|
||||
|
||||
// Send init event to new menu
|
||||
getCurrentScreen()->init();
|
||||
@ -187,7 +187,7 @@ void AbstractStateManager::reshowTopMostMenu()
|
||||
if (currScreen != NULL) getCurrentScreen()->tearDown();
|
||||
}
|
||||
|
||||
switchToScreen( m_menu_stack[m_menu_stack.size()-1].c_str() );
|
||||
switchToScreen(m_menu_stack[m_menu_stack.size()-1].second);
|
||||
|
||||
// Send init event to new menu
|
||||
Screen* screen = getCurrentScreen();
|
||||
@ -216,10 +216,10 @@ void AbstractStateManager::popMenu()
|
||||
if (UserConfigParams::logGUI())
|
||||
{
|
||||
Log::info("AbstractStateManager::popMenu", "Switching to screen %s",
|
||||
m_menu_stack[m_menu_stack.size()-1].c_str());
|
||||
m_menu_stack[m_menu_stack.size()-1].first.c_str());
|
||||
}
|
||||
|
||||
if (m_menu_stack[m_menu_stack.size()-1] == RACE_STATE_NAME)
|
||||
if (m_menu_stack[m_menu_stack.size()-1].first == RACE_STATE_NAME)
|
||||
{
|
||||
setGameState(GAME);
|
||||
GUIEngine::cleanForGame();
|
||||
@ -227,7 +227,7 @@ void AbstractStateManager::popMenu()
|
||||
else
|
||||
{
|
||||
setGameState(MENU);
|
||||
switchToScreen(m_menu_stack[m_menu_stack.size()-1].c_str());
|
||||
switchToScreen(m_menu_stack[m_menu_stack.size()-1].second);
|
||||
|
||||
Screen* screen = getCurrentScreen();
|
||||
if (!screen->isLoaded()) screen->loadFromFile();
|
||||
@ -254,10 +254,10 @@ void AbstractStateManager::resetAndGoToScreen(Screen* screen)
|
||||
m_menu_stack.clear();
|
||||
|
||||
if (!screen->isLoaded()) screen->loadFromFile();
|
||||
m_menu_stack.push_back(name);
|
||||
m_menu_stack.emplace_back(name, screen);
|
||||
setGameState(MENU);
|
||||
|
||||
switchToScreen(name.c_str());
|
||||
switchToScreen(screen);
|
||||
getCurrentScreen()->init();
|
||||
|
||||
onTopMostScreenChanged();
|
||||
@ -277,12 +277,12 @@ void AbstractStateManager::resetAndSetStack(Screen* screens[])
|
||||
|
||||
for (int n=0; screens[n] != NULL; n++)
|
||||
{
|
||||
m_menu_stack.push_back(screens[n]->getName());
|
||||
m_menu_stack.emplace_back(screens[n]->getName(), screens[n]);
|
||||
}
|
||||
|
||||
setGameState(MENU);
|
||||
|
||||
switchToScreen(m_menu_stack[m_menu_stack.size()-1].c_str());
|
||||
switchToScreen(m_menu_stack[m_menu_stack.size()-1].second);
|
||||
getCurrentScreen()->init();
|
||||
|
||||
onTopMostScreenChanged();
|
||||
|
@ -59,11 +59,11 @@ namespace GUIEngine
|
||||
|
||||
/**
|
||||
* This stack will contain menu names (e.g. main.stkgui),
|
||||
* and/or 'race'.
|
||||
* and/or 'race' with screen instance pointer.
|
||||
*/
|
||||
std::vector<std::string> m_menu_stack;
|
||||
std::vector<std::pair<std::string, Screen*> > m_menu_stack;
|
||||
|
||||
void pushMenu(std::string name);
|
||||
void pushMenu(Screen* screen);
|
||||
|
||||
void setGameState(GameState state);
|
||||
|
||||
@ -133,10 +133,10 @@ namespace GUIEngine
|
||||
|
||||
T* instance = T::getInstance();
|
||||
|
||||
m_menu_stack.push_back(instance->getName());
|
||||
m_menu_stack.emplace_back(instance->getName(), instance);
|
||||
setGameState(MENU);
|
||||
|
||||
switchToScreen(instance->getName().c_str());
|
||||
switchToScreen(instance);
|
||||
getCurrentScreen()->init();
|
||||
|
||||
onTopMostScreenChanged();
|
||||
|
@ -882,7 +882,7 @@ namespace GUIEngine
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
void switchToScreen(const char* screen_name)
|
||||
void switchToScreen(Screen* screen)
|
||||
{
|
||||
needsUpdate.clearWithoutDeleting();
|
||||
|
||||
@ -893,12 +893,12 @@ namespace GUIEngine
|
||||
Widget::resetIDCounters();
|
||||
|
||||
// check if we already loaded this screen
|
||||
const int screen_amount = g_loaded_screens.size();
|
||||
for(int n=0; n<screen_amount; n++)
|
||||
Screen* loaded_screen;
|
||||
for_in (loaded_screen, g_loaded_screens)
|
||||
{
|
||||
if (g_loaded_screens[n].getName() == screen_name)
|
||||
if (loaded_screen == screen)
|
||||
{
|
||||
g_current_screen = g_loaded_screens.get(n);
|
||||
g_current_screen = loaded_screen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -925,20 +925,21 @@ namespace GUIEngine
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
void removeScreen(const char* name)
|
||||
void removeScreen(Screen* screen)
|
||||
{
|
||||
const int screen_amount = g_loaded_screens.size();
|
||||
for(int n=0; n<screen_amount; n++)
|
||||
int n = 0;
|
||||
Screen* loaded_screen;
|
||||
for_in (loaded_screen, g_loaded_screens)
|
||||
{
|
||||
if (g_loaded_screens[n].getName() == name)
|
||||
if (loaded_screen == screen)
|
||||
{
|
||||
g_current_screen = g_loaded_screens.get(n);
|
||||
g_current_screen->unload();
|
||||
delete g_current_screen;
|
||||
screen->unload();
|
||||
delete screen;
|
||||
g_current_screen = NULL;
|
||||
g_loaded_screens.remove(n);
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,12 +199,12 @@ namespace GUIEngine
|
||||
/** \brief Add a screen to the list of screens known by the gui engine */
|
||||
void addScreenToList(Screen* screen);
|
||||
/** \brief Remove a screen from the list of screens known by the gui engine */
|
||||
void removeScreen(const char* name);
|
||||
void removeScreen(Screen* screen);
|
||||
|
||||
/** \brief Low-level mean to change current screen.
|
||||
* \note Do not use directly. Use a state manager instead to get higher-level functionnality.
|
||||
*/
|
||||
void switchToScreen(const char* );
|
||||
void switchToScreen(Screen* screen);
|
||||
|
||||
/** \brief erases the currently displayed screen, removing all added irrLicht widgets
|
||||
* \note Do not use directly. Use a state manager instead to get higher-level functionnality.
|
||||
|
@ -269,13 +269,7 @@ void Attachment::saveState(BareNetworkString *buffer) const
|
||||
void Attachment::rewindTo(BareNetworkString *buffer)
|
||||
{
|
||||
uint8_t type = buffer->getUInt8();
|
||||
|
||||
AttachmentType new_type = AttachmentType(type & 0x7f); // mask out bit 7
|
||||
// FIXME Sometimes type == 255 is returned, reason unknown
|
||||
if (new_type > ATTACH_NOTHING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is no attachment, clear the attachment if necessary and exit
|
||||
if(new_type==ATTACH_NOTHING)
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/controller/ai_properties.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
@ -328,3 +329,18 @@ void AIBaseController::determineTurnRadius(const Vec3 &end, Vec3 *center,
|
||||
}
|
||||
|
||||
} // determineTurnRadius
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void AIBaseController::saveState(BareNetworkString *buffer) const
|
||||
{
|
||||
// Endcontroller needs this for proper offset in kart rewinder
|
||||
buffer->addUInt32(0).addUInt32(0).addUInt32(0);
|
||||
} // copyToBuffer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void AIBaseController::rewindTo(BareNetworkString *buffer)
|
||||
{
|
||||
// Endcontroller needs this for proper offset in kart rewinder
|
||||
// Skip 3 uint32_t
|
||||
buffer->skip(3 * 4);
|
||||
} // rewindTo
|
||||
|
@ -104,9 +104,8 @@ public:
|
||||
};
|
||||
virtual void skidBonusTriggered() {};
|
||||
// ------------------------------------------------------------------------
|
||||
/** Not used for AIs. */
|
||||
virtual void saveState(BareNetworkString *buffer) const OVERRIDE {}
|
||||
virtual void rewindTo(BareNetworkString *buffer) OVERRIDE {}
|
||||
virtual void saveState(BareNetworkString *buffer) const OVERRIDE;
|
||||
virtual void rewindTo(BareNetworkString *buffer) OVERRIDE;
|
||||
|
||||
}; // AIBaseController
|
||||
|
||||
|
@ -161,10 +161,11 @@ bool LocalPlayerController::action(PlayerAction action, int value,
|
||||
NetworkConfig::get()->isClient() &&
|
||||
!RewindManager::get()->isRewinding() )
|
||||
{
|
||||
GameProtocol::lock()
|
||||
->controllerAction(m_kart->getWorldKartId(),
|
||||
action, value,
|
||||
m_steer_val_l, m_steer_val_r);
|
||||
if (auto gp = GameProtocol::lock())
|
||||
{
|
||||
gp->controllerAction(m_kart->getWorldKartId(), action, value,
|
||||
m_steer_val_l, m_steer_val_r);
|
||||
}
|
||||
}
|
||||
return PlayerController::action(action, value, /*dry_run*/false);
|
||||
} // action
|
||||
@ -383,3 +384,11 @@ bool LocalPlayerController::canGetAchievements() const
|
||||
{
|
||||
return m_player->getConstProfile() == PlayerManager::getCurrentPlayer();
|
||||
} // canGetAchievements
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
core::stringw LocalPlayerController::getName() const
|
||||
{
|
||||
if (NetworkConfig::get()->isNetworking())
|
||||
return PlayerController::getName();
|
||||
return m_player->getProfile()->getName();
|
||||
} // getName
|
||||
|
@ -78,7 +78,7 @@ public:
|
||||
virtual bool isLocalPlayerController() const OVERRIDE {return true;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the name of the player profile. */
|
||||
core::stringw getName() const OVERRIDE { return m_player->getProfile()->getName(); }
|
||||
core::stringw getName() const OVERRIDE;
|
||||
|
||||
|
||||
}; // LocalPlayerController
|
||||
|
@ -29,6 +29,10 @@
|
||||
#include "karts/skidding.hpp"
|
||||
#include "karts/rescue_animation.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "network/protocols/lobby_protocol.hpp"
|
||||
#include "race/history.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
@ -384,4 +388,17 @@ void PlayerController::rewindTo(BareNetworkString *buffer)
|
||||
m_steer_val = buffer->getUInt32();
|
||||
m_steer_val_l = buffer->getUInt32();
|
||||
m_steer_val_r = buffer->getUInt32();
|
||||
} // rewindTo
|
||||
} // rewindTo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
core::stringw PlayerController::getName() const
|
||||
{
|
||||
if (NetworkConfig::get()->isNetworking())
|
||||
{
|
||||
auto& players = LobbyProtocol::get<LobbyProtocol>()->getGameSetup()
|
||||
->getPlayers();
|
||||
if (auto player = players.at(m_kart->getWorldKartId()).lock())
|
||||
return player->getName();
|
||||
}
|
||||
return m_kart->getName();
|
||||
} // getName
|
||||
|
@ -93,6 +93,9 @@ public:
|
||||
virtual void finishedRace(float time) OVERRIDE
|
||||
{
|
||||
} // finishedRace
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the name of the player profile. */
|
||||
core::stringw getName() const OVERRIDE;
|
||||
|
||||
}; // class PlayerController
|
||||
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include "modes/soccer_world.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "physics/btKartRaycast.hpp"
|
||||
@ -910,23 +911,23 @@ void Kart::finishedRace(float time, bool from_server)
|
||||
// because the race was over (i.e. estimating the finish time). If
|
||||
// this kart then crosses the finish line (with the end controller)
|
||||
// it would trigger a race end again.
|
||||
if(m_finished_race) return;
|
||||
if (m_finished_race) return;
|
||||
|
||||
/* if(!from_server)
|
||||
if (NetworkConfig::get()->isNetworking() && !from_server)
|
||||
{
|
||||
if(NetworkConfig::get()->isServer())
|
||||
if (NetworkConfig::get()->isServer())
|
||||
{
|
||||
RaceEventManager::getInstance()->kartFinishedRace(this, time);
|
||||
} // isServer
|
||||
|
||||
// Ignore local detection of a kart finishing a race in a
|
||||
// network game.
|
||||
else if(NetworkConfig::get()->isClient())
|
||||
else if (NetworkConfig::get()->isClient())
|
||||
{
|
||||
return;
|
||||
}
|
||||
} // !from_server
|
||||
*/
|
||||
|
||||
m_finished_race = true;
|
||||
m_finish_time = time;
|
||||
m_controller->finishedRace(time);
|
||||
@ -967,7 +968,7 @@ void Kart::finishedRace(float time, bool from_server)
|
||||
{
|
||||
// Save for music handling in race result gui
|
||||
setRaceResult();
|
||||
if(!isGhostKart())
|
||||
if (!isGhostKart())
|
||||
{
|
||||
setController(new EndController(this, m_controller));
|
||||
}
|
||||
@ -998,15 +999,17 @@ void Kart::setRaceResult()
|
||||
else
|
||||
m_race_result = false;
|
||||
}
|
||||
else if (this->getPosition() <= 0.5f*race_manager->getNumberOfKarts() ||
|
||||
this->getPosition() == 1)
|
||||
else if (this->getPosition() <= 0.5f *
|
||||
World::getWorld()->getCurrentNumKarts() ||
|
||||
this->getPosition() == 1)
|
||||
m_race_result = true;
|
||||
else
|
||||
m_race_result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->getPosition() <= 0.5f*race_manager->getNumberOfKarts() ||
|
||||
if (this->getPosition() <= 0.5f *
|
||||
World::getWorld()->getCurrentNumKarts() ||
|
||||
this->getPosition() == 1)
|
||||
m_race_result = true;
|
||||
else
|
||||
|
@ -172,7 +172,7 @@ protected:
|
||||
|
||||
/** True if fire button was pushed and not released */
|
||||
bool m_fire_clicked;
|
||||
|
||||
|
||||
/** True if the kart has been selected to have a boosted ai */
|
||||
bool m_boosted_ai;
|
||||
|
||||
@ -486,11 +486,9 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the position 0.25s before */
|
||||
virtual const Vec3& getPreviousXYZ() const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a more recent different previous position */
|
||||
virtual const Vec3& getRecentPreviousXYZ() const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** For debugging only: check if a kart is flying. */
|
||||
bool isFlying() const { return m_flying; }
|
||||
|
99
src/main.cpp
99
src/main.cpp
@ -191,6 +191,7 @@
|
||||
#include "graphics/particle_kind_manager.hpp"
|
||||
#include "graphics/referee.hpp"
|
||||
#include "graphics/sp/sp_base.hpp"
|
||||
#include "graphics/sp/sp_shader.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/event_handler.hpp"
|
||||
#include "guiengine/dialog_queue.hpp"
|
||||
@ -210,6 +211,9 @@
|
||||
#include "modes/cutscene_world.hpp"
|
||||
#include "modes/demo_world.hpp"
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "network/protocols/client_lobby.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
@ -569,6 +573,7 @@ void cmdLineHelp()
|
||||
" --unlock-all Permanently unlock all karts and tracks for testing.\n"
|
||||
" --no-unlock-all Disable unlock-all (i.e. base unlocking on player achievement).\n"
|
||||
" --no-graphics Do not display the actual race.\n"
|
||||
" --sp-shader-debug Enables debug in sp shader, it will print all unavailable uniforms.\n"
|
||||
" --demo-mode=t Enables demo mode after t seconds of idle time in "
|
||||
"main menu.\n"
|
||||
" --demo-tracks=t1,t2 List of tracks to be used in demo mode. No\n"
|
||||
@ -586,7 +591,7 @@ void cmdLineHelp()
|
||||
" --server-password= Sets a password for a server (both client&server).\n"
|
||||
" --connect-now=ip Connect to a server with IP known now\n"
|
||||
" (in format x.x.x.x:xxx(port)), the port should be its\n"
|
||||
" private port.\n"
|
||||
" public port.\n"
|
||||
" --login=s Automatically log in (set the login).\n"
|
||||
" --password=s Automatically log in (set the password).\n"
|
||||
" --port=n Port number to use.\n"
|
||||
@ -729,10 +734,13 @@ int handleCmdLinePreliminary()
|
||||
if(CommandLine::has("--kartdir", &s))
|
||||
KartPropertiesManager::addKartSearchDir(s);
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if(CommandLine::has("--no-graphics") || CommandLine::has("-l"))
|
||||
{
|
||||
#endif
|
||||
ProfileWorld::disableGraphics();
|
||||
}
|
||||
|
||||
if (CommandLine::has("--sp-shader-debug"))
|
||||
SP::SPShader::m_sp_shader_debug = true;
|
||||
|
||||
if(CommandLine::has("--screensize", &s) || CommandLine::has("-s", &s))
|
||||
{
|
||||
@ -1012,7 +1020,6 @@ int handleCmdLine()
|
||||
}
|
||||
} // --type
|
||||
|
||||
|
||||
if (CommandLine::has("--login", &s))
|
||||
login = s.c_str();
|
||||
if (CommandLine::has("--password", &s))
|
||||
@ -1051,6 +1058,12 @@ int handleCmdLine()
|
||||
NetworkConfig::get()->setPassword(server_password);
|
||||
}
|
||||
|
||||
if (CommandLine::has("--motd", &s))
|
||||
{
|
||||
core::stringw motd = StringUtils::xmlDecode(s);
|
||||
NetworkConfig::get()->setMOTD(motd);
|
||||
}
|
||||
|
||||
if (CommandLine::has("--server-id-file", &s))
|
||||
{
|
||||
NetworkConfig::get()->setServerIdFile(
|
||||
@ -1074,21 +1087,36 @@ int handleCmdLine()
|
||||
}
|
||||
if (CommandLine::has("--connect-now", &s))
|
||||
{
|
||||
TransportAddress ip(s);
|
||||
NetworkConfig::get()->setIsLAN();
|
||||
TransportAddress server_addr(s);
|
||||
NetworkConfig::get()->setIsWAN();
|
||||
NetworkConfig::get()->setIsServer(false);
|
||||
Log::info("main", "Try to connect to server '%s'.",
|
||||
ip.toString().c_str() );
|
||||
irr::core::stringw name = StringUtils::utf8ToWide(ip.toString());
|
||||
auto server = std::make_shared<Server>(0, name,
|
||||
NetworkConfig::get()->getMaxPlayers(), 0,
|
||||
race_manager->getDifficulty(),
|
||||
NetworkConfig::get()->getServerGameMode(race_manager->getMinorMode(),
|
||||
race_manager->getMajorMode()), ip, !server_password.empty());
|
||||
NetworkingLobby::getInstance()->setJoinedServer(server);
|
||||
STKHost::create(server);
|
||||
auto server = std::make_shared<Server>(0, L"", 0, 0, 0, 0, server_addr,
|
||||
!server_password.empty());
|
||||
NetworkConfig::get()->addNetworkPlayer(
|
||||
input_manager->getDeviceManager()->getLatestUsedDevice(),
|
||||
PlayerManager::getCurrentPlayer(), false/*handicap*/);
|
||||
NetworkConfig::get()->doneAddingNetworkPlayers();
|
||||
STKHost::create();
|
||||
auto cts = std::make_shared<ConnectToServer>(server);
|
||||
cts->setup();
|
||||
Log::info("main", "Trying to connect to server '%s'.",
|
||||
server_addr.toString().c_str());
|
||||
if (!cts->handleDirectConnect(10000))
|
||||
{
|
||||
Log::error("main", "Timeout trying to connect to server '%s'.",
|
||||
server_addr.toString().c_str());
|
||||
STKHost::get()->shutdown();
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cl = LobbyProtocol::create<ClientLobby>();
|
||||
cl->setAddress(server_addr);
|
||||
cl->requestStart();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<LobbyProtocol> server_lobby;
|
||||
if (CommandLine::has("--wan-server", &s))
|
||||
{
|
||||
// Try to use saved user token if exists
|
||||
@ -1113,7 +1141,7 @@ int handleCmdLine()
|
||||
NetworkConfig::get()->setIsServer(true);
|
||||
NetworkConfig::get()->setIsWAN();
|
||||
NetworkConfig::get()->setIsPublicServer();
|
||||
STKHost::create();
|
||||
server_lobby = STKHost::create();
|
||||
Log::info("main", "Creating a WAN server '%s'.", s.c_str());
|
||||
}
|
||||
}
|
||||
@ -1122,7 +1150,7 @@ int handleCmdLine()
|
||||
NetworkConfig::get()->setServerName(StringUtils::xmlDecode(s));
|
||||
NetworkConfig::get()->setIsServer(true);
|
||||
NetworkConfig::get()->setIsLAN();
|
||||
STKHost::create();
|
||||
server_lobby = STKHost::create();
|
||||
Log::info("main", "Creating a LAN server '%s'.", s.c_str());
|
||||
}
|
||||
if (CommandLine::has("--auto-connect"))
|
||||
@ -1130,6 +1158,34 @@ int handleCmdLine()
|
||||
NetworkConfig::get()->setAutoConnect(true);
|
||||
}
|
||||
|
||||
if (CommandLine::has("--extra-server-info", &n))
|
||||
{
|
||||
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
|
||||
{
|
||||
LobbyProtocol::get<LobbyProtocol>()->getGameSetup()
|
||||
->setSoccerGoalTarget((bool)n);
|
||||
NetworkConfig::get()->setServerMode(
|
||||
race_manager->getMinorMode(),
|
||||
RaceManager::MAJOR_MODE_SINGLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LobbyProtocol::get<LobbyProtocol>()->getGameSetup()
|
||||
->setGrandPrixTrack(n);
|
||||
NetworkConfig::get()->setServerMode(
|
||||
race_manager->getMinorMode(),
|
||||
RaceManager::MAJOR_MODE_GRAND_PRIX);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkConfig::get()->setServerMode(
|
||||
race_manager->getMinorMode(), RaceManager::MAJOR_MODE_SINGLE);
|
||||
}
|
||||
// The extra server info has to be set before server lobby started
|
||||
if (server_lobby)
|
||||
server_lobby->requestStart();
|
||||
|
||||
/** Disable detection of LAN connection when connecting via WAN. This is
|
||||
* mostly a debugging feature to force using WAN connection. */
|
||||
if (CommandLine::has("--disable-lan"))
|
||||
@ -1919,11 +1975,16 @@ int main(int argc, char *argv[] )
|
||||
// If the window was closed in the middle of a race, remove players,
|
||||
// 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
|
||||
if (input_manager)
|
||||
{
|
||||
delete input_manager;
|
||||
input_manager = NULL;
|
||||
}
|
||||
|
||||
if (STKHost::existHost())
|
||||
STKHost::get()->shutdown();
|
||||
|
||||
NetworkConfig::destroy();
|
||||
cleanSuperTuxKart();
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -25,10 +25,12 @@
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/message_queue.hpp"
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/protocols/lobby_protocol.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
@ -36,8 +38,6 @@
|
||||
#include "online/request_manager.hpp"
|
||||
#include "race/history.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/main_menu_screen.hpp"
|
||||
#include "states_screens/online_screen.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "utils/profiler.hpp"
|
||||
|
||||
@ -300,8 +300,25 @@ void MainLoop::run()
|
||||
}
|
||||
#endif
|
||||
|
||||
while(!m_abort)
|
||||
while (!m_abort)
|
||||
{
|
||||
bool loading_shutdown = false;
|
||||
auto lb = LobbyProtocol::get<LobbyProtocol>();
|
||||
if (World::getWorld() && lb &&
|
||||
STKHost::existHost() && !STKHost::get()->requestedShutdown())
|
||||
{
|
||||
while (!lb->allPlayersReady())
|
||||
{
|
||||
if (STKHost::existHost() && STKHost::get()->requestedShutdown())
|
||||
{
|
||||
loading_shutdown = true;
|
||||
break;
|
||||
}
|
||||
StkTime::sleep(1);
|
||||
m_curr_time = irr_driver->getDevice()->getTimer()->getRealTime();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if (parent != 0 && parent != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@ -330,7 +347,9 @@ void MainLoop::run()
|
||||
float dt = stk_config->ticks2Time(1);
|
||||
left_over_time -= num_steps * dt ;
|
||||
|
||||
if (STKHost::existHost() &&
|
||||
// Shutdown next frame if shutdown request is sent while loading the
|
||||
// world
|
||||
if (!loading_shutdown && STKHost::existHost() &&
|
||||
STKHost::get()->requestedShutdown())
|
||||
{
|
||||
SFXManager::get()->quickSound("anvil");
|
||||
@ -340,18 +359,16 @@ void MainLoop::run()
|
||||
msg = STKHost::get()->getErrorMessage();
|
||||
}
|
||||
STKHost::get()->shutdown();
|
||||
// In case the user opened a race pause dialog
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
if (World::getWorld())
|
||||
{
|
||||
race_manager->exitRace();
|
||||
}
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
GUIEngine::Screen* new_stack[] =
|
||||
{
|
||||
MainMenuScreen::getInstance(),
|
||||
OnlineScreen::getInstance(), NULL
|
||||
};
|
||||
StateManager::get()->resetAndSetStack(new_stack);
|
||||
StateManager::get()->resetAndSetStack(
|
||||
NetworkConfig::get()->getResetScreens().data());
|
||||
MessageQueue::add(MessageQueue::MT_ERROR, msg);
|
||||
}
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
|
@ -383,7 +383,7 @@ void LinearWorld::newLap(unsigned int kart_index)
|
||||
|
||||
// Store the temporary string because clang would mess this up
|
||||
// (remove the stringw before the wchar_t* is used).
|
||||
const core::stringw &kart_name = kart->getName();
|
||||
const core::stringw &kart_name = kart->getController()->getName();
|
||||
|
||||
//I18N: as in "fastest lap: 60 seconds by Wilber"
|
||||
irr::core::stringw m_fastest_lap_message =
|
||||
|
@ -170,6 +170,18 @@ public:
|
||||
{
|
||||
return stk_config->ticks2Time(m_fastest_lap_ticks);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Network use: get fastest lap in ticks */
|
||||
int getFastestLapTicks() const
|
||||
{
|
||||
return m_fastest_lap_ticks;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Network use: set fastest lap in ticks */
|
||||
void setFastestLapTicks(int ticks)
|
||||
{
|
||||
m_fastest_lap_ticks = ticks;
|
||||
}
|
||||
}; // LinearWorld
|
||||
|
||||
#endif
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "graphics/render_info.hpp"
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/keyboard_device.hpp"
|
||||
@ -341,11 +342,13 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index,
|
||||
gk = ReplayPlay::get()->getNumGhostKart();
|
||||
|
||||
std::shared_ptr<RenderInfo> ri = std::make_shared<RenderInfo>();
|
||||
if (global_player_id > -1 && race_manager->getKartInfo(global_player_id)
|
||||
.getDefaultKartColor() > 0.0f)
|
||||
core::stringw online_name;
|
||||
if (global_player_id > -1)
|
||||
{
|
||||
ri->setHue(race_manager->getKartInfo(global_player_id)
|
||||
.getDefaultKartColor());
|
||||
online_name = race_manager->getKartInfo(global_player_id)
|
||||
.getPlayerName();
|
||||
}
|
||||
|
||||
int position = index+1;
|
||||
@ -378,6 +381,8 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index,
|
||||
case RaceManager::KT_NETWORK_PLAYER:
|
||||
{
|
||||
controller = new NetworkPlayerController(new_kart);
|
||||
if (!online_name.empty())
|
||||
new_kart->setOnScreenText(online_name.c_str());
|
||||
m_num_players++;
|
||||
break;
|
||||
}
|
||||
@ -564,7 +569,7 @@ void World::terminateRace()
|
||||
// to show it in the GUI
|
||||
int best_highscore_rank = -1;
|
||||
std::string highscore_who = "";
|
||||
if (!this->isNetworkWorld())
|
||||
if (!isNetworkWorld())
|
||||
{
|
||||
updateHighscores(&best_highscore_rank);
|
||||
}
|
||||
@ -656,6 +661,8 @@ void World::terminateRace()
|
||||
results->clearHighscores();
|
||||
}
|
||||
|
||||
// In case someone opened paused race dialog in network game
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
results->push();
|
||||
WorldStatus::terminateRace();
|
||||
} // terminateRace
|
||||
@ -1081,7 +1088,7 @@ void World::updateTrack(int ticks)
|
||||
// ----------------------------------------------------------------------------
|
||||
Highscores* World::getHighscores() const
|
||||
{
|
||||
if(!m_use_highscores) return NULL;
|
||||
if (isNetworkWorld() || !m_use_highscores) return NULL;
|
||||
|
||||
const Highscores::HighscoreType type = "HST_" + getIdent();
|
||||
|
||||
@ -1210,6 +1217,7 @@ AbstractKart *World::getLocalPlayerKart(unsigned int n) const
|
||||
/** Remove (eliminate) a kart from the race */
|
||||
void World::eliminateKart(int kart_id, bool notify_of_elimination)
|
||||
{
|
||||
assert(kart_id < (int)m_karts.size());
|
||||
AbstractKart *kart = m_karts[kart_id];
|
||||
if (kart->isGhostKart()) return;
|
||||
|
||||
@ -1226,7 +1234,7 @@ void World::eliminateKart(int kart_id, bool notify_of_elimination)
|
||||
{
|
||||
// Store the temporary string because clang would mess this up
|
||||
// (remove the stringw before the wchar_t* is used).
|
||||
const core::stringw &kart_name = kart->getName();
|
||||
const core::stringw &kart_name = kart->getController()->getName();
|
||||
m_race_gui->addMessage(_("'%s' has been eliminated.",
|
||||
kart_name),
|
||||
camera->getKart(),
|
||||
@ -1306,7 +1314,9 @@ void World::unpause()
|
||||
//-----------------------------------------------------------------------------
|
||||
void World::escapePressed()
|
||||
{
|
||||
new RacePausedDialog(0.8f, 0.6f);
|
||||
if (!(NetworkConfig::get()->isNetworking() &&
|
||||
getPhase() < MUSIC_PHASE))
|
||||
new RacePausedDialog(0.8f, 0.6f);
|
||||
} // escapePressed
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -113,7 +113,6 @@ protected:
|
||||
|
||||
void updateHighscores (int* best_highscore_rank);
|
||||
void resetAllKarts ();
|
||||
void eliminateKart (int kart_number, bool notifyOfElimination=true);
|
||||
Controller*
|
||||
loadAIController (AbstractKart *kart);
|
||||
|
||||
@ -321,6 +320,8 @@ public:
|
||||
virtual void escapePressed();
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void loadCustomModels() {}
|
||||
// ------------------------------------------------------------------------
|
||||
void eliminateKart(int kart_number, bool notify_of_elimination = true);
|
||||
|
||||
/** Set the network mode (true if networked) */
|
||||
void setNetworkWorld(bool is_networked) { m_is_network_world = is_networked; }
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/protocols/client_lobby.hpp"
|
||||
#include "network/protocols/server_lobby.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
@ -150,6 +149,11 @@ void WorldStatus::setClockMode(const ClockType mode, const float initial_time)
|
||||
*/
|
||||
void WorldStatus::enterRaceOverState()
|
||||
{
|
||||
// Waiting for server result info
|
||||
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||
if (cl && !cl->receivedServerResult())
|
||||
return;
|
||||
|
||||
// Don't enter race over if it's already race over
|
||||
if (m_phase == DELAY_FINISH_PHASE || m_phase == RESULT_DISPLAY_PHASE ||
|
||||
m_phase == FINISH_PHASE)
|
||||
@ -257,12 +261,11 @@ void WorldStatus::updateTime(int ticks)
|
||||
case WAIT_FOR_SERVER_PHASE:
|
||||
{
|
||||
// This stage is only reached in case of a networked game.
|
||||
// A client waits for a message from the server that it can
|
||||
// start the race (i.e. that all clients and the server have
|
||||
// loaded the world). The server waits for a confirmation from
|
||||
// The server waits for a confirmation from
|
||||
// each client that they have started (to guarantee that the
|
||||
// server is running with a local time behind all clients).
|
||||
if (m_server_is_ready.load() == false) return;
|
||||
if (NetworkConfig::get()->isServer() &&
|
||||
m_server_is_ready.load() == false) return;
|
||||
|
||||
m_phase = READY_PHASE;
|
||||
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||
@ -400,10 +403,12 @@ void WorldStatus::updateTime(int ticks)
|
||||
break;
|
||||
}
|
||||
case FINISH_PHASE:
|
||||
case IN_GAME_MENU_PHASE:
|
||||
// Nothing to do here.
|
||||
break;
|
||||
case GOAL_PHASE:
|
||||
// Nothing to do here as well.
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
@ -21,24 +21,17 @@
|
||||
#include "config/player_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "online/online_profile.hpp"
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
GameSetup::GameSetup()
|
||||
{
|
||||
m_num_local_players = 0;
|
||||
m_local_master = 0;
|
||||
m_laps = 0;
|
||||
m_reverse = false;
|
||||
} // GameSetup
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Update and see if any player disconnects.
|
||||
* \param remove_disconnected_players remove the disconnected players,
|
||||
* otherwise replace with AI (when racing), so this function must be called
|
||||
* otherwise eliminate the kart in world, so this function must be called
|
||||
* in main thread.
|
||||
*/
|
||||
void GameSetup::update(bool remove_disconnected_players)
|
||||
@ -54,16 +47,84 @@ void GameSetup::update(bool remove_disconnected_players)
|
||||
return;
|
||||
}
|
||||
lock.unlock();
|
||||
if (!World::getWorld())
|
||||
if (!World::getWorld() ||
|
||||
World::getWorld()->getPhase() < WorldStatus::MUSIC_PHASE)
|
||||
return;
|
||||
for (uint8_t i = 0; i < (uint8_t)m_players.size(); i++)
|
||||
{
|
||||
if (!m_players[i].expired())
|
||||
continue;
|
||||
AbstractKart* k = World::getWorld()->getKart(i);
|
||||
if (!k->isEliminated())
|
||||
{
|
||||
World::getWorld()->eliminateKart(i,
|
||||
false/*notify_of_elimination*/);
|
||||
k->setPosition(
|
||||
World::getWorld()->getCurrentNumKarts() + 1);
|
||||
k->finishedRace(World::getWorld()->getTime());
|
||||
NetworkString p(PROTOCOL_GAME_EVENTS);
|
||||
p.setSynchronous(true);
|
||||
p.addUInt8(GameEventsProtocol::GE_PLAYER_DISCONNECT).addUInt8(i);
|
||||
STKHost::get()->sendPacketToAllPeers(&p, true);
|
||||
}
|
||||
}
|
||||
} // removePlayer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void GameSetup::loadWorld()
|
||||
{
|
||||
assert(!m_track.empty());
|
||||
assert(!m_tracks.empty());
|
||||
// Disable accidentally unlocking of a challenge
|
||||
PlayerManager::getCurrentPlayer()->setCurrentChallenge("");
|
||||
race_manager->setTimeTarget(0.0f);
|
||||
race_manager->setReverseTrack(m_reverse);
|
||||
race_manager->startSingleRace(m_track, m_laps, false/*from_overworld*/);
|
||||
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
|
||||
{
|
||||
if (isSoccerGoalTarget())
|
||||
race_manager->setMaxGoal(m_laps);
|
||||
else
|
||||
race_manager->setTimeTarget((float)m_laps * 60.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
race_manager->startSingleRace(m_tracks.back(), m_laps,
|
||||
false/*from_overworld*/);
|
||||
}
|
||||
} // loadWorld
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool GameSetup::isGrandPrix() const
|
||||
{
|
||||
return m_extra_server_info != -1 &&
|
||||
NetworkConfig::get()->getLocalGameMode().second ==
|
||||
RaceManager::MAJOR_MODE_GRAND_PRIX;
|
||||
} // isGrandPrix
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void GameSetup::addServerInfo(NetworkString* ns)
|
||||
{
|
||||
assert(NetworkConfig::get()->isServer());
|
||||
ns->encodeString(NetworkConfig::get()->getServerName());
|
||||
ns->addUInt8(race_manager->getDifficulty())
|
||||
.addUInt8((uint8_t)NetworkConfig::get()->getMaxPlayers())
|
||||
.addUInt8((uint8_t)NetworkConfig::get()->getServerMode());
|
||||
if (hasExtraSeverInfo())
|
||||
{
|
||||
if (isGrandPrix())
|
||||
{
|
||||
ns->addUInt8((uint8_t)2).addUInt8((uint8_t)m_tracks.size())
|
||||
.addUInt8(getExtraServerInfo());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Soccer mode
|
||||
ns->addUInt8((uint8_t)1).addUInt8(getExtraServerInfo());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No extra server info
|
||||
ns->addUInt8((uint8_t)0);
|
||||
}
|
||||
ns->encodeString(NetworkConfig::get()->getMOTD());
|
||||
} // addServerInfo
|
||||
|
@ -24,12 +24,14 @@
|
||||
|
||||
#include "network/remote_kart_info.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class NetworkPlayerProfile;
|
||||
class NetworkString;
|
||||
|
||||
// ============================================================================
|
||||
/*! \class GameSetup
|
||||
@ -47,19 +49,22 @@ private:
|
||||
/** Stores the number of local players. */
|
||||
int m_num_local_players;
|
||||
|
||||
/** The player id of the local game master, used in
|
||||
* kart selection screen. */
|
||||
uint8_t m_local_master;
|
||||
|
||||
std::string m_track;
|
||||
std::vector<std::string> m_tracks;
|
||||
|
||||
unsigned m_laps;
|
||||
|
||||
bool m_reverse;
|
||||
|
||||
int m_extra_server_info;
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
GameSetup();
|
||||
GameSetup()
|
||||
{
|
||||
m_num_local_players = 0;
|
||||
m_extra_server_info = -1;
|
||||
reset();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
~GameSetup() {}
|
||||
// ------------------------------------------------------------------------
|
||||
@ -69,7 +74,7 @@ public:
|
||||
void update(bool remove_disconnected_players);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the number of local players. */
|
||||
void setNumLocalPlayers(int n) { m_num_local_players = n; }
|
||||
void setNumLocalPlayers(int n) { m_num_local_players = n; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the nunber of local players. */
|
||||
int getNumLocalPlayers() const { return m_num_local_players; }
|
||||
@ -104,17 +109,51 @@ public:
|
||||
return (unsigned)m_players.size();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the id of the local master. */
|
||||
int getLocalMasterID() const { return m_local_master; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setRace(const std::string& track, unsigned laps, bool reverse)
|
||||
{
|
||||
m_track = track;
|
||||
m_tracks.push_back(track);
|
||||
m_laps = laps;
|
||||
m_reverse = reverse;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void reset()
|
||||
{
|
||||
m_tracks.clear();
|
||||
m_laps = 0;
|
||||
m_reverse = false;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void setGrandPrixTrack(int tracks_no) { m_extra_server_info = tracks_no; }
|
||||
// ------------------------------------------------------------------------
|
||||
void addServerInfo(NetworkString* ns);
|
||||
// ------------------------------------------------------------------------
|
||||
void loadWorld();
|
||||
// ------------------------------------------------------------------------
|
||||
bool isGrandPrix() const;
|
||||
// ------------------------------------------------------------------------
|
||||
bool hasExtraSeverInfo() const { return m_extra_server_info != -1; }
|
||||
// ------------------------------------------------------------------------
|
||||
uint8_t getExtraServerInfo() const
|
||||
{
|
||||
assert(hasExtraSeverInfo());
|
||||
return (uint8_t)m_extra_server_info;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned getTotalGrandPrixTracks() const
|
||||
{
|
||||
assert(isGrandPrix());
|
||||
return m_extra_server_info;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void setSoccerGoalTarget(bool val) { m_extra_server_info = (int)val; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool isSoccerGoalTarget() const
|
||||
{
|
||||
assert(hasExtraSeverInfo());
|
||||
return m_extra_server_info != 0;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
const std::vector<std::string>& getAllTracks() const { return m_tracks; }
|
||||
};
|
||||
|
||||
#endif // GAME_SETUP_HPP
|
||||
|
@ -186,9 +186,9 @@ void Network::openLog()
|
||||
std::string s = file_manager
|
||||
->getUserConfigFile(FileManager::getStdoutName()+".packet");
|
||||
m_log_file.setAtomic(fopen(s.c_str(), "w+"));
|
||||
if (!m_log_file.getData())
|
||||
Log::warn("STKHost", "Network packets won't be logged: no file.");
|
||||
}
|
||||
if (!m_log_file.getData())
|
||||
Log::warn("STKHost", "Network packets won't be logged: no file.");
|
||||
} // openLog
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -20,6 +20,11 @@
|
||||
#include "config/stk_config.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "online/xml_request.hpp"
|
||||
#include "states_screens/main_menu_screen.hpp"
|
||||
#include "states_screens/networking_lobby.hpp"
|
||||
#include "states_screens/online_lan.hpp"
|
||||
#include "states_screens/online_profile_servers.hpp"
|
||||
#include "states_screens/online_screen.hpp"
|
||||
|
||||
NetworkConfig *NetworkConfig::m_network_config = NULL;
|
||||
bool NetworkConfig::m_disable_lan = false;
|
||||
@ -72,39 +77,38 @@ void NetworkConfig::setIsServer(bool b)
|
||||
} // setIsServer
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
unsigned NetworkConfig::getServerGameMode(RaceManager::MinorRaceModeType minor,
|
||||
RaceManager::MajorRaceModeType major)
|
||||
void NetworkConfig::setServerMode(RaceManager::MinorRaceModeType minor,
|
||||
RaceManager::MajorRaceModeType major)
|
||||
{
|
||||
if (major == RaceManager::MAJOR_MODE_GRAND_PRIX)
|
||||
{
|
||||
if (minor == RaceManager::MINOR_MODE_NORMAL_RACE)
|
||||
return 0;
|
||||
m_server_mode = 0;
|
||||
else if (minor == RaceManager::MINOR_MODE_TIME_TRIAL)
|
||||
return 1;
|
||||
m_server_mode = 1;
|
||||
else if (minor == RaceManager::MINOR_MODE_FOLLOW_LEADER)
|
||||
return 2;
|
||||
m_server_mode = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (minor == RaceManager::MINOR_MODE_NORMAL_RACE)
|
||||
return 3;
|
||||
m_server_mode = 3;
|
||||
else if (minor == RaceManager::MINOR_MODE_TIME_TRIAL)
|
||||
return 4;
|
||||
m_server_mode = 4;
|
||||
else if (minor == RaceManager::MINOR_MODE_FOLLOW_LEADER)
|
||||
return 5;
|
||||
m_server_mode = 5;
|
||||
else if (minor == RaceManager::MINOR_MODE_3_STRIKES)
|
||||
return 6;
|
||||
m_server_mode = 6;
|
||||
else if (minor == RaceManager::MINOR_MODE_SOCCER)
|
||||
return 7;
|
||||
m_server_mode = 7;
|
||||
}
|
||||
return 0;
|
||||
} // getServerGameMode
|
||||
} // setServerMode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::pair<RaceManager::MinorRaceModeType, RaceManager::MajorRaceModeType>
|
||||
NetworkConfig::getLocalGameMode(unsigned id)
|
||||
NetworkConfig::getLocalGameMode()
|
||||
{
|
||||
switch(id)
|
||||
switch (m_server_mode)
|
||||
{
|
||||
case 0:
|
||||
return { RaceManager::MINOR_MODE_NORMAL_RACE,
|
||||
@ -147,3 +151,79 @@ void NetworkConfig::setUserDetails(Online::XMLRequest* r,
|
||||
r->addParameter("userid", m_cur_user_id);
|
||||
r->addParameter("token", m_cur_user_token);
|
||||
} // setUserDetails
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
core::stringw NetworkConfig::getModeName(unsigned id)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case 0:
|
||||
return _("Normal Race (Grand Prix)");
|
||||
case 1:
|
||||
return _("Time Trial (Grand Prix)");
|
||||
case 3:
|
||||
return _("Normal Race");
|
||||
case 4:
|
||||
return _("Time Trial");
|
||||
case 6:
|
||||
return _("3 Strikes Battle");
|
||||
case 7:
|
||||
return _("Soccer");
|
||||
default:
|
||||
return L"";
|
||||
}
|
||||
} // getModeName
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::vector<GUIEngine::Screen*>
|
||||
NetworkConfig::getResetScreens(bool lobby) const
|
||||
{
|
||||
if (lobby)
|
||||
{
|
||||
if (isWAN())
|
||||
{
|
||||
return
|
||||
{
|
||||
MainMenuScreen::getInstance(),
|
||||
OnlineScreen::getInstance(),
|
||||
OnlineProfileServers::getInstance(),
|
||||
NetworkingLobby::getInstance(),
|
||||
nullptr
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
{
|
||||
MainMenuScreen::getInstance(),
|
||||
OnlineScreen::getInstance(),
|
||||
OnlineLanScreen::getInstance(),
|
||||
NetworkingLobby::getInstance(),
|
||||
nullptr
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isWAN())
|
||||
{
|
||||
return
|
||||
{
|
||||
MainMenuScreen::getInstance(),
|
||||
OnlineScreen::getInstance(),
|
||||
OnlineProfileServers::getInstance(),
|
||||
nullptr
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
{
|
||||
MainMenuScreen::getInstance(),
|
||||
OnlineScreen::getInstance(),
|
||||
OnlineLanScreen::getInstance(),
|
||||
nullptr
|
||||
};
|
||||
}
|
||||
}
|
||||
} // getResetScreens
|
||||
|
@ -34,6 +34,11 @@ namespace Online
|
||||
class XMLRequest;
|
||||
}
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
class Screen;
|
||||
}
|
||||
|
||||
class InputDevice;
|
||||
class PlayerProfile;
|
||||
|
||||
@ -86,6 +91,8 @@ private:
|
||||
/** If this is a server, the server name. */
|
||||
irr::core::stringw m_server_name;
|
||||
|
||||
unsigned m_server_mode;
|
||||
|
||||
/** Used by wan server. */
|
||||
uint32_t m_cur_user_id;
|
||||
std::string m_cur_user_token;
|
||||
@ -96,6 +103,8 @@ private:
|
||||
std::vector<std::tuple<InputDevice*, PlayerProfile*,
|
||||
/*is_handicap*/bool> > m_network_players;
|
||||
|
||||
core::stringw m_motd;
|
||||
|
||||
NetworkConfig();
|
||||
|
||||
public:
|
||||
@ -249,13 +258,9 @@ public:
|
||||
* requested. */
|
||||
bool isAutoConnect() const { return m_auto_connect; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the game mode id for server database. */
|
||||
unsigned getServerGameMode(RaceManager::MinorRaceModeType mode,
|
||||
RaceManager::MajorRaceModeType);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the minor and majar game mode from server database id. */
|
||||
std::pair<RaceManager::MinorRaceModeType, RaceManager::MajorRaceModeType>
|
||||
getLocalGameMode(unsigned);
|
||||
getLocalGameMode();
|
||||
// ------------------------------------------------------------------------
|
||||
void setCurrentUserId(uint32_t id) { m_cur_user_id = id ; }
|
||||
// ------------------------------------------------------------------------
|
||||
@ -270,6 +275,21 @@ public:
|
||||
void setServerIdFile(const std::string& id) { m_server_id_file = id; }
|
||||
// ------------------------------------------------------------------------
|
||||
const std::string& getServerIdFile() const { return m_server_id_file; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setMOTD(const core::stringw& motd) { m_motd = motd; }
|
||||
// ------------------------------------------------------------------------
|
||||
const core::stringw& getMOTD() const { return m_motd; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setServerMode(RaceManager::MinorRaceModeType mode,
|
||||
RaceManager::MajorRaceModeType);
|
||||
// ------------------------------------------------------------------------
|
||||
void setServerMode(unsigned mode) { m_server_mode = mode; }
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned getServerMode() const { return m_server_mode; }
|
||||
// ------------------------------------------------------------------------
|
||||
core::stringw getModeName(unsigned id);
|
||||
// ------------------------------------------------------------------------
|
||||
std::vector<GUIEngine::Screen*> getResetScreens(bool lobby = false) const;
|
||||
|
||||
}; // class NetworkConfig
|
||||
|
||||
|
@ -30,7 +30,7 @@ void NetworkString::unitTesting()
|
||||
{
|
||||
NetworkString s(PROTOCOL_LOBBY_ROOM);
|
||||
assert(s.getProtocolType() == PROTOCOL_LOBBY_ROOM);
|
||||
assert(s.getProtocolType() != PROTOCOL_KART_UPDATE);
|
||||
assert(s.getProtocolType() != PROTOCOL_CONTROLLER_EVENTS);
|
||||
assert(!s.isSynchronous());
|
||||
s.setSynchronous(true);
|
||||
assert(s.isSynchronous());
|
||||
|
@ -46,10 +46,9 @@ enum ProtocolType
|
||||
PROTOCOL_LOBBY_ROOM = 0x02, //!< Protocol that is used during the lobby room phase.
|
||||
PROTOCOL_START_GAME = 0x03, //!< Protocol used when starting the game.
|
||||
PROTOCOL_SYNCHRONIZATION = 0x04, //!< Protocol used to determine latency
|
||||
PROTOCOL_KART_UPDATE = 0x05, //!< Protocol to update karts position, rotation etc...
|
||||
PROTOCOL_GAME_EVENTS = 0x06, //!< Protocol to communicate the game events.
|
||||
PROTOCOL_CONTROLLER_EVENTS = 0x07, //!< Protocol to transfer controller modifications
|
||||
PROTOCOL_SILENT = 0x08, //!< Used for protocols that do not subscribe to any network event.
|
||||
PROTOCOL_GAME_EVENTS = 0x05, //!< Protocol to communicate the game events.
|
||||
PROTOCOL_CONTROLLER_EVENTS = 0x06, //!< Protocol to transfer controller modifications
|
||||
PROTOCOL_SILENT = 0x07, //!< Used for protocols that do not subscribe to any network event.
|
||||
PROTOCOL_MAX , //!< Maximum number of different protocol types
|
||||
PROTOCOL_SYNCHRONOUS = 0x80, //!< Flag, indicates synchronous delivery
|
||||
}; // ProtocolType
|
||||
|
@ -24,12 +24,13 @@
|
||||
#include "guiengine/message_queue.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "modes/world_with_rank.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/game_protocol.hpp"
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
@ -81,10 +82,13 @@ ClientLobby::~ClientLobby()
|
||||
void ClientLobby::clearPlayers()
|
||||
{
|
||||
StateManager::get()->resetActivePlayers();
|
||||
input_manager->getDeviceManager()->setAssignMode(NO_ASSIGN);
|
||||
input_manager->getDeviceManager()->setSinglePlayer(NULL);
|
||||
input_manager->setMasterPlayerOnly(false);
|
||||
input_manager->getDeviceManager()->clearLatestUsedDevice();
|
||||
if (input_manager)
|
||||
{
|
||||
input_manager->getDeviceManager()->setAssignMode(NO_ASSIGN);
|
||||
input_manager->getDeviceManager()->setSinglePlayer(NULL);
|
||||
input_manager->setMasterPlayerOnly(false);
|
||||
input_manager->getDeviceManager()->clearLatestUsedDevice();
|
||||
}
|
||||
} // clearPlayers
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -99,9 +103,10 @@ void ClientLobby::setAddress(const TransportAddress &address)
|
||||
void ClientLobby::setup()
|
||||
{
|
||||
clearPlayers();
|
||||
m_received_server_result = false;
|
||||
TracksScreen::getInstance()->resetVote();
|
||||
LobbyProtocol::setup();
|
||||
m_state = NONE;
|
||||
m_state.store(NONE);
|
||||
} // setup
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -111,7 +116,8 @@ void ClientLobby::setup()
|
||||
*/
|
||||
void ClientLobby::doneWithResults()
|
||||
{
|
||||
NetworkString *done = getNetworkString(1);
|
||||
NetworkString* done = getNetworkString(1);
|
||||
done->setSynchronous(true);
|
||||
done->addUInt8(LE_RACE_FINISHED_ACK);
|
||||
sendToServer(done, /*reliable*/true);
|
||||
delete done;
|
||||
@ -135,6 +141,8 @@ bool ClientLobby::notifyEvent(Event* event)
|
||||
case LE_EXIT_RESULT: exitResultScreen(event); break;
|
||||
case LE_UPDATE_PLAYER_LIST: updatePlayerList(event); break;
|
||||
case LE_CHAT: handleChat(event); break;
|
||||
case LE_CONNECTION_ACCEPTED: connectionAccepted(event); break;
|
||||
case LE_SERVER_INFO: handleServerInfo(event); break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
@ -159,7 +167,6 @@ bool ClientLobby::notifyEventAsynchronous(Event* event)
|
||||
case LE_PLAYER_DISCONNECTED : disconnectedPlayer(event); break;
|
||||
case LE_START_RACE: startGame(event); break;
|
||||
case LE_CONNECTION_REFUSED: connectionRefused(event); break;
|
||||
case LE_CONNECTION_ACCEPTED: connectionAccepted(event); break;
|
||||
case LE_VOTE: displayPlayerVote(event); break;
|
||||
case LE_SERVER_OWNERSHIP: becomingServerOwner(); break;
|
||||
default: break;
|
||||
@ -216,10 +223,9 @@ void ClientLobby::addAllPlayers(Event* event)
|
||||
|
||||
std::shared_ptr<STKPeer> peer = event->getPeerSP();
|
||||
peer->cleanPlayerProfiles();
|
||||
|
||||
m_game_setup->update(true/*remove_disconnected_players*/);
|
||||
std::vector<std::shared_ptr<NetworkPlayerProfile> > players;
|
||||
unsigned player_count = data.getUInt8();
|
||||
assert(m_game_setup->getPlayerCount() == 0);
|
||||
|
||||
for (unsigned i = 0; i < player_count; i++)
|
||||
{
|
||||
@ -245,18 +251,19 @@ void ClientLobby::addAllPlayers(Event* event)
|
||||
//-----------------------------------------------------------------------------
|
||||
void ClientLobby::update(int ticks)
|
||||
{
|
||||
switch (m_state)
|
||||
switch (m_state.load())
|
||||
{
|
||||
case NONE:
|
||||
if (STKHost::get()->isConnectedTo(m_server_address))
|
||||
{
|
||||
m_state = LINKED;
|
||||
m_state.store(LINKED);
|
||||
}
|
||||
break;
|
||||
case LINKED:
|
||||
{
|
||||
NetworkString *ns = getNetworkString();
|
||||
ns->addUInt8(LE_CONNECTION_REQUESTED)
|
||||
.addUInt8(NetworkConfig::m_server_version)
|
||||
.encodeString(NetworkConfig::get()->getPassword());
|
||||
|
||||
assert(!NetworkConfig::get()->isAddingNetworkPlayers());
|
||||
@ -305,7 +312,7 @@ void ClientLobby::update(int ticks)
|
||||
|
||||
sendToServer(ns);
|
||||
delete ns;
|
||||
m_state = REQUESTING_CONNECTION;
|
||||
m_state.store(REQUESTING_CONNECTION);
|
||||
}
|
||||
break;
|
||||
case REQUESTING_CONNECTION:
|
||||
@ -337,7 +344,7 @@ void ClientLobby::update(int ticks)
|
||||
{
|
||||
screen->push();
|
||||
}
|
||||
m_state = SELECTING_KARTS;
|
||||
m_state.store(SELECTING_KARTS);
|
||||
}
|
||||
break;
|
||||
case SELECTING_KARTS:
|
||||
@ -347,7 +354,7 @@ void ClientLobby::update(int ticks)
|
||||
case RACE_FINISHED:
|
||||
break;
|
||||
case DONE:
|
||||
m_state = EXITING;
|
||||
m_state.store(EXITING);
|
||||
requestTerminate();
|
||||
break;
|
||||
case EXITING:
|
||||
@ -419,7 +426,7 @@ void ClientLobby::disconnectedPlayer(Event* event)
|
||||
*/
|
||||
void ClientLobby::connectionAccepted(Event* event)
|
||||
{
|
||||
// At least 4 byte should remain now
|
||||
// At least 4 bytes should remain now
|
||||
if (!checkDataSize(event, 4)) return;
|
||||
|
||||
NetworkString &data = event->data();
|
||||
@ -435,11 +442,88 @@ void ClientLobby::connectionAccepted(Event* event)
|
||||
NetworkConfig::get()->getNetworkPlayers().size());
|
||||
// connection token
|
||||
uint32_t token = data.getToken();
|
||||
if (!peer->isClientServerTokenSet())
|
||||
peer->setClientServerToken(token);
|
||||
m_state = CONNECTED;
|
||||
peer->setClientServerToken(token);
|
||||
m_state.store(CONNECTED);
|
||||
|
||||
} // connectionAccepted
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ClientLobby::handleServerInfo(Event* event)
|
||||
{
|
||||
// At least 6 bytes should remain now
|
||||
if (!checkDataSize(event, 6)) return;
|
||||
|
||||
NetworkString &data = event->data();
|
||||
// Add server info
|
||||
core::stringw str, each_line;
|
||||
uint8_t u_data;
|
||||
data.decodeStringW(&str);
|
||||
|
||||
//I18N: In the networking lobby
|
||||
each_line = _("Server name: %s", str);
|
||||
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
|
||||
|
||||
u_data = data.getUInt8();
|
||||
const core::stringw& difficulty_name =
|
||||
race_manager->getDifficultyName((RaceManager::Difficulty)u_data);
|
||||
race_manager->setDifficulty((RaceManager::Difficulty)u_data);
|
||||
//I18N: In the networking lobby
|
||||
each_line = _("Difficulty: %s", difficulty_name);
|
||||
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
|
||||
|
||||
u_data = data.getUInt8();
|
||||
//I18N: In the networking lobby
|
||||
each_line = _("Max players: %d", (int)u_data);
|
||||
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
|
||||
|
||||
u_data = data.getUInt8();
|
||||
NetworkConfig::get()->setServerMode(u_data);
|
||||
auto game_mode = NetworkConfig::get()->getLocalGameMode();
|
||||
race_manager->setMinorMode(game_mode.first);
|
||||
// We may use single mode in network even it's grand prix
|
||||
//race_manager->setMajorMode(game_mode.second);
|
||||
|
||||
//I18N: In the networking lobby
|
||||
core::stringw mode_name = NetworkConfig::get()->getModeName(u_data);
|
||||
each_line = _("Game mode: %s", mode_name);
|
||||
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
|
||||
|
||||
uint8_t extra_server_info = data.getUInt8();
|
||||
switch (extra_server_info)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
u_data = data.getUInt8();
|
||||
core::stringw tl = _("Time limit");
|
||||
core::stringw gl = _("Goals limit");
|
||||
core::stringw sgt = u_data == 0 ? tl : gl;
|
||||
m_game_setup->setSoccerGoalTarget(u_data != 0);
|
||||
//I18N: In the networking lobby
|
||||
each_line = _("Soccer game type: %s", sgt);
|
||||
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
unsigned cur_gp_track = data.getUInt8();
|
||||
unsigned total_gp_track = data.getUInt8();
|
||||
m_game_setup->setGrandPrixTrack(total_gp_track);
|
||||
each_line = _("Grand prix progress: %d / %d", cur_gp_track,
|
||||
total_gp_track);
|
||||
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// MOTD
|
||||
data.decodeStringW(&str);
|
||||
if (!str.empty())
|
||||
NetworkingLobby::getInstance()->addMoreServerInfo(str);
|
||||
|
||||
} // handleServerInfo
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ClientLobby::updatePlayerList(Event* event)
|
||||
{
|
||||
@ -464,10 +548,10 @@ void ClientLobby::updatePlayerList(Event* event)
|
||||
//-----------------------------------------------------------------------------
|
||||
void ClientLobby::becomingServerOwner()
|
||||
{
|
||||
MessageQueue::add(MessageQueue::MT_GENERIC,
|
||||
_("You are now the owner of server."));
|
||||
core::stringw msg = _("You are now the owner of server.");
|
||||
MessageQueue::add(MessageQueue::MT_GENERIC, msg);
|
||||
STKHost::get()->setAuthorisedToControl(true);
|
||||
if (m_state == CONNECTED && NetworkConfig::get()->isAutoConnect())
|
||||
if (m_state.load() == CONNECTED && NetworkConfig::get()->isAutoConnect())
|
||||
{
|
||||
// Send a message to the server to start
|
||||
NetworkString start(PROTOCOL_LOBBY_ROOM);
|
||||
@ -537,12 +621,12 @@ void ClientLobby::connectionRefused(Event* event)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the server broadcasts to start the race to all clients.
|
||||
* \param event : Event providing the information (no additional information
|
||||
* \param event : Event providing the information (no additional informati
|
||||
* in this case).
|
||||
*/
|
||||
void ClientLobby::startGame(Event* event)
|
||||
{
|
||||
m_state = PLAYING;
|
||||
m_state.store(PLAYING);
|
||||
// Triggers the world finite state machine to go from WAIT_FOR_SERVER_PHASE
|
||||
// to READY_PHASE.
|
||||
World::getWorld()->setReadyToRace();
|
||||
@ -560,9 +644,10 @@ void ClientLobby::startGame(Event* event)
|
||||
*/
|
||||
void ClientLobby::startingRaceNow()
|
||||
{
|
||||
NetworkString *ns = getNetworkString(2);
|
||||
NetworkString* ns = getNetworkString(2);
|
||||
ns->addUInt8(LE_STARTED_RACE);
|
||||
sendToServer(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
Log::verbose("ClientLobby", "StartingRaceNow at %lf",
|
||||
StkTime::getRealTime());
|
||||
} // startingRaceNow
|
||||
@ -574,7 +659,7 @@ void ClientLobby::startingRaceNow()
|
||||
*/
|
||||
void ClientLobby::startSelection(Event* event)
|
||||
{
|
||||
m_state = KART_SELECTION;
|
||||
m_state.store(KART_SELECTION);
|
||||
const NetworkString& data = event->data();
|
||||
const unsigned kart_num = data.getUInt16();
|
||||
const unsigned track_num = data.getUInt16();
|
||||
@ -609,35 +694,30 @@ void ClientLobby::startSelection(Event* event)
|
||||
*/
|
||||
void ClientLobby::raceFinished(Event* event)
|
||||
{
|
||||
if(!checkDataSize(event, 1)) return;
|
||||
|
||||
NetworkString &data = event->data();
|
||||
Log::error("ClientLobby",
|
||||
"Server notified that the race is finished.");
|
||||
Log::info("ClientLobby", "Server notified that the race is finished.");
|
||||
if (m_game_setup->isGrandPrix())
|
||||
{
|
||||
// fastest lap, and than each kart before / after grand prix points
|
||||
}
|
||||
else if (race_manager->modeHasLaps())
|
||||
{
|
||||
int t = data.getUInt32();
|
||||
static_cast<LinearWorld*>(World::getWorld())->setFastestLapTicks(t);
|
||||
}
|
||||
|
||||
// stop race protocols
|
||||
auto pm = ProtocolManager::lock();
|
||||
assert(pm);
|
||||
pm->findAndTerminate(PROTOCOL_CONTROLLER_EVENTS);
|
||||
pm->findAndTerminate(PROTOCOL_KART_UPDATE);
|
||||
pm->findAndTerminate(PROTOCOL_GAME_EVENTS);
|
||||
RaceEventManager::getInstance()->stop();
|
||||
|
||||
// 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)
|
||||
{
|
||||
uint8_t kart_id = data.getUInt8();
|
||||
ranked_world->setKartPosition(kart_id,position);
|
||||
Log::info("ClientLobby", "Kart %d has finished #%d",
|
||||
kart_id, position);
|
||||
position++;
|
||||
}
|
||||
ranked_world->endSetKartPositions();
|
||||
m_state = RACE_FINISHED;
|
||||
ranked_world->terminateRace();
|
||||
RaceEventManager::getInstance()->getProtocol()->requestTerminate();
|
||||
GameProtocol::lock()->requestTerminate();
|
||||
|
||||
while (!RaceEventManager::getInstance()->protocolStopped())
|
||||
StkTime::sleep(1);
|
||||
while (!GameProtocol::emptyInstance())
|
||||
StkTime::sleep(1);
|
||||
|
||||
m_received_server_result = true;
|
||||
} // raceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -646,16 +726,8 @@ void ClientLobby::raceFinished(Event* event)
|
||||
*/
|
||||
void ClientLobby::exitResultScreen(Event *event)
|
||||
{
|
||||
// stop race protocols
|
||||
auto pm = ProtocolManager::lock();
|
||||
assert(pm);
|
||||
pm->findAndTerminate(PROTOCOL_CONTROLLER_EVENTS);
|
||||
pm->findAndTerminate(PROTOCOL_KART_UPDATE);
|
||||
pm->findAndTerminate(PROTOCOL_GAME_EVENTS);
|
||||
|
||||
// Will be reset to linked if connected to server, see update(float dt)
|
||||
setup();
|
||||
|
||||
m_state.store(CONNECTED);
|
||||
RaceResultGUI::getInstance()->backToLobby();
|
||||
} // exitResultScreen
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "network/protocols/lobby_protocol.hpp"
|
||||
#include "network/transport_address.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <set>
|
||||
|
||||
class ClientLobby : public LobbyProtocol
|
||||
@ -20,13 +22,14 @@ private:
|
||||
void displayPlayerVote(Event* event);
|
||||
void updatePlayerList(Event* event);
|
||||
void handleChat(Event* event);
|
||||
void handleServerInfo(Event* event);
|
||||
void becomingServerOwner();
|
||||
|
||||
void clearPlayers();
|
||||
|
||||
TransportAddress m_server_address;
|
||||
|
||||
enum STATE
|
||||
enum ClientState : unsigned int
|
||||
{
|
||||
NONE,
|
||||
LINKED,
|
||||
@ -41,11 +44,13 @@ private:
|
||||
};
|
||||
|
||||
/** The state of the finite state machine. */
|
||||
STATE m_state;
|
||||
std::atomic<ClientState> m_state;
|
||||
|
||||
std::set<std::string> m_available_karts;
|
||||
std::set<std::string> m_available_tracks;
|
||||
|
||||
bool m_received_server_result = false;
|
||||
|
||||
void addAllPlayers(Event* event);
|
||||
|
||||
public:
|
||||
@ -53,6 +58,7 @@ public:
|
||||
virtual ~ClientLobby();
|
||||
void setAddress(const TransportAddress &address);
|
||||
void doneWithResults();
|
||||
bool receivedServerResult() { return m_received_server_result; }
|
||||
void startingRaceNow();
|
||||
const std::set<std::string>& getAvailableKarts() const
|
||||
{ return m_available_karts; }
|
||||
@ -64,9 +70,10 @@ public:
|
||||
virtual void setup() OVERRIDE;
|
||||
virtual void update(int ticks) OVERRIDE;
|
||||
virtual bool waitingForPlayers() const OVERRIDE
|
||||
{ return m_state == LINKED; }
|
||||
{ return m_state.load() == CONNECTED; }
|
||||
virtual void asynchronousUpdate() OVERRIDE {}
|
||||
|
||||
virtual bool allPlayersReady() const OVERRIDE
|
||||
{ return m_state.load() >= PLAYING; }
|
||||
};
|
||||
|
||||
#endif // CLIENT_LOBBY_HPP
|
||||
|
@ -37,7 +37,6 @@ ConnectToPeer::ConnectToPeer(uint32_t peer_id) : Protocol(PROTOCOL_CONNECTION)
|
||||
m_peer_address.clear();
|
||||
m_peer_id = peer_id;
|
||||
m_state = NONE;
|
||||
m_is_lan = false;
|
||||
} // ConnectToPeer(peer_id)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -51,7 +50,6 @@ ConnectToPeer::ConnectToPeer(const TransportAddress &address)
|
||||
// We don't need to find the peer address, so we can start
|
||||
// with the state when we found the peer address.
|
||||
m_state = WAIT_FOR_CONNECTION;
|
||||
m_is_lan = true;
|
||||
} // ConnectToPeers(TransportAddress)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -39,9 +39,6 @@ protected:
|
||||
* gone. */
|
||||
std::shared_ptr<Protocol> m_current_protocol;
|
||||
|
||||
/** True if this is a LAN connection. */
|
||||
bool m_is_lan;
|
||||
|
||||
/** Timer use for tracking broadcast. */
|
||||
double m_timer = 0.0;
|
||||
|
||||
|
@ -168,12 +168,17 @@ void ConnectToServer::asynchronousUpdate()
|
||||
}
|
||||
if (m_tried_connection++ > 7)
|
||||
{
|
||||
Log::warn("ConnectToServer", "Timeout waiting for"
|
||||
" aloha, trying to connect anyway.");
|
||||
m_state = CONNECTING;
|
||||
// Reset timer for next usage
|
||||
m_timer = 0.0;
|
||||
m_tried_connection = 0;
|
||||
if (NetworkConfig::get()->isWAN())
|
||||
{
|
||||
Log::warn("ConnectToServer", "Timeout waiting for"
|
||||
" aloha, trying to connect anyway.");
|
||||
m_state = CONNECTING;
|
||||
// Reset timer for next usage
|
||||
m_timer = 0.0;
|
||||
m_tried_connection = 0;
|
||||
}
|
||||
else
|
||||
m_state = DONE;
|
||||
return;
|
||||
}
|
||||
if ((!NetworkConfig::m_disable_lan &&
|
||||
@ -257,7 +262,9 @@ void ConnectToServer::update(int ticks)
|
||||
switch(m_state.load())
|
||||
{
|
||||
case REQUESTING_CONNECTION:
|
||||
case CONNECTING:
|
||||
{
|
||||
// Make sure lobby display the quick play server name
|
||||
assert(m_server);
|
||||
NetworkingLobby::getInstance()->setJoinedServer(m_server);
|
||||
break;
|
||||
@ -292,7 +299,7 @@ void ConnectToServer::update(int ticks)
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool ConnectToServer::handleDirectConnect()
|
||||
bool ConnectToServer::handleDirectConnect(int timeout)
|
||||
{
|
||||
// Direct connection to server should only possbile if public and private
|
||||
// ports of server are the same
|
||||
@ -308,10 +315,32 @@ bool ConnectToServer::handleDirectConnect()
|
||||
/*max_in_bandwidth*/0, /*max_out_bandwidth*/0, &ea,
|
||||
true/*change_port_if_bound*/);
|
||||
assert(dc);
|
||||
if (m_server_address.getPort() == 0)
|
||||
{
|
||||
// Get the server port of server from (common) server discovery port
|
||||
Log::info("ConnectToServer", "Detect port for server address.");
|
||||
BareNetworkString s(std::string("stk-server-port"));
|
||||
TransportAddress address(m_server_address.getIP(),
|
||||
NetworkConfig::get()->getServerDiscoveryPort());
|
||||
dc->sendRawPacket(s, address);
|
||||
TransportAddress sender;
|
||||
const int LEN = 2048;
|
||||
char buffer[LEN];
|
||||
int len = dc->receiveRawPacket(buffer, LEN, &sender, 2000);
|
||||
if (len != 2)
|
||||
{
|
||||
Log::error("ConnectToServer", "Invalid port number");
|
||||
delete dc;
|
||||
return false;
|
||||
}
|
||||
BareNetworkString server_port(buffer, len);
|
||||
uint16_t port = server_port.getUInt16();
|
||||
m_server_address.setPort(port);
|
||||
}
|
||||
ENetPeer* p = dc->connectTo(m_server_address);
|
||||
if (p)
|
||||
{
|
||||
while (enet_host_service(dc->getENetHost(), &event, 2000) != 0)
|
||||
while (enet_host_service(dc->getENetHost(), &event, timeout) != 0)
|
||||
{
|
||||
if (event.type == ENET_EVENT_TYPE_CONNECT)
|
||||
{
|
||||
|
@ -56,7 +56,6 @@ private:
|
||||
|
||||
void registerWithSTKServer();
|
||||
void waitingAloha(bool is_wan);
|
||||
bool handleDirectConnect();
|
||||
public:
|
||||
ConnectToServer(std::shared_ptr<Server> server);
|
||||
virtual ~ConnectToServer();
|
||||
@ -65,6 +64,8 @@ public:
|
||||
virtual void setup() OVERRIDE;
|
||||
virtual void asynchronousUpdate() OVERRIDE;
|
||||
virtual void update(int ticks) OVERRIDE;
|
||||
bool handleDirectConnect(int timeout = 2000);
|
||||
|
||||
}; // class ConnectToServer
|
||||
|
||||
#endif // CONNECT_TO_SERVER_HPP
|
||||
|
@ -33,15 +33,6 @@ GameEventsProtocol::~GameEventsProtocol()
|
||||
{
|
||||
} // ~GameEventsProtocol
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Once the GameEventsProtocol is ready, signal the world that the timer
|
||||
* can start.
|
||||
*/
|
||||
void GameEventsProtocol::setup()
|
||||
{
|
||||
m_count_ready_clients = 0;
|
||||
} // setup
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GameEventsProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
@ -55,21 +46,15 @@ bool GameEventsProtocol::notifyEvent(Event* event)
|
||||
Log::warn("GameEventsProtocol", "Too short message.");
|
||||
return true;
|
||||
}
|
||||
if ( event->getPeer()->getClientServerToken() != data.getToken())
|
||||
{
|
||||
Log::warn("GameEventsProtocol", "Bad token.");
|
||||
return true;
|
||||
}
|
||||
int8_t type = data.getUInt8();
|
||||
uint8_t type = data.getUInt8();
|
||||
switch (type)
|
||||
{
|
||||
case GE_CLIENT_STARTED_RSG:
|
||||
receivedClientHasStarted(event); break;
|
||||
case GE_ITEM_COLLECTED:
|
||||
collectedItem(data); break;
|
||||
case GE_KART_FINISHED_RACE:
|
||||
kartFinishedRace(data); break;
|
||||
|
||||
case GE_PLAYER_DISCONNECT:
|
||||
eliminatePlayer(data); break;
|
||||
default:
|
||||
Log::warn("GameEventsProtocol", "Unkown message type.");
|
||||
break;
|
||||
@ -95,12 +80,28 @@ void GameEventsProtocol::collectedItem(Item* item, AbstractKart* kart)
|
||||
ns->addUInt8(GE_ITEM_COLLECTED).addUInt32(item->getItemId())
|
||||
.addUInt8(powerup).addUInt8(kart->getWorldKartId());
|
||||
Log::info("GameEventsProtocol",
|
||||
"Notified a peer that a kart collected item %d.",
|
||||
(int)(kart->getPowerup()->getType()));
|
||||
"Notified a peer that a kart collected item %d index %d",
|
||||
(int)(kart->getPowerup()->getType()), item->getItemId());
|
||||
STKHost::get()->sendPacketToAllPeers(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
} // collectedItem
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GameEventsProtocol::eliminatePlayer(const NetworkString &data)
|
||||
{
|
||||
assert(NetworkConfig::get()->isClient());
|
||||
if (data.size() < 1)
|
||||
{
|
||||
Log::warn("GameEventsProtocol", "eliminatePlayer: Too short message.");
|
||||
}
|
||||
int kartid = data.getUInt8();
|
||||
World::getWorld()->eliminateKart(kartid, false/*notify_of_elimination*/);
|
||||
World::getWorld()->getKart(kartid)->setPosition(
|
||||
World::getWorld()->getCurrentNumKarts() + 1);
|
||||
World::getWorld()->getKart(kartid)->finishedRace(
|
||||
World::getWorld()->getTime());
|
||||
} // eliminatePlayer
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called on the client when an itemCollected message is received.
|
||||
*/
|
||||
@ -115,10 +116,10 @@ void GameEventsProtocol::collectedItem(const NetworkString &data)
|
||||
uint8_t kart_id = data.getUInt8();
|
||||
// now set the kart powerup
|
||||
AbstractKart* kart = World::getWorld()->getKart(kart_id);
|
||||
Log::info("GameEventsProtocol", "Item %d of index %d picked by a player.",
|
||||
powerup_type, item_id);
|
||||
ItemManager::get()->collectedItem(ItemManager::get()->getItem(item_id),
|
||||
kart, powerup_type);
|
||||
Log::info("GameEventsProtocol", "Item %d picked by a player.",
|
||||
powerup_type);
|
||||
} // collectedItem
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -155,39 +156,3 @@ void GameEventsProtocol::kartFinishedRace(const NetworkString &ns)
|
||||
World::getWorld()->getKart(kart_id)->finishedRace(time,
|
||||
/*from_server*/true);
|
||||
} // kartFinishedRace
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called on a client when it has started its ready-set-go. The client will
|
||||
* inform the server anout this. The server will wait for all clients to
|
||||
* have started before it will start its own countdown.
|
||||
*/
|
||||
void GameEventsProtocol::clientHasStarted()
|
||||
{
|
||||
assert(NetworkConfig::get()->isClient());
|
||||
NetworkString *ns = getNetworkString(1);
|
||||
ns->setSynchronous(true);
|
||||
ns->addUInt8(GE_CLIENT_STARTED_RSG);
|
||||
sendToServer(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
} // clientHasStarted
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called on the server when a client has signaled that it has started ready
|
||||
* set go. The server waits for the last client before it starts its own
|
||||
* ready set go. */
|
||||
void GameEventsProtocol::receivedClientHasStarted(Event *event)
|
||||
{
|
||||
/* assert(NetworkConfig::get()->isServer());
|
||||
m_count_ready_clients++;
|
||||
Log::verbose("GameEvent",
|
||||
"Host %d has started ready-set-go: %d out of %d done",
|
||||
event->getPeer()->getHostId(), m_count_ready_clients,
|
||||
STKHost::get()->getGameSetup()->getPlayerCount() );
|
||||
if (m_count_ready_clients==STKHost::get()->getGameSetup()->getPlayerCount())
|
||||
{
|
||||
Log::verbose("GameEvent", "All %d clients have started.",
|
||||
STKHost::get()->getGameSetup()->getPlayerCount());
|
||||
// SIgnal the server to start now - since it is now behind the client
|
||||
// times by the latency of the 'slowest' client.
|
||||
World::getWorld()->startReadySetGo();
|
||||
}*/
|
||||
} // receivedClientHasStarted
|
||||
|
@ -9,19 +9,15 @@ class Item;
|
||||
|
||||
class GameEventsProtocol : public Protocol
|
||||
{
|
||||
private:
|
||||
enum GameEventType {
|
||||
GE_CLIENT_STARTED_RSG = 0x01,
|
||||
GE_ITEM_COLLECTED = 0x02,
|
||||
GE_KART_FINISHED_RACE = 0x03
|
||||
public:
|
||||
enum GameEventType : uint8_t
|
||||
{
|
||||
GE_ITEM_COLLECTED = 1,
|
||||
GE_KART_FINISHED_RACE = 2,
|
||||
GE_PLAYER_DISCONNECT = 3
|
||||
}; // GameEventType
|
||||
|
||||
/** Count how many clients have started 'ready'. The server
|
||||
* will only go to its 'ready' phase if all client shave done so.
|
||||
* This means the server time is far enough behind the clients
|
||||
* that at time T all client messages for time T have been
|
||||
* received (short of latency spikes). */
|
||||
int m_count_ready_clients;
|
||||
private:
|
||||
void eliminatePlayer(const NetworkString &ns);
|
||||
|
||||
public:
|
||||
GameEventsProtocol();
|
||||
@ -31,16 +27,14 @@ public:
|
||||
void collectedItem(Item* item, AbstractKart* kart);
|
||||
void collectedItem(const NetworkString &ns);
|
||||
void kartFinishedRace(AbstractKart *kart, float time);
|
||||
void clientHasStarted();
|
||||
void receivedClientHasStarted(Event *event);
|
||||
void kartFinishedRace(const NetworkString &ns);
|
||||
virtual void setup() OVERRIDE;
|
||||
virtual void setup() OVERRIDE {}
|
||||
virtual void update(int ticks) OVERRIDE {};
|
||||
virtual void asynchronousUpdate() OVERRIDE{}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool notifyEventAsynchronous(Event* event) OVERRIDE
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
} // notifyEventAsynchronous
|
||||
|
||||
|
||||
|
@ -334,8 +334,7 @@ void GameProtocol::rewind(BareNetworkString *buffer)
|
||||
int value_r = buffer->getUInt32();
|
||||
Controller *c = World::getWorld()->getKart(kart_id)->getController();
|
||||
PlayerController *pc = dynamic_cast<PlayerController*>(c);
|
||||
// FIXME this can be endcontroller when finishing the race
|
||||
//assert(pc);
|
||||
if(pc)
|
||||
// This can be endcontroller when finishing the race
|
||||
if (pc)
|
||||
pc->actionFromNetwork(action, value, value_l, value_r);
|
||||
} // rewind
|
||||
|
@ -36,14 +36,15 @@ std::weak_ptr<LobbyProtocol> LobbyProtocol::m_lobby;
|
||||
LobbyProtocol::LobbyProtocol(CallbackObject* callback_object)
|
||||
: Protocol(PROTOCOL_LOBBY_ROOM, callback_object)
|
||||
{
|
||||
m_game_setup = NULL;
|
||||
m_game_setup = new GameSetup();
|
||||
} // LobbyProtocol
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
LobbyProtocol::~LobbyProtocol()
|
||||
{
|
||||
if (m_game_setup)
|
||||
delete m_game_setup;
|
||||
if (RaceEventManager::getInstance())
|
||||
RaceEventManager::getInstance()->stop();
|
||||
delete m_game_setup;
|
||||
} // ~LobbyProtocol
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -62,24 +63,21 @@ void LobbyProtocol::loadWorld()
|
||||
// Race startup sequence
|
||||
// ---------------------
|
||||
// This creates the network world.
|
||||
RaceEventManager::getInstance<RaceEventManager>()->start();
|
||||
auto gep = std::make_shared<GameEventsProtocol>();
|
||||
RaceEventManager::getInstance<RaceEventManager>()->start(gep);
|
||||
|
||||
// Make sure that if there is only a single local player this player can
|
||||
// use all input devices.
|
||||
StateManager::ActivePlayer *ap = race_manager->getNumLocalPlayers()>1
|
||||
? NULL
|
||||
: StateManager::get()->getActivePlayer(0);
|
||||
// Reset the ai kart list in the race manager, otherwise in network race
|
||||
// we can get an assertion if previously a local race with AI was done
|
||||
std::vector<std::string> ai_kart_list;
|
||||
race_manager->setAIKartList(ai_kart_list);
|
||||
input_manager->getDeviceManager()->setSinglePlayer(ap);
|
||||
|
||||
// Load the actual world.
|
||||
m_game_setup->loadWorld();
|
||||
World::getWorld()->setNetworkWorld(true);
|
||||
GameProtocol::createInstance()->requestStart();
|
||||
std::make_shared<GameEventsProtocol>()->requestStart();
|
||||
gep->requestStart();
|
||||
|
||||
} // loadWorld
|
||||
|
||||
@ -134,6 +132,8 @@ void LobbyProtocol::configRemoteKart(
|
||||
// Inform the race manager about the data for this kart.
|
||||
race_manager->setPlayerKart(i, rki);
|
||||
} // for i in players
|
||||
// Clean all previous AI if exists in offline game
|
||||
race_manager->computeRandomKartList();
|
||||
Log::info("LobbyProtocol", "Player configuration ready.");
|
||||
} // configRemoteKart
|
||||
|
||||
@ -143,7 +143,5 @@ void LobbyProtocol::configRemoteKart(
|
||||
*/
|
||||
void LobbyProtocol::setup()
|
||||
{
|
||||
if (m_game_setup)
|
||||
delete m_game_setup;
|
||||
m_game_setup = new GameSetup();
|
||||
m_game_setup->reset();
|
||||
} // setupNewGame
|
||||
|
@ -43,9 +43,8 @@ public:
|
||||
LE_CONNECTION_REQUESTED = 1, // a connection to the server
|
||||
LE_CONNECTION_REFUSED, // Connection to server refused
|
||||
LE_CONNECTION_ACCEPTED, // Connection to server accepted
|
||||
LE_KART_SELECTION_UPDATE, // inform client about kart selected
|
||||
LE_SERVER_INFO, // inform client about server info
|
||||
LE_REQUEST_BEGIN, // begin of kart selection
|
||||
LE_KART_SELECTION_REFUSED, // Client not auth. to start selection
|
||||
LE_UPDATE_PLAYER_LIST, // inform client about player list update
|
||||
LE_KART_SELECTION, // Player selected kart
|
||||
LE_PLAYER_DISCONNECTED, // Client disconnected
|
||||
@ -114,6 +113,7 @@ public:
|
||||
virtual void finishedLoadingWorld() = 0;
|
||||
virtual void loadWorld();
|
||||
virtual bool waitingForPlayers() const = 0;
|
||||
virtual bool allPlayersReady() const = 0;
|
||||
GameSetup* getGameSetup() const { return m_game_setup; }
|
||||
|
||||
}; // class LobbyProtocol
|
||||
|
@ -20,13 +20,14 @@
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "network/protocols/connect_to_peer.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/game_protocol.hpp"
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
@ -106,6 +107,7 @@ ServerLobby::~ServerLobby()
|
||||
void ServerLobby::setup()
|
||||
{
|
||||
LobbyProtocol::setup();
|
||||
StateManager::get()->resetActivePlayers();
|
||||
// We use maximum 16bit unsigned limit
|
||||
auto all_k = kart_properties_manager->getAllAvailableKarts();
|
||||
auto all_t = track_manager->getAllTrackIdentifiers();
|
||||
@ -122,7 +124,7 @@ void ServerLobby::setup()
|
||||
// Initialise the data structures to detect if all clients and
|
||||
// the server are ready:
|
||||
m_server_has_loaded_world.store(false);
|
||||
m_peers_ready.clear();
|
||||
resetPeersReady();
|
||||
m_peers_votes.clear();
|
||||
m_server_delay = 0.0;
|
||||
Log::info("ServerLobby", "Reset server to initial state.");
|
||||
@ -144,6 +146,7 @@ bool ServerLobby::notifyEvent(Event* event)
|
||||
switch (message_type)
|
||||
{
|
||||
case LE_REQUEST_BEGIN: startSelection(event); break;
|
||||
case LE_RACE_FINISHED_ACK: playerFinishedResult(event); break;
|
||||
default: Log::error("ServerLobby", "Unknown message type %d - ignored.",
|
||||
message_type);
|
||||
break;
|
||||
@ -205,7 +208,6 @@ bool ServerLobby::notifyEventAsynchronous(Event* event)
|
||||
case LE_CLIENT_LOADED_WORLD: finishedLoadingWorldClient(event); break;
|
||||
case LE_STARTED_RACE: startedRaceOnClient(event); break;
|
||||
case LE_VOTE: playerVote(event); break;
|
||||
case LE_RACE_FINISHED_ACK: playerFinishedResult(event); break;
|
||||
case LE_KICK_HOST: kickHost(event); break;
|
||||
case LE_CHAT: handleChat(event); break;
|
||||
default: break;
|
||||
@ -256,6 +258,7 @@ void ServerLobby::asynchronousUpdate()
|
||||
}
|
||||
else
|
||||
{
|
||||
m_server_address.copy(STKHost::get()->getPublicAddress());
|
||||
STKHost::get()->startListening();
|
||||
m_state = REGISTER_SELF_ADDRESS;
|
||||
}
|
||||
@ -298,10 +301,7 @@ void ServerLobby::asynchronousUpdate()
|
||||
return;
|
||||
m_state = WAIT_FOR_RACE_STARTED;
|
||||
// Reset for next state usage
|
||||
for (auto p : m_peers_ready)
|
||||
{
|
||||
p.second = false;
|
||||
}
|
||||
resetPeersReady();
|
||||
signalRaceStartToClients();
|
||||
break;
|
||||
}
|
||||
@ -351,10 +351,7 @@ void ServerLobby::asynchronousUpdate()
|
||||
configRemoteKart(players);
|
||||
|
||||
// Reset for next state usage
|
||||
for (auto p : m_peers_ready)
|
||||
{
|
||||
p.second = false;
|
||||
}
|
||||
resetPeersReady();
|
||||
m_state = LOAD_WORLD;
|
||||
sendMessageToPeersChangingToken(load_world);
|
||||
delete load_world;
|
||||
@ -366,21 +363,6 @@ void ServerLobby::asynchronousUpdate()
|
||||
|
||||
} // asynchronousUpdate
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ServerLobby::checkPeersReady() const
|
||||
{
|
||||
bool all_ready = true;
|
||||
for (auto p : m_peers_ready)
|
||||
{
|
||||
if (p.first.expired())
|
||||
continue;
|
||||
all_ready = all_ready && p.second;
|
||||
if (!all_ready)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // checkPeersReady
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Simple finite state machine. Once this
|
||||
* is known, register the server and its address with the stk server so that
|
||||
@ -388,6 +370,22 @@ bool ServerLobby::checkPeersReady() const
|
||||
*/
|
||||
void ServerLobby::update(int ticks)
|
||||
{
|
||||
// Reset server to initial state if no more connected players
|
||||
if (m_state.load() > ACCEPTING_CLIENTS &&
|
||||
STKHost::get()->getPeerCount() == 0 &&
|
||||
NetworkConfig::get()->getServerIdFile().empty())
|
||||
{
|
||||
if (RaceEventManager::getInstance() &&
|
||||
RaceEventManager::getInstance()->isRunning())
|
||||
{
|
||||
stopCurrentRace();
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(m_connection_mutex);
|
||||
m_state = NetworkConfig::get()->isLAN() ?
|
||||
ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
|
||||
setup();
|
||||
}
|
||||
|
||||
// Check if server owner has left
|
||||
updateServerOwner();
|
||||
if (m_game_setup)
|
||||
@ -402,7 +400,7 @@ void ServerLobby::update(int ticks)
|
||||
case REGISTER_SELF_ADDRESS:
|
||||
case ACCEPTING_CLIENTS:
|
||||
case WAIT_FOR_WORLD_LOADED:
|
||||
case WAIT_FOR_RACE_STARTED:
|
||||
case WAIT_FOR_RACE_STARTED:
|
||||
case DELAY_SERVER:
|
||||
{
|
||||
// Waiting for asynchronousUpdate
|
||||
@ -426,20 +424,9 @@ void ServerLobby::update(int ticks)
|
||||
}
|
||||
break;
|
||||
case RESULT_DISPLAY:
|
||||
if(StkTime::getRealTime() > m_timeout.load())
|
||||
if (checkPeersReady() ||
|
||||
StkTime::getRealTime() > m_timeout.load())
|
||||
{
|
||||
RaceResultGUI::getInstance()->backToLobby();
|
||||
// notify the network world that it is stopped
|
||||
RaceEventManager::getInstance()->stop();
|
||||
// stop race protocols
|
||||
auto pm = ProtocolManager::lock();
|
||||
assert(pm);
|
||||
pm->findAndTerminate(PROTOCOL_CONTROLLER_EVENTS);
|
||||
pm->findAndTerminate(PROTOCOL_KART_UPDATE);
|
||||
pm->findAndTerminate(PROTOCOL_GAME_EVENTS);
|
||||
setup();
|
||||
m_state = NetworkConfig::get()->isLAN() ?
|
||||
ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
|
||||
// Send a notification to all clients to exit
|
||||
// the race result screen
|
||||
NetworkString *exit_result_screen = getNetworkString(1);
|
||||
@ -448,6 +435,17 @@ void ServerLobby::update(int ticks)
|
||||
sendMessageToPeersChangingToken(exit_result_screen,
|
||||
/*reliable*/true);
|
||||
delete exit_result_screen;
|
||||
std::lock_guard<std::mutex> lock(m_connection_mutex);
|
||||
m_state = NetworkConfig::get()->isLAN() ?
|
||||
ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
|
||||
updatePlayerList();
|
||||
NetworkString* server_info = getNetworkString();
|
||||
server_info->setSynchronous(true);
|
||||
server_info->addUInt8(LE_SERVER_INFO);
|
||||
m_game_setup->addServerInfo(server_info);
|
||||
sendMessageToPeersChangingToken(server_info);
|
||||
delete server_info;
|
||||
setup();
|
||||
}
|
||||
break;
|
||||
case ERROR_LEAVE:
|
||||
@ -466,25 +464,23 @@ void ServerLobby::update(int ticks)
|
||||
void ServerLobby::registerServer()
|
||||
{
|
||||
Online::XMLRequest *request = new Online::XMLRequest();
|
||||
const TransportAddress& addr = STKHost::get()->getPublicAddress();
|
||||
NetworkConfig::get()->setUserDetails(request, "create");
|
||||
request->addParameter("address", addr.getIP() );
|
||||
request->addParameter("port", addr.getPort() );
|
||||
request->addParameter("address", m_server_address.getIP() );
|
||||
request->addParameter("port", m_server_address.getPort() );
|
||||
request->addParameter("private_port",
|
||||
STKHost::get()->getPrivatePort() );
|
||||
request->addParameter("name", NetworkConfig::get()->getServerName() );
|
||||
request->addParameter("max_players",
|
||||
NetworkConfig::get()->getMaxPlayers());
|
||||
request->addParameter("difficulty", race_manager->getDifficulty());
|
||||
request->addParameter("game_mode",
|
||||
NetworkConfig::get()->getServerGameMode(race_manager->getMinorMode(),
|
||||
race_manager->getMajorMode()));
|
||||
request->addParameter("game_mode", NetworkConfig::get()->getServerMode());
|
||||
request->addParameter("password",
|
||||
(unsigned)(!NetworkConfig::get()->getPassword().empty()));
|
||||
request->addParameter("version",
|
||||
(unsigned)NetworkConfig::m_server_version);
|
||||
|
||||
Log::info("ServerLobby", "Public server addr %s", addr.toString().c_str());
|
||||
Log::info("ServerLobby", "Public server address %s",
|
||||
m_server_address.toString().c_str());
|
||||
|
||||
request->executeNow();
|
||||
|
||||
@ -511,14 +507,13 @@ void ServerLobby::registerServer()
|
||||
*/
|
||||
void ServerLobby::unregisterServer()
|
||||
{
|
||||
const TransportAddress &addr = STKHost::get()->getPublicAddress();
|
||||
Online::XMLRequest* request = new Online::XMLRequest();
|
||||
NetworkConfig::get()->setUserDetails(request, "stop");
|
||||
|
||||
request->addParameter("address", addr.getIP());
|
||||
request->addParameter("port", addr.getPort());
|
||||
|
||||
Log::info("ServerLobby", "address %s", addr.toString().c_str());
|
||||
request->addParameter("address", m_server_address.getIP());
|
||||
request->addParameter("port", m_server_address.getPort());
|
||||
Log::info("ServerLobby", "Unregister server address %s",
|
||||
m_server_address.toString().c_str());
|
||||
request->executeNow();
|
||||
|
||||
const XMLNode * result = request->getXMLData();
|
||||
@ -593,6 +588,24 @@ void ServerLobby::startSelection(const Event *event)
|
||||
// a new screen, which must be donefrom the main thread.
|
||||
ns->setSynchronous(true);
|
||||
ns->addUInt8(LE_START_SELECTION);
|
||||
|
||||
// Remove karts / tracks from server that are not supported on all clients
|
||||
std::set<std::string> karts_erase, tracks_erase;
|
||||
auto peers = STKHost::get()->getPeers();
|
||||
for (auto peer : peers)
|
||||
{
|
||||
peer->eraseServerKarts(m_available_kts.first, karts_erase);
|
||||
peer->eraseServerTracks(m_available_kts.second, tracks_erase);
|
||||
}
|
||||
for (const std::string& kart_erase : karts_erase)
|
||||
{
|
||||
m_available_kts.first.erase(kart_erase);
|
||||
}
|
||||
for (const std::string& track_erase : tracks_erase)
|
||||
{
|
||||
m_available_kts.second.erase(track_erase);
|
||||
}
|
||||
|
||||
const auto& all_k = m_available_kts.first;
|
||||
const auto& all_t = m_available_kts.second;
|
||||
ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size());
|
||||
@ -672,51 +685,60 @@ void ServerLobby::checkIncomingConnectionRequests()
|
||||
* to state RESULT_DISPLAY, during which the race result gui is shown and all
|
||||
* clients can click on 'continue'.
|
||||
*/
|
||||
void ServerLobby::checkRaceFinished()
|
||||
void ServerLobby::checkRaceFinished()
|
||||
{
|
||||
assert(RaceEventManager::getInstance()->isRunning());
|
||||
assert(World::getWorld());
|
||||
if(!RaceEventManager::getInstance()->isRaceOver()) return;
|
||||
if (!RaceEventManager::getInstance()->isRaceOver()) return;
|
||||
|
||||
m_player_ready_counter = 0;
|
||||
// Set the delay before the server forces all clients to exit the race
|
||||
// result screen and go back to the lobby
|
||||
m_timeout.store((float)(StkTime::getRealTime()+15.0f));
|
||||
m_state = RESULT_DISPLAY;
|
||||
|
||||
// calculate karts ranks :
|
||||
int num_karts = race_manager->getNumberOfKarts();
|
||||
std::vector<int> karts_results;
|
||||
std::vector<float> karts_times;
|
||||
for (int j = 0; j < num_karts; j++)
|
||||
{
|
||||
float kart_time = race_manager->getKartRaceTime(j);
|
||||
for (unsigned int i = 0; i < karts_times.size(); i++)
|
||||
{
|
||||
if (kart_time < karts_times[i])
|
||||
{
|
||||
karts_times.insert(karts_times.begin() + i, kart_time);
|
||||
karts_results.insert(karts_results.begin() + i, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetworkString *total = getNetworkString(1 + karts_results.size());
|
||||
// Reset for next state usage
|
||||
resetPeersReady();
|
||||
NetworkString* total = getNetworkString();
|
||||
total->setSynchronous(true);
|
||||
total->addUInt8(LE_RACE_FINISHED);
|
||||
for (unsigned int i = 0; i < karts_results.size(); i++)
|
||||
if (m_game_setup->isGrandPrix())
|
||||
{
|
||||
total->addUInt8(karts_results[i]); // kart pos = i+1
|
||||
Log::info("ServerLobby", "Kart %d finished #%d",
|
||||
karts_results[i], i + 1);
|
||||
// fastest lap, and than each kart before / after grand prix points
|
||||
}
|
||||
else if (race_manager->modeHasLaps())
|
||||
{
|
||||
int fastest_lap =
|
||||
static_cast<LinearWorld*>(World::getWorld())->getFastestLapTicks();
|
||||
total->addUInt32(fastest_lap);
|
||||
}
|
||||
|
||||
stopCurrentRace();
|
||||
// Set the delay before the server forces all clients to exit the race
|
||||
// result screen and go back to the lobby
|
||||
m_timeout.store((float)StkTime::getRealTime() + 15.0f);
|
||||
m_state = RESULT_DISPLAY;
|
||||
sendMessageToPeersChangingToken(total, /*reliable*/ true);
|
||||
delete total;
|
||||
Log::info("ServerLobby", "End of game message sent");
|
||||
|
||||
|
||||
} // checkRaceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Stop any race currently in server, should only be called in main thread.
|
||||
*/
|
||||
void ServerLobby::stopCurrentRace()
|
||||
{
|
||||
// notify the network world that it is stopped
|
||||
RaceEventManager::getInstance()->stop();
|
||||
|
||||
// stop race protocols before going back to lobby (end race)
|
||||
RaceEventManager::getInstance()->getProtocol()->requestTerminate();
|
||||
GameProtocol::lock()->requestTerminate();
|
||||
|
||||
while (!RaceEventManager::getInstance()->protocolStopped())
|
||||
StkTime::sleep(1);
|
||||
while (!GameProtocol::emptyInstance())
|
||||
StkTime::sleep(1);
|
||||
|
||||
// This will go back to lobby in server (and exit the current race)
|
||||
RaceResultGUI::getInstance()->backToLobby();
|
||||
} // stopCurrentRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called when a client disconnects.
|
||||
* \param event The disconnect event.
|
||||
@ -775,6 +797,21 @@ void ServerLobby::connectionRequested(Event* event)
|
||||
return;
|
||||
}
|
||||
|
||||
// Check server version
|
||||
int version = data.getUInt8();
|
||||
if (version < stk_config->m_max_server_version ||
|
||||
version > stk_config->m_max_server_version)
|
||||
{
|
||||
NetworkString *message = getNetworkString(2);
|
||||
message->addUInt8(LE_CONNECTION_REFUSED)
|
||||
.addUInt8(RR_INCOMPATIBLE_DATA);
|
||||
peer->sendPacket(message);
|
||||
peer->reset();
|
||||
delete message;
|
||||
Log::verbose("ServerLobby", "Player refused: wrong server version");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for password
|
||||
std::string password;
|
||||
data.decodeString(&password);
|
||||
@ -869,9 +906,8 @@ void ServerLobby::connectionRequested(Event* event)
|
||||
client_tracks.insert(track);
|
||||
}
|
||||
|
||||
// Remove karts/tracks from server that are not supported on the new client
|
||||
// so that in the end the server has a list of all karts/tracks available
|
||||
// on all clients
|
||||
// Drop this player if he doesn't have at least 1 kart / track the same
|
||||
// as server
|
||||
std::set<std::string> karts_erase, tracks_erase;
|
||||
for (const std::string& server_kart : m_available_kts.first)
|
||||
{
|
||||
@ -888,8 +924,6 @@ void ServerLobby::connectionRequested(Event* event)
|
||||
}
|
||||
}
|
||||
|
||||
// Drop this player if he doesn't have at least 1 kart / track the same
|
||||
// from server
|
||||
if (karts_erase.size() == m_available_kts.first.size() ||
|
||||
tracks_erase.size() == m_available_kts.second.size())
|
||||
{
|
||||
@ -904,14 +938,9 @@ void ServerLobby::connectionRequested(Event* event)
|
||||
return;
|
||||
}
|
||||
|
||||
for (const std::string& kart_erase : karts_erase)
|
||||
{
|
||||
m_available_kts.first.erase(kart_erase);
|
||||
}
|
||||
for (const std::string& track_erase : tracks_erase)
|
||||
{
|
||||
m_available_kts.second.erase(track_erase);
|
||||
}
|
||||
// Save available karts and tracks from clients in STKPeer so if this peer
|
||||
// disconnects later in lobby it won't affect current players
|
||||
peer->setAvailableKartsTracks(client_karts, client_tracks);
|
||||
|
||||
if (!peer->isClientServerTokenSet())
|
||||
{
|
||||
@ -926,13 +955,22 @@ void ServerLobby::connectionRequested(Event* event)
|
||||
|
||||
peer->setClientServerToken(token);
|
||||
}
|
||||
|
||||
// send a message to the one that asked to connect
|
||||
NetworkString *message_ack = getNetworkString(4);
|
||||
NetworkString* message_ack = getNetworkString(4);
|
||||
message_ack->setSynchronous(true);
|
||||
// connection success -- return the host id of peer
|
||||
message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt32(peer->getHostId());
|
||||
peer->sendPacket(message_ack);
|
||||
delete message_ack;
|
||||
|
||||
NetworkString* server_info = getNetworkString();
|
||||
server_info->setSynchronous(true);
|
||||
server_info->addUInt8(LE_SERVER_INFO);
|
||||
m_game_setup->addServerInfo(server_info);
|
||||
peer->sendPacket(server_info);
|
||||
delete server_info;
|
||||
|
||||
m_peers_ready[peer] = false;
|
||||
for (std::shared_ptr<NetworkPlayerProfile> npp : peer->getPlayerProfiles())
|
||||
{
|
||||
@ -947,7 +985,7 @@ void ServerLobby::connectionRequested(Event* event)
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::updatePlayerList()
|
||||
{
|
||||
if (m_state.load() != ACCEPTING_CLIENTS)
|
||||
if (m_state.load() > ACCEPTING_CLIENTS)
|
||||
return;
|
||||
auto all_profiles = STKHost::get()->getAllPlayerProfiles();
|
||||
NetworkString* pl = getNetworkString();
|
||||
@ -1045,7 +1083,7 @@ void ServerLobby::kartSelectionRequested(Event* event)
|
||||
{
|
||||
peer->getPlayerProfiles()[i]->setKartName(kart);
|
||||
}
|
||||
Log::verbose("ServerLobby", "Player %d from peer %d chose %s", i,
|
||||
Log::debug("ServerLobby", "Player %d from peer %d chose %s", i,
|
||||
peer->getHostId(), kart.c_str());
|
||||
}
|
||||
} // kartSelectionRequested
|
||||
@ -1083,8 +1121,8 @@ void ServerLobby::playerVote(Event* event)
|
||||
NetworkString other = NetworkString(PROTOCOL_LOBBY_ROOM);
|
||||
std::string name = StringUtils::wideToUtf8(event->getPeer()
|
||||
->getPlayerProfiles()[0]->getName());
|
||||
other.addUInt8(LE_VOTE).addFloat(m_timeout.load()).encodeString(name)
|
||||
.addUInt32(event->getPeer()->getHostId());
|
||||
other.addUInt8(LE_VOTE).addFloat(UserConfigParams::m_voting_timeout)
|
||||
.encodeString(name).addUInt32(event->getPeer()->getHostId());
|
||||
other += data;
|
||||
|
||||
std::string track_name;
|
||||
@ -1227,14 +1265,10 @@ void ServerLobby::startedRaceOnClient(Event *event)
|
||||
*/
|
||||
void ServerLobby::playerFinishedResult(Event *event)
|
||||
{
|
||||
m_player_ready_counter++;
|
||||
if(m_player_ready_counter >= (int)STKHost::get()->getPeerCount())
|
||||
{
|
||||
// We can't trigger the world/race exit here, since this is called
|
||||
// from the protocol manager thread. So instead we force the timeout
|
||||
// to get triggered (which is done from the main thread):
|
||||
m_timeout.store(0);
|
||||
}
|
||||
if (m_state.load() != RESULT_DISPLAY)
|
||||
return;
|
||||
std::shared_ptr<STKPeer> peer = event->getPeerSP();
|
||||
m_peers_ready.at(peer) = true;
|
||||
} // playerFinishedResult
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define SERVER_LOBBY_HPP
|
||||
|
||||
#include "network/protocols/lobby_protocol.hpp"
|
||||
#include "network/transport_address.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
#include <atomic>
|
||||
@ -65,9 +66,6 @@ private:
|
||||
/** It indicates if this server is registered with the stk server. */
|
||||
std::atomic_bool m_server_registered;
|
||||
|
||||
/** Counts how many players are ready to go on. */
|
||||
int m_player_ready_counter;
|
||||
|
||||
/** Timeout counter for various state. */
|
||||
std::atomic<float> m_timeout;
|
||||
|
||||
@ -78,6 +76,8 @@ private:
|
||||
/** Ban list ip (in decimal) with online user id. */
|
||||
std::map<uint32_t, uint32_t> m_ban_list;
|
||||
|
||||
TransportAddress m_server_address;
|
||||
|
||||
// connection management
|
||||
void clientDisconnected(Event* event);
|
||||
void connectionRequested(Event* event);
|
||||
@ -95,8 +95,36 @@ private:
|
||||
void createServerIdFile();
|
||||
void updatePlayerList();
|
||||
void updateServerOwner();
|
||||
bool checkPeersReady() const;
|
||||
bool checkPeersReady() const
|
||||
{
|
||||
bool all_ready = true;
|
||||
for (auto p : m_peers_ready)
|
||||
{
|
||||
if (p.first.expired())
|
||||
continue;
|
||||
all_ready = all_ready && p.second;
|
||||
if (!all_ready)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void resetPeersReady()
|
||||
{
|
||||
for (auto it = m_peers_ready.begin(); it != m_peers_ready.end();)
|
||||
{
|
||||
if (it->first.expired())
|
||||
{
|
||||
it = m_peers_ready.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second = false;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::tuple<std::string, uint8_t, bool> handleVote();
|
||||
void stopCurrentRace();
|
||||
|
||||
public:
|
||||
ServerLobby();
|
||||
@ -117,6 +145,8 @@ public:
|
||||
void updateBanList();
|
||||
virtual bool waitingForPlayers() const OVERRIDE
|
||||
{ return m_state.load() == ACCEPTING_CLIENTS; }
|
||||
virtual bool allPlayersReady() const OVERRIDE
|
||||
{ return m_state.load() >= WAIT_FOR_RACE_STARTED; }
|
||||
|
||||
}; // class ServerLobby
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "karts/controller/controller.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "utils/profiler.hpp"
|
||||
@ -26,18 +25,13 @@ RaceEventManager::~RaceEventManager()
|
||||
*/
|
||||
void RaceEventManager::update(int ticks)
|
||||
{
|
||||
// Replay all recorded events up to the current time (only if the
|
||||
// timer isn't stopped, otherwise a potential rewind will trigger
|
||||
// an infinite loop since world time does not increase)
|
||||
if (World::getWorld()->getPhase() != WorldStatus::IN_GAME_MENU_PHASE)
|
||||
{
|
||||
// This might adjust dt - if a new state is being played, the dt is
|
||||
// determined from the last state till 'now'
|
||||
PROFILER_PUSH_CPU_MARKER("RaceEvent:play event", 100, 100, 100);
|
||||
RewindManager::get()->playEventsTill(World::getWorld()->getTimeTicks(),
|
||||
&ticks);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
// Replay all recorded events up to the current time
|
||||
// This might adjust dt - if a new state is being played, the dt is
|
||||
// determined from the last state till 'now'
|
||||
PROFILER_PUSH_CPU_MARKER("RaceEvent:play event", 100, 100, 100);
|
||||
RewindManager::get()->playEventsTill(World::getWorld()->getTimeTicks(),
|
||||
&ticks);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
World::getWorld()->updateWorld(ticks);
|
||||
|
||||
// if the race is over
|
||||
@ -50,18 +44,6 @@ void RaceEventManager::update(int ticks)
|
||||
}
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void RaceEventManager::start()
|
||||
{
|
||||
m_running = true;
|
||||
} // start
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void RaceEventManager::stop()
|
||||
{
|
||||
m_running = false;
|
||||
} // stop
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool RaceEventManager::isRaceOver()
|
||||
{
|
||||
@ -74,9 +56,8 @@ bool RaceEventManager::isRaceOver()
|
||||
// ----------------------------------------------------------------------------
|
||||
void RaceEventManager::kartFinishedRace(AbstractKart *kart, float time)
|
||||
{
|
||||
auto protocol = std::static_pointer_cast<GameEventsProtocol>(
|
||||
ProtocolManager::lock()->getProtocol(PROTOCOL_GAME_EVENTS));
|
||||
protocol->kartFinishedRace(kart, time);
|
||||
if (auto game_events_protocol = m_game_events_protocol.lock())
|
||||
game_events_protocol->kartFinishedRace(kart, time);
|
||||
} // kartFinishedRace
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -89,9 +70,7 @@ void RaceEventManager::collectedItem(Item *item, AbstractKart *kart)
|
||||
{
|
||||
// this is only called in the server
|
||||
assert(NetworkConfig::get()->isServer());
|
||||
|
||||
auto protocol = std::static_pointer_cast<GameEventsProtocol>(
|
||||
ProtocolManager::lock()->getProtocol(PROTOCOL_GAME_EVENTS));
|
||||
protocol->collectedItem(item,kart);
|
||||
if (auto game_events_protocol = m_game_events_protocol.lock())
|
||||
game_events_protocol->collectedItem(item, kart);
|
||||
} // collectedItem
|
||||
|
||||
|
@ -21,10 +21,10 @@
|
||||
|
||||
#include "input/input.hpp"
|
||||
#include "utils/singleton.hpp"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class Controller;
|
||||
class KartUpdateProtocol;
|
||||
class GameEventsProtocol;
|
||||
class AbstractKart;
|
||||
class Item;
|
||||
|
||||
@ -40,23 +40,38 @@ private:
|
||||
bool m_running;
|
||||
float m_race_time;
|
||||
|
||||
std::weak_ptr<GameEventsProtocol> m_game_events_protocol;
|
||||
|
||||
friend class AbstractSingleton<RaceEventManager>;
|
||||
|
||||
RaceEventManager();
|
||||
virtual ~RaceEventManager();
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
void update(int ticks);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
bool isRaceOver();
|
||||
|
||||
void collectedItem(Item *item, AbstractKart *kart);
|
||||
void kartFinishedRace(AbstractKart *kart, float time);
|
||||
// ------------------------------------------------------------------------
|
||||
void start(std::shared_ptr<GameEventsProtocol> gep)
|
||||
{
|
||||
m_game_events_protocol = gep;
|
||||
m_running = true;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void stop() { m_running = false; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if this instance is in running state or not. */
|
||||
bool isRunning() { return m_running; }
|
||||
bool isRunning() { return m_running; }
|
||||
// ------------------------------------------------------------------------
|
||||
std::shared_ptr<GameEventsProtocol> getProtocol() const
|
||||
{ return m_game_events_protocol.lock(); }
|
||||
// ------------------------------------------------------------------------
|
||||
bool protocolStopped() const { return m_game_events_protocol.expired(); }
|
||||
// ------------------------------------------------------------------------
|
||||
bool isRaceOver();
|
||||
// ------------------------------------------------------------------------
|
||||
void collectedItem(Item *item, AbstractKart *kart);
|
||||
// ------------------------------------------------------------------------
|
||||
void kartFinishedRace(AbstractKart *kart, float time);
|
||||
|
||||
};
|
||||
|
||||
|
@ -346,15 +346,6 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
|
||||
// Now start the rewind with the full state:
|
||||
world->setTicks(exact_rewind_ticks);
|
||||
|
||||
// Need to exit loop if in-game menu is open, since world clock
|
||||
// will not be increased while the game is paused
|
||||
if (World::getWorld()->getPhase() == WorldStatus::IN_GAME_MENU_PHASE)
|
||||
{
|
||||
m_is_rewinding = false;
|
||||
history->setReplayHistory(is_history);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the (first) full state to which we have to rewind
|
||||
RewindInfo *current = m_rewind_queue.getCurrent();
|
||||
assert(current->isState());
|
||||
@ -395,5 +386,3 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
|
||||
history->setReplayHistory(is_history);
|
||||
m_is_rewinding = false;
|
||||
} // rewindTo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
@ -39,10 +39,9 @@ Server::Server(const XMLNode& xml)
|
||||
m_current_players = 0;
|
||||
m_max_players = 0;
|
||||
m_distance = 0.0f;
|
||||
m_server_mode = 0;
|
||||
xml.get("game_mode", &m_server_mode);
|
||||
unsigned server_data = 0;
|
||||
xml.get("game_mode", &server_data);
|
||||
m_minor_mode = NetworkConfig::get()->getLocalGameMode(server_data).first;
|
||||
m_major_mode = NetworkConfig::get()->getLocalGameMode(server_data).second;
|
||||
xml.get("difficulty", &server_data);
|
||||
m_difficulty = (RaceManager::Difficulty)server_data;
|
||||
|
||||
@ -121,8 +120,7 @@ Server::Server(unsigned server_id, const core::stringw &name, int max_players,
|
||||
// In case of LAN server, public and private port are the same.
|
||||
m_private_port = m_address.getPort();
|
||||
m_difficulty = (RaceManager::Difficulty)difficulty;
|
||||
m_minor_mode = NetworkConfig::get()->getLocalGameMode(server_mode).first;
|
||||
m_major_mode = NetworkConfig::get()->getLocalGameMode(server_mode).second;
|
||||
m_server_mode = server_mode;
|
||||
m_password_protected = password_protected;
|
||||
m_distance = 0.0f;
|
||||
} // server(server_id, ...)
|
||||
|
@ -68,9 +68,7 @@ protected:
|
||||
* connection using the private port with a broadcast is possible. */
|
||||
uint16_t m_private_port;
|
||||
|
||||
RaceManager::MinorRaceModeType m_minor_mode;
|
||||
|
||||
RaceManager::MajorRaceModeType m_major_mode;
|
||||
unsigned m_server_mode;
|
||||
|
||||
RaceManager::Difficulty m_difficulty;
|
||||
|
||||
@ -115,11 +113,7 @@ public:
|
||||
/** Returns the number of currently connected players. */
|
||||
const int getCurrentPlayers() const { return m_current_players; }
|
||||
// ------------------------------------------------------------------------
|
||||
RaceManager::MinorRaceModeType getRaceMinorMode() const
|
||||
{ return m_minor_mode; }
|
||||
// ------------------------------------------------------------------------
|
||||
RaceManager::MajorRaceModeType getRaceMajorMode() const
|
||||
{ return m_major_mode; }
|
||||
unsigned getServerMode() const { return m_server_mode; }
|
||||
// ------------------------------------------------------------------------
|
||||
RaceManager::Difficulty getDifficulty() const { return m_difficulty; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "network/servers_manager.hpp"
|
||||
|
||||
#include "config/stk_config.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "network/network.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
@ -160,8 +161,9 @@ Online::XMLRequest* ServersManager::getLANRefreshRequest() const
|
||||
if (len > 0)
|
||||
{
|
||||
BareNetworkString s(buffer, len);
|
||||
uint8_t version = s.getUInt8();
|
||||
if (version != NetworkConfig::m_server_version)
|
||||
int version = s.getUInt8();
|
||||
if (version < stk_config->m_max_server_version ||
|
||||
version > stk_config->m_max_server_version)
|
||||
{
|
||||
Log::verbose("ServersManager", "Skipping a server");
|
||||
continue;
|
||||
@ -236,10 +238,11 @@ void ServersManager::setWanServers(bool success, const XMLNode* input)
|
||||
const XMLNode *servers_xml = input->getNode("servers");
|
||||
for (unsigned int i = 0; i < servers_xml->getNumNodes(); i++)
|
||||
{
|
||||
unsigned version = 0;
|
||||
int version = 0;
|
||||
servers_xml->getNode(i)->get("version", &version);
|
||||
assert(version != 0);
|
||||
if (version != NetworkConfig::m_server_version)
|
||||
if (version < stk_config->m_max_server_version ||
|
||||
version > stk_config->m_max_server_version)
|
||||
{
|
||||
Log::verbose("ServersManager", "Skipping a server");
|
||||
continue;
|
||||
|
@ -67,25 +67,27 @@
|
||||
STKHost *STKHost::m_stk_host = NULL;
|
||||
bool STKHost::m_enable_console = false;
|
||||
|
||||
void STKHost::create(std::shared_ptr<Server> server, SeparateProcess* p)
|
||||
std::shared_ptr<LobbyProtocol> STKHost::create(SeparateProcess* p)
|
||||
{
|
||||
assert(m_stk_host == NULL);
|
||||
std::shared_ptr<LobbyProtocol> lp;
|
||||
if (NetworkConfig::get()->isServer())
|
||||
{
|
||||
std::shared_ptr<ServerLobby> sl = LobbyProtocol::create<ServerLobby>();
|
||||
m_stk_host = new STKHost(NetworkConfig::get()->getServerName());
|
||||
sl->requestStart();
|
||||
lp = LobbyProtocol::create<ServerLobby>();
|
||||
m_stk_host = new STKHost(true/*server*/);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stk_host = new STKHost(server);
|
||||
m_stk_host = new STKHost(false/*server*/);
|
||||
}
|
||||
// Separate process for client-server gui if exists
|
||||
m_stk_host->m_separate_process = p;
|
||||
if (!m_stk_host->m_network)
|
||||
{
|
||||
delete m_stk_host;
|
||||
m_stk_host = NULL;
|
||||
}
|
||||
return lp;
|
||||
} // create
|
||||
|
||||
// ============================================================================
|
||||
@ -258,57 +260,42 @@ void STKHost::create(std::shared_ptr<Server> server, SeparateProcess* p)
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
/** Constructor for a client
|
||||
/** The constructor for a server or client.
|
||||
*/
|
||||
STKHost::STKHost(std::shared_ptr<Server> server)
|
||||
{
|
||||
// Will be overwritten with the correct value once a connection with the
|
||||
// server is made.
|
||||
m_host_id = 0;
|
||||
init();
|
||||
|
||||
ENetAddress ea;
|
||||
ea.host = STKHost::HOST_ANY;
|
||||
ea.port = NetworkConfig::get()->getClientPort();
|
||||
|
||||
m_network = new Network(/*peer_count*/1, /*channel_limit*/2,
|
||||
/*max_in_bandwidth*/0, /*max_out_bandwidth*/0,
|
||||
&ea, true/*change_port_if_bound*/);
|
||||
if (!m_network)
|
||||
{
|
||||
Log::fatal ("STKHost", "An error occurred while trying to create "
|
||||
"an ENet client host.");
|
||||
}
|
||||
|
||||
setPrivatePort();
|
||||
} // STKHost
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** The constructor for a server.
|
||||
* The server control flow starts with the ServerLobby.
|
||||
*/
|
||||
STKHost::STKHost(const irr::core::stringw &server_name)
|
||||
STKHost::STKHost(bool server)
|
||||
{
|
||||
init();
|
||||
m_host_id = 0; // indicates a server host.
|
||||
|
||||
ENetAddress addr;
|
||||
addr.host = STKHost::HOST_ANY;
|
||||
addr.port = NetworkConfig::get()->getServerPort();
|
||||
|
||||
// Reserver 1 peer to handle full server message
|
||||
m_network = new Network(NetworkConfig::get()->getMaxPlayers() + 1,
|
||||
/*channel_limit*/2,
|
||||
/*max_in_bandwidth*/0,
|
||||
/*max_out_bandwidth*/ 0, &addr,
|
||||
true/*change_port_if_bound*/);
|
||||
if (server)
|
||||
{
|
||||
addr.port = NetworkConfig::get()->getServerPort();
|
||||
// Reserve 1 peer to deliver full server message
|
||||
m_network = new Network(NetworkConfig::get()->getMaxPlayers() + 1,
|
||||
/*channel_limit*/2, /*max_in_bandwidth*/0,
|
||||
/*max_out_bandwidth*/ 0, &addr, true/*change_port_if_bound*/);
|
||||
}
|
||||
else
|
||||
{
|
||||
addr.port = NetworkConfig::get()->getClientPort();
|
||||
// Client only has 1 peer
|
||||
m_network = new Network(/*peer_count*/1, /*channel_limit*/2,
|
||||
/*max_in_bandwidth*/0, /*max_out_bandwidth*/0, &addr,
|
||||
true/*change_port_if_bound*/);
|
||||
}
|
||||
|
||||
if (!m_network)
|
||||
{
|
||||
Log::fatal("STKHost", "An error occurred while trying to create an "
|
||||
"ENet server host.");
|
||||
}
|
||||
setPrivatePort();
|
||||
} // STKHost(server_name)
|
||||
if (server)
|
||||
Log::info("STKHost", "Server port is %d", m_private_port);
|
||||
} // STKHost
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialises the internal data structures and starts the protocol manager
|
||||
@ -941,9 +928,7 @@ void STKHost::handleDirectSocketRequest(Network* direct_socket,
|
||||
s.addUInt8((uint8_t)sl->getGameSetup()->getPlayerCount());
|
||||
s.addUInt16(m_private_port);
|
||||
s.addUInt8((uint8_t)race_manager->getDifficulty());
|
||||
s.addUInt8((uint8_t)
|
||||
NetworkConfig::get()->getServerGameMode(race_manager->getMinorMode(),
|
||||
race_manager->getMajorMode()));
|
||||
s.addUInt8((uint8_t)NetworkConfig::get()->getServerMode());
|
||||
s.addUInt8(!NetworkConfig::get()->getPassword().empty());
|
||||
direct_socket->sendRawPacket(s, sender);
|
||||
} // if message is server-requested
|
||||
@ -974,6 +959,12 @@ void STKHost::handleDirectSocketRequest(Network* direct_socket,
|
||||
Log::error("STKHost", "which is not localhost - rejected.");
|
||||
}
|
||||
}
|
||||
else if (command == "stk-server-port")
|
||||
{
|
||||
BareNetworkString s;
|
||||
s.addUInt16(m_private_port);
|
||||
direct_socket->sendRawPacket(s, sender);
|
||||
}
|
||||
else
|
||||
Log::info("STKHost", "Received unknown command '%s'",
|
||||
std::string(buffer, len).c_str());
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <tuple>
|
||||
|
||||
class GameSetup;
|
||||
class LobbyProtocol;
|
||||
class NetworkPlayerProfile;
|
||||
class Server;
|
||||
class ServerLobby;
|
||||
@ -132,9 +133,7 @@ private:
|
||||
uint16_t m_private_port;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
STKHost(std::shared_ptr<Server> server);
|
||||
// ------------------------------------------------------------------------
|
||||
STKHost(const irr::core::stringw &server_name);
|
||||
STKHost(bool server);
|
||||
// ------------------------------------------------------------------------
|
||||
~STKHost();
|
||||
// ------------------------------------------------------------------------
|
||||
@ -154,9 +153,7 @@ public:
|
||||
/** Creates the STKHost. It takes all confifguration parameters from
|
||||
* NetworkConfig. This STKHost can either be a client or a server.
|
||||
*/
|
||||
static void create(std::shared_ptr<Server> server = nullptr,
|
||||
SeparateProcess* p = NULL);
|
||||
|
||||
static std::shared_ptr<LobbyProtocol> create(SeparateProcess* p = NULL);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the instance of STKHost. */
|
||||
static STKHost *get()
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class NetworkPlayerProfile;
|
||||
@ -72,6 +73,9 @@ protected:
|
||||
|
||||
float m_connected_time;
|
||||
|
||||
/** Available karts and tracks from this peer */
|
||||
std::pair<std::set<std::string>, std::set<std::string> > m_available_kts;
|
||||
|
||||
public:
|
||||
STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id);
|
||||
~STKPeer() {}
|
||||
@ -126,6 +130,40 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
float getConnectedTime() const { return m_connected_time; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setAvailableKartsTracks(std::set<std::string>& k,
|
||||
std::set<std::string>& t)
|
||||
{ m_available_kts = std::make_pair(std::move(k), std::move(t)); }
|
||||
// ------------------------------------------------------------------------
|
||||
void eraseServerKarts(const std::set<std::string>& server_karts,
|
||||
std::set<std::string>& karts_erase)
|
||||
{
|
||||
if (m_available_kts.first.empty())
|
||||
return;
|
||||
for (const std::string& server_kart : server_karts)
|
||||
{
|
||||
if (m_available_kts.first.find(server_kart) ==
|
||||
m_available_kts.first.end())
|
||||
{
|
||||
karts_erase.insert(server_kart);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void eraseServerTracks(const std::set<std::string>& server_tracks,
|
||||
std::set<std::string>& tracks_erase)
|
||||
{
|
||||
if (m_available_kts.second.empty())
|
||||
return;
|
||||
for (const std::string& server_track : server_tracks)
|
||||
{
|
||||
if (m_available_kts.second.find(server_track) ==
|
||||
m_available_kts.second.end())
|
||||
{
|
||||
tracks_erase.insert(server_track);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
uint32_t getPing() const;
|
||||
|
||||
}; // STKPeer
|
||||
|
@ -250,8 +250,7 @@ void CreateServerScreen::createServer()
|
||||
auto server = std::make_shared<Server>(0/*server_id*/, name,
|
||||
max_players, /*current_player*/0, (RaceManager::Difficulty)
|
||||
difficulty_widget->getSelection(PLAYER_ID_GAME_MASTER),
|
||||
NetworkConfig::get()->getServerGameMode(race_manager->getMinorMode(),
|
||||
race_manager->getMajorMode()), server_address, !password.empty());
|
||||
0, server_address, !password.empty());
|
||||
|
||||
#undef USE_GRAPHICS_SERVER
|
||||
#ifdef USE_GRAPHICS_SERVER
|
||||
@ -276,7 +275,9 @@ void CreateServerScreen::createServer()
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_NORMAL_RACE);
|
||||
|
||||
race_manager->setReverseTrack(false);
|
||||
STKHost::create();
|
||||
auto sl = STKHost::create();
|
||||
assert(sl);
|
||||
sl->requestStart();
|
||||
#else
|
||||
|
||||
NetworkConfig::get()->setIsServer(false);
|
||||
@ -311,10 +312,26 @@ void CreateServerScreen::createServer()
|
||||
" --server-id-file=" << server_id_file <<
|
||||
" --log=1 --no-console-log";
|
||||
|
||||
if (m_more_options_spinner->isVisible())
|
||||
{
|
||||
int esi = m_more_options_spinner->getValue();
|
||||
if (gamemode_widget->getSelection(PLAYER_ID_GAME_MASTER)
|
||||
!= 3/*is soccer*/)
|
||||
{
|
||||
// Grand prix track count
|
||||
if (esi > 0)
|
||||
server_cfg << " --extra-server-info=" << esi;
|
||||
}
|
||||
else
|
||||
{
|
||||
server_cfg << " --extra-server-info=" << esi;
|
||||
}
|
||||
}
|
||||
|
||||
SeparateProcess* sp =
|
||||
new SeparateProcess(SeparateProcess::getCurrentExecutableLocation(),
|
||||
server_cfg.str() + password);
|
||||
STKHost::create(server, sp);
|
||||
STKHost::create(sp);
|
||||
NetworkingLobby::getInstance()->setJoinedServer(server);
|
||||
#endif
|
||||
} // createServer
|
||||
|
@ -71,6 +71,11 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
GUIEngine::EventPropagation processEvent(const std::string& eventSource)
|
||||
OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
GUIEngine::TextBoxWidget* getTextField() const { return m_text_field; }
|
||||
// ------------------------------------------------------------------------
|
||||
GUIEngine::LabelWidget* getTitle() const { return m_title; }
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "audio/music_manager.hpp"
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
#include "guiengine/widgets/icon_button_widget.hpp"
|
||||
@ -32,9 +34,9 @@
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/help_screen_1.hpp"
|
||||
#include "states_screens/main_menu_screen.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "states_screens/race_setup_screen.hpp"
|
||||
#include "states_screens/options_screen_video.hpp"
|
||||
#include "states_screens/online_screen.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
@ -57,16 +59,32 @@ RacePausedDialog::RacePausedDialog(const float percentWidth,
|
||||
loadFromFile("race_paused_dialog.stkgui");
|
||||
}
|
||||
|
||||
World::getWorld()->schedulePause(WorldStatus::IN_GAME_MENU_PHASE);
|
||||
|
||||
IconButtonWidget* back_btn = getWidget<IconButtonWidget>("backbtn");
|
||||
back_btn->setFocusForPlayer( PLAYER_ID_GAME_MASTER );
|
||||
|
||||
if (NetworkConfig::get()->isNetworking())
|
||||
{
|
||||
music_manager->pauseMusic();
|
||||
SFXManager::get()->pauseAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
World::getWorld()->schedulePause(WorldStatus::IN_GAME_MENU_PHASE);
|
||||
}
|
||||
} // RacePausedDialog
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
RacePausedDialog::~RacePausedDialog()
|
||||
{
|
||||
World::getWorld()->scheduleUnpause();
|
||||
if (NetworkConfig::get()->isNetworking())
|
||||
{
|
||||
music_manager->resumeMusic();
|
||||
SFXManager::get()->resumeAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
World::getWorld()->scheduleUnpause();
|
||||
}
|
||||
} // ~RacePausedDialog
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -172,18 +190,23 @@ GUIEngine::EventPropagation
|
||||
}
|
||||
World::getWorld()->scheduleUnpause();
|
||||
race_manager->exitRace();
|
||||
Screen* newStack[] = {MainMenuScreen::getInstance(),
|
||||
NetworkConfig::get()->isNetworking() ?
|
||||
static_cast<Screen*>(OnlineScreen::getInstance()) :
|
||||
static_cast<Screen*>(RaceSetupScreen::getInstance()),
|
||||
NULL};
|
||||
StateManager::get()->resetAndSetStack( newStack );
|
||||
Screen* new_stack[] =
|
||||
{
|
||||
MainMenuScreen::getInstance(),
|
||||
RaceSetupScreen::getInstance(),
|
||||
NULL
|
||||
};
|
||||
StateManager::get()->resetAndSetStack(
|
||||
NetworkConfig::get()->isNetworking() ?
|
||||
NetworkConfig::get()->getResetScreens().data() :
|
||||
new_stack);
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
return GUIEngine::EVENT_BLOCK;
|
||||
}
|
||||
else if (selection == "endrace")
|
||||
{
|
||||
ModalDialog::dismiss();
|
||||
World::getWorld()->getRaceGUI()->removeReferee();
|
||||
World::getWorld()->endRaceEarly();
|
||||
return GUIEngine::EVENT_BLOCK;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ ServerInfoDialog::ServerInfoDialog(std::shared_ptr<Server> server)
|
||||
GUIEngine::LabelWidget *lbldifficulty = getWidget<LabelWidget>("server_difficulty");
|
||||
lbldifficulty->setText(difficulty, false);
|
||||
|
||||
core::stringw mode = RaceManager::getNameOf(server->getRaceMinorMode());
|
||||
core::stringw mode = NetworkConfig::get()->getModeName(server->getServerMode());
|
||||
GUIEngine::LabelWidget *gamemode = getWidget<LabelWidget>("server_game_mode");
|
||||
gamemode->setText(mode, false);
|
||||
|
||||
@ -104,7 +104,7 @@ void ServerInfoDialog::requestJoin()
|
||||
{
|
||||
NetworkConfig::get()->setPassword("");
|
||||
}
|
||||
STKHost::create(m_server);
|
||||
STKHost::create();
|
||||
NetworkingLobby::getInstance()->setJoinedServer(m_server);
|
||||
ModalDialog::dismiss();
|
||||
NetworkingLobby::getInstance()->push();
|
||||
|
@ -425,7 +425,9 @@ void KartSelectionScreen::tearDown()
|
||||
Screen::tearDown();
|
||||
m_kart_widgets.clearAndDeleteAll();
|
||||
|
||||
GUIEngine::removeScreen(getName().c_str());
|
||||
if (m_must_delete_on_back)
|
||||
GUIEngine::removeScreen(this);
|
||||
|
||||
} // tearDown
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -54,13 +54,6 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool playerQuit(StateManager::ActivePlayer* player) OVERRIDE
|
||||
{ return true; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void tearDown() OVERRIDE
|
||||
{
|
||||
m_must_delete_on_back = true;
|
||||
KartSelectionScreen::tearDown();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -152,44 +152,6 @@ void NetworkingLobby::init()
|
||||
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkingLobby::setJoinedServer(std::shared_ptr<Server> server)
|
||||
{
|
||||
if (server == m_joined_server)
|
||||
return;
|
||||
|
||||
m_joined_server = server;
|
||||
m_server_info.clear();
|
||||
|
||||
if (!m_joined_server)
|
||||
return;
|
||||
core::stringw each_line;
|
||||
|
||||
//I18N: In the networking lobby
|
||||
each_line = _("Server name: %s", m_joined_server->getName());
|
||||
m_server_info.push_back(each_line);
|
||||
|
||||
const core::stringw& difficulty_name =
|
||||
race_manager->getDifficultyName(m_joined_server->getDifficulty());
|
||||
//I18N: In the networking lobby
|
||||
each_line = _("Difficulty: %s", difficulty_name);
|
||||
m_server_info.push_back(each_line);
|
||||
|
||||
//I18N: In the networking lobby
|
||||
each_line = _("Max players: %d", m_joined_server->getMaxPlayers());
|
||||
m_server_info.push_back(each_line);
|
||||
|
||||
//I18N: In the networking lobby
|
||||
core::stringw mode = RaceManager::getNameOf(m_joined_server->getRaceMinorMode());
|
||||
each_line = _("Game mode: %s", mode);
|
||||
|
||||
race_manager->setMinorMode(m_joined_server->getRaceMinorMode());
|
||||
race_manager->setMajorMode(m_joined_server->getRaceMajorMode());
|
||||
race_manager->setDifficulty(m_joined_server->getDifficulty());
|
||||
|
||||
m_server_info.push_back(each_line);
|
||||
} // setJoinedServer
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkingLobby::addMoreServerInfo(core::stringw info)
|
||||
{
|
||||
@ -253,7 +215,8 @@ void NetworkingLobby::onUpdate(float delta)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_server_peer.expired() && STKHost::existHost())
|
||||
if (m_server_peer.expired() && NetworkConfig::get()->isClient()
|
||||
&& STKHost::existHost())
|
||||
m_server_peer = STKHost::get()->getServerPeerForClient();
|
||||
core::stringw total_msg;
|
||||
for (auto& string : m_server_info)
|
||||
|
@ -115,7 +115,11 @@ public:
|
||||
|
||||
void finishAddingPlayers();
|
||||
void addMoreServerInfo(core::stringw info);
|
||||
void setJoinedServer(std::shared_ptr<Server> server);
|
||||
void setJoinedServer(std::shared_ptr<Server> server)
|
||||
{
|
||||
m_joined_server = server;
|
||||
m_server_info.clear();
|
||||
}
|
||||
void updatePlayers(const std::vector<std::tuple<uint32_t/*host id*/,
|
||||
uint32_t/*online id*/, core::stringw/*player name*/,
|
||||
int/*icon id*/> >& p);
|
||||
|
@ -50,14 +50,9 @@ OnlineProfileServers::OnlineProfileServers() : GUIEngine::Screen("online/profile
|
||||
// -----------------------------------------------------------------------------
|
||||
void OnlineProfileServers::beforeAddingWidget()
|
||||
{
|
||||
if (!PlayerManager::getCurrentOnlineId())
|
||||
{
|
||||
getWidget<IconButtonWidget>("find_wan_server")->setActive(false);
|
||||
getWidget<IconButtonWidget>("create_wan_server")->setActive(false);
|
||||
getWidget<IconButtonWidget>("quick_wan_play")->setActive(false);
|
||||
}
|
||||
#ifdef ANDROID
|
||||
getWidget("create_wan_server")->setVisible(false);
|
||||
if (getWidget("create_wan_server"))
|
||||
getWidget("create_wan_server")->setVisible(false);
|
||||
#endif
|
||||
} // beforeAddingWidget
|
||||
|
||||
@ -65,10 +60,28 @@ void OnlineProfileServers::beforeAddingWidget()
|
||||
|
||||
void OnlineProfileServers::init()
|
||||
{
|
||||
RibbonWidget* ribbon = getWidget<RibbonWidget>("wan");
|
||||
assert(ribbon != NULL);
|
||||
ribbon->select("find_wan_server", PLAYER_ID_GAME_MASTER);
|
||||
ribbon->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
if (!PlayerManager::getCurrentOnlineId())
|
||||
{
|
||||
getWidget("back")->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
getWidget<IconButtonWidget>("find_wan_server")->setActive(false);
|
||||
getWidget<IconButtonWidget>("create_wan_server")->setActive(false);
|
||||
getWidget<IconButtonWidget>("quick_wan_play")->setActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
getWidget<IconButtonWidget>("find_wan_server")->setActive(true);
|
||||
getWidget<IconButtonWidget>("create_wan_server")->setActive(true);
|
||||
getWidget<IconButtonWidget>("quick_wan_play")->setActive(true);
|
||||
RibbonWidget* ribbon = getWidget<RibbonWidget>("wan");
|
||||
assert(ribbon != NULL);
|
||||
ribbon->select("find_wan_server", PLAYER_ID_GAME_MASTER);
|
||||
ribbon->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
}
|
||||
#ifdef ANDROID
|
||||
if (getWidget("create_wan_server") &&
|
||||
getWidget("create_wan_server")->isVisible())
|
||||
getWidget("create_wan_server")->setVisible(false);
|
||||
#endif
|
||||
} // init
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -20,19 +20,28 @@
|
||||
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "guiengine/message_queue.hpp"
|
||||
#include "guiengine/widgets/check_box_widget.hpp"
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "guiengine/widgets/list_widget.hpp"
|
||||
#include "guiengine/widgets/ribbon_widget.hpp"
|
||||
#include "guiengine/widgets/text_box_widget.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "network/protocols/client_lobby.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/server.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
#include "online/request_manager.hpp"
|
||||
#include "states_screens/networking_lobby.hpp"
|
||||
#include "states_screens/online_lan.hpp"
|
||||
#include "states_screens/online_profile_achievements.hpp"
|
||||
#include "states_screens/online_profile_servers.hpp"
|
||||
#include "states_screens/online_screen.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/user_screen.hpp"
|
||||
#include "states_screens/dialogs/general_text_field_dialog.hpp"
|
||||
#include "states_screens/dialogs/message_dialog.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
@ -134,6 +143,13 @@ void OnlineScreen::onUpdate(float delta)
|
||||
|
||||
m_online->setLabel(PlayerManager::getCurrentOnlineId() ? m_online_string
|
||||
: m_login_string);
|
||||
// In case for entering server address finished
|
||||
if (auto lb = LobbyProtocol::get<LobbyProtocol>())
|
||||
{
|
||||
NetworkingLobby::getInstance()->setJoinedServer(nullptr);
|
||||
StateManager::get()->resetAndSetStack(
|
||||
NetworkConfig::get()->getResetScreens(true/*lobby*/).data());
|
||||
}
|
||||
} // onUpdate
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -143,6 +159,7 @@ void OnlineScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
{
|
||||
if (name == "user-id")
|
||||
{
|
||||
NetworkConfig::get()->cleanNetworkPlayers();
|
||||
UserScreen::getInstance()->push();
|
||||
return;
|
||||
}
|
||||
@ -197,7 +214,7 @@ void OnlineScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
"\"Connect to the Internet\"."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (PlayerManager::getCurrentOnlineId())
|
||||
{
|
||||
ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId());
|
||||
@ -208,6 +225,65 @@ void OnlineScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
UserScreen::getInstance()->push();
|
||||
}
|
||||
}
|
||||
else if (selection == "enter-address")
|
||||
{
|
||||
if (NetworkConfig::get()->isAddingNetworkPlayers())
|
||||
{
|
||||
core::stringw msg =
|
||||
_("No player available for connecting to server.");
|
||||
MessageQueue::add(MessageQueue::MT_ERROR, msg);
|
||||
return;
|
||||
}
|
||||
core::stringw instruction =
|
||||
_("Enter the server address with IP (optional) followed by : and"
|
||||
" then port.");
|
||||
auto gtfd = new GeneralTextFieldDialog(instruction.c_str(),
|
||||
[] (const irr::core::stringw& text) {},
|
||||
[this] (GUIEngine::LabelWidget* lw,
|
||||
GUIEngine::TextBoxWidget* tb)->bool
|
||||
{
|
||||
TransportAddress server_addr(
|
||||
StringUtils::wideToUtf8(tb->getText()));
|
||||
if (server_addr.getIP() == 0)
|
||||
{
|
||||
core::stringw err = _("Invalid server address: %s.",
|
||||
tb->getText());
|
||||
lw->setText(err, true);
|
||||
return false;
|
||||
}
|
||||
NetworkConfig::get()->setIsWAN();
|
||||
NetworkConfig::get()->setIsServer(false);
|
||||
NetworkConfig::get()->setPassword("");
|
||||
auto server = std::make_shared<Server>(0, L"", 0, 0, 0, 0,
|
||||
server_addr, false);
|
||||
STKHost::create();
|
||||
auto cts = std::make_shared<ConnectToServer>(server);
|
||||
cts->setup();
|
||||
Log::info("OnlineScreen", "Trying to connect to server '%s'.",
|
||||
server_addr.toString().c_str());
|
||||
if (!cts->handleDirectConnect(10000))
|
||||
{
|
||||
core::stringw err = _("Cannot connect to server %s.",
|
||||
server_addr.toString().c_str());
|
||||
STKHost::get()->shutdown();
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
lw->setText(err, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_entered_server_address.copy(
|
||||
STKHost::get()->getServerPeerForClient()->getAddress());
|
||||
auto cl = LobbyProtocol::create<ClientLobby>();
|
||||
cl->setAddress(m_entered_server_address);
|
||||
cl->requestStart();
|
||||
return true;
|
||||
});
|
||||
if (!m_entered_server_address.isUnset())
|
||||
{
|
||||
gtfd->getTextField()->setText(StringUtils::utf8ToWide(
|
||||
m_entered_server_address.toString()));
|
||||
}
|
||||
}
|
||||
} // eventCallback
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -220,5 +296,3 @@ bool OnlineScreen::onEscapePressed()
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
return true;
|
||||
} // onEscapePressed
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#define HEADER_ONLINE_SCREEN_HPP
|
||||
|
||||
#include "guiengine/screen.hpp"
|
||||
#include "network/transport_address.hpp"
|
||||
|
||||
|
||||
namespace GUIEngine { class CheckBoxWidget; class ListWidget;
|
||||
class ButtonWidget; class IconButtonWidget; }
|
||||
@ -44,6 +46,8 @@ private:
|
||||
|
||||
GUIEngine::CheckBoxWidget* m_enable_splitscreen;
|
||||
|
||||
TransportAddress m_entered_server_address;
|
||||
|
||||
OnlineScreen();
|
||||
|
||||
public:
|
||||
|
@ -1067,3 +1067,12 @@ void RaceGUIBase::drawPlungerInFace(const Camera *camera, float dt)
|
||||
true /* alpha */ );
|
||||
#endif // !SERVER_ONLY
|
||||
} // drawPlungerInFace
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void RaceGUIBase::removeReferee()
|
||||
{
|
||||
if (m_referee->isAttached()) // race phase:
|
||||
{
|
||||
m_referee->removeFromSceneGraph();
|
||||
}
|
||||
} // removeReferee
|
||||
|
@ -248,6 +248,7 @@ public:
|
||||
const core::vector2df &scaling) {};
|
||||
|
||||
void cleanupMessages(const float dt);
|
||||
void removeReferee();
|
||||
|
||||
}; // RaceGUIBase
|
||||
|
||||
|
@ -51,9 +51,7 @@
|
||||
#include "scriptengine/property_animator.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 "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
@ -168,21 +166,14 @@ void RaceResultGUI::enableAllButtons()
|
||||
// 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
|
||||
// -------------------------
|
||||
@ -342,16 +333,15 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
// If we're playing online :
|
||||
if (World::getWorld()->isNetworkWorld())
|
||||
{
|
||||
StateManager::get()->popMenu();
|
||||
if (name == "middle") // Continue button (return to server lobby)
|
||||
{
|
||||
// Signal to the server that this client is back in the lobby now.
|
||||
auto clrp = LobbyProtocol::get<ClientLobby>();
|
||||
if(clrp)
|
||||
clrp->doneWithResults();
|
||||
backToLobby();
|
||||
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||
if (cl)
|
||||
cl->doneWithResults();
|
||||
getWidget("middle")->setText(_("Waiting for others"));
|
||||
}
|
||||
if (name == "bottom") // Quit server (return to main menu)
|
||||
if (name == "bottom") // Quit server (return to online lan / wan menu)
|
||||
{
|
||||
if (STKHost::existHost())
|
||||
{
|
||||
@ -359,7 +349,8 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
}
|
||||
race_manager->exitRace();
|
||||
race_manager->setAIKartOverride("");
|
||||
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
|
||||
StateManager::get()->resetAndSetStack(
|
||||
NetworkConfig::get()->getResetScreens().data());
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
}
|
||||
return;
|
||||
@ -430,18 +421,16 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
|
||||
} // eventCallback
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets up the giu to go back to the lobby. Can only be called in case of a
|
||||
/** Sets up the gui to go back to the lobby. Can only be called in case of a
|
||||
* networked game.
|
||||
*/
|
||||
void RaceResultGUI::backToLobby()
|
||||
{
|
||||
race_manager->exitRace();
|
||||
race_manager->setAIKartOverride("");
|
||||
Screen* newStack[] = { MainMenuScreen::getInstance(),
|
||||
OnlineScreen::getInstance(),
|
||||
NetworkingLobby::getInstance(),
|
||||
NULL };
|
||||
StateManager::get()->resetAndSetStack(newStack);
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
StateManager::get()->resetAndSetStack(
|
||||
NetworkConfig::get()->getResetScreens(true/*lobby*/).data());
|
||||
} // backToLobby
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -149,7 +149,7 @@ void ServerSelection::loadList(unsigned sort_case)
|
||||
return c->getDifficulty() > d->getDifficulty();
|
||||
break;
|
||||
case 3:
|
||||
return c->getRaceMinorMode() > d->getRaceMinorMode();
|
||||
return c->getServerMode() > d->getServerMode();
|
||||
break;
|
||||
case 4:
|
||||
return c->getServerOwnerName() > d->getServerOwnerName();
|
||||
@ -175,7 +175,8 @@ void ServerSelection::loadList(unsigned sort_case)
|
||||
race_manager->getDifficultyName(server->getDifficulty());
|
||||
row.push_back(GUIEngine::ListWidget::ListCell(difficulty, -1, 1, true));
|
||||
|
||||
core::stringw mode = RaceManager::getNameOf(server->getRaceMinorMode());
|
||||
core::stringw mode =
|
||||
NetworkConfig::get()->getModeName(server->getServerMode());
|
||||
row.push_back(GUIEngine::ListWidget::ListCell(mode, -1, 2, true));
|
||||
|
||||
if (NetworkConfig::get()->isWAN())
|
||||
|
@ -52,7 +52,12 @@ void TracksScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
const int playerID)
|
||||
{
|
||||
// -- track selection screen
|
||||
if (name == "tracks")
|
||||
if ((name == "lap-spinner" || name == "reverse") &&
|
||||
STKHost::existHost() && m_selected_track != NULL)
|
||||
{
|
||||
voteForPlayer();
|
||||
}
|
||||
else if (name == "tracks")
|
||||
{
|
||||
DynamicRibbonWidget* w2 = dynamic_cast<DynamicRibbonWidget*>(widget);
|
||||
if(!w2) return;
|
||||
@ -84,27 +89,17 @@ void TracksScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
m_random_track_list.push_back(selection);
|
||||
|
||||
} // selection=="random_track"
|
||||
Track *track = track_manager->getTrack(selection);
|
||||
m_selected_track = track_manager->getTrack(selection);
|
||||
|
||||
if (track)
|
||||
if (m_selected_track)
|
||||
{
|
||||
if (STKHost::existHost())
|
||||
{
|
||||
assert(m_laps);
|
||||
assert(m_reversed);
|
||||
// Remember reverse globally for each stk instance
|
||||
m_reverse_checked = m_reversed->getState();
|
||||
UserConfigParams::m_num_laps = m_laps->getValue();
|
||||
NetworkString vote(PROTOCOL_LOBBY_ROOM);
|
||||
vote.addUInt8(LobbyProtocol::LE_VOTE);
|
||||
vote.encodeString(track->getIdent())
|
||||
.addUInt8(m_laps->getValue())
|
||||
.addUInt8(m_reversed->getState());
|
||||
STKHost::get()->sendToServer(&vote, true);
|
||||
voteForPlayer();
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackInfoScreen::getInstance()->setTrack(track);
|
||||
TrackInfoScreen::getInstance()->setTrack(m_selected_track);
|
||||
TrackInfoScreen::getInstance()->push();
|
||||
}
|
||||
} // if clicked_track
|
||||
@ -139,6 +134,7 @@ void TracksScreen::tearDown()
|
||||
{
|
||||
m_network_tracks = false;
|
||||
m_vote_timeout = -1.0f;
|
||||
m_selected_track = NULL;
|
||||
} // tearDown
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -354,6 +350,31 @@ void TracksScreen::setFocusOnTrack(const std::string& trackName)
|
||||
tracks_widget->setSelection(trackName, PLAYER_ID_GAME_MASTER, true);
|
||||
} // setFocusOnTrack
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void TracksScreen::setVoteTimeout(float timeout)
|
||||
{
|
||||
if (m_vote_timeout != -1.0f)
|
||||
return;
|
||||
m_vote_timeout = (float)StkTime::getRealTime() + timeout;
|
||||
} // setVoteTimeout
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void TracksScreen::voteForPlayer()
|
||||
{
|
||||
assert(STKHost::existHost());
|
||||
assert(m_selected_track);
|
||||
assert(m_laps);
|
||||
assert(m_reversed);
|
||||
// Remember reverse globally for each stk instance
|
||||
m_reverse_checked = m_reversed->getState();
|
||||
UserConfigParams::m_num_laps = m_laps->getValue();
|
||||
NetworkString vote(PROTOCOL_LOBBY_ROOM);
|
||||
vote.addUInt8(LobbyProtocol::LE_VOTE);
|
||||
vote.encodeString(m_selected_track->getIdent())
|
||||
.addUInt8(m_laps->getValue()).addUInt8(m_reversed->getState());
|
||||
STKHost::get()->sendToServer(&vote, true);
|
||||
} // voteForPlayer
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void TracksScreen::onUpdate(float dt)
|
||||
{
|
||||
@ -365,7 +386,7 @@ void TracksScreen::onUpdate(float dt)
|
||||
}
|
||||
|
||||
m_votes->setVisible(true);
|
||||
int remaining_time = int(m_vote_timeout - float(StkTime::getRealTime()));
|
||||
int remaining_time = (int)(m_vote_timeout - StkTime::getRealTime());
|
||||
if (remaining_time < 0)
|
||||
remaining_time = 0;
|
||||
//I18N: In tracks screen, about voting of tracks in network
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class Track;
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
class CheckBoxWidget;
|
||||
@ -47,6 +49,7 @@ private:
|
||||
m_reverse_checked = false;
|
||||
}
|
||||
|
||||
Track* m_selected_track = NULL;
|
||||
GUIEngine::CheckBoxWidget* m_reversed;
|
||||
GUIEngine::SpinnerWidget* m_laps;
|
||||
GUIEngine::LabelWidget* m_votes;
|
||||
@ -59,10 +62,12 @@ private:
|
||||
|
||||
Synchronised<std::map<std::string, core::stringw> > m_vote_messages;
|
||||
|
||||
std::deque<std::string> m_random_track_list;
|
||||
|
||||
/** adds the tracks from the current track group into the tracks ribbon */
|
||||
void buildTrackList();
|
||||
|
||||
std::deque<std::string> m_random_track_list;
|
||||
void voteForPlayer();
|
||||
|
||||
public:
|
||||
|
||||
@ -101,12 +106,7 @@ public:
|
||||
m_vote_timeout = -1.0f;
|
||||
}
|
||||
|
||||
void setVoteTimeout(float timeout)
|
||||
{
|
||||
if (m_vote_timeout != -1.0f)
|
||||
return;
|
||||
m_vote_timeout = timeout;
|
||||
}
|
||||
void setVoteTimeout(float timeout);
|
||||
|
||||
void addVoteMessage(const std::string& user,
|
||||
const irr::core::stringw& message)
|
||||
|
@ -82,35 +82,53 @@ public:
|
||||
static void reportInvalidParameters();
|
||||
static bool has(const std::string &option);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Searches for an option 'option=XX'. If found, *t will contain 'XX'.
|
||||
* If the value was found, the entry is removed from the list of all
|
||||
* command line arguments. This is the interface for any integer
|
||||
* values (i.e. using %d as format while scanning).
|
||||
/** Searches for an option 'option=XX'. If found, *value will contain 'XX'.
|
||||
* If the value was found and the type of XX and value matches each other,
|
||||
* the entry is removed from the list of all command line arguments.
|
||||
* \param option The option (must include '-' or '--' as required).
|
||||
* \param t Address of a variable to store the value.
|
||||
* \param format The '%' format to sscanf the value in t with.
|
||||
* \param value Pointer to store the value.
|
||||
* \return true if the value was found, false otherwise.
|
||||
*/
|
||||
static bool has(const std::string &option, int *t)
|
||||
template<typename T> static bool has(const std::string& option, T* value)
|
||||
{
|
||||
return has(option, t, "%d");
|
||||
std::string equal = option + "=";
|
||||
std::vector<std::string>::iterator i;
|
||||
for (i = m_argv.begin(); i < m_argv.end(); i++)
|
||||
{
|
||||
if (i->compare(0, equal.size(), equal) == 0)
|
||||
{
|
||||
std::string result =
|
||||
i->substr(equal.size(), std::string::npos);
|
||||
if (StringUtils::fromString(result, *value))
|
||||
{
|
||||
m_argv.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Searches for an option 'option=XX'. If found, *t will contain 'XX'.
|
||||
* If the value was found, the entry is removed from the list of all
|
||||
* command line arguments. This is the interface for a std::string
|
||||
/** Searches for an option 'option=XX'. If found, *value will contain 'XX'.
|
||||
* If the value was found and the type of XX and value matches each other,
|
||||
* the entry is removed from the list of all command line arguments.
|
||||
* It copies the result directly to value to include space.
|
||||
* \param option The option (must include '-' or '--' as required).
|
||||
* \param t Address of a variable to store the value.
|
||||
* \param format The '%' format to sscanf the value in t with.
|
||||
* \param value String pointer to store the value.
|
||||
* \return true if the value was found, false otherwise.
|
||||
*/
|
||||
static bool has(const std::string &option, std::string *t)
|
||||
static bool has(const std::string& option, std::string* value)
|
||||
{
|
||||
char s[1024];
|
||||
if(has(option, s, "%1023s"))
|
||||
std::string equal = option + "=";
|
||||
std::vector<std::string>::iterator i;
|
||||
for (i = m_argv.begin(); i < m_argv.end(); i++)
|
||||
{
|
||||
*t = s;
|
||||
return true;
|
||||
if (i->compare(0, equal.size(), equal) == 0)
|
||||
{
|
||||
*value = i->substr(equal.size(), std::string::npos);
|
||||
m_argv.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} // has<std::string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user