Add the framework in server lobby for live update config

This commit is contained in:
Benau 2018-12-05 14:19:01 +08:00
parent b341ec8e8c
commit 3d64340137
13 changed files with 193 additions and 45 deletions

View File

@ -1954,6 +1954,7 @@ int main(int argc, char *argv[] )
{
main_loop = new MainLoop(parent_pid);
has_parent_process = true;
ServerConfig::m_server_configurable = true;
}
else
main_loop = new MainLoop(0/*parent_pid*/);

View File

@ -25,6 +25,7 @@
#include "network/network_config.hpp"
#include "network/network_player_profile.hpp"
#include "network/protocols/game_events_protocol.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/server_config.hpp"
#include "network/stk_host.hpp"
#include "race/race_manager.hpp"
@ -186,7 +187,7 @@ void GameSetup::loadWorld()
bool GameSetup::isGrandPrix() const
{
return m_extra_server_info != -1 &&
ServerConfig::getLocalGameMode().second ==
ServerConfig::getLocalGameModeFromConfig().second ==
RaceManager::MAJOR_MODE_GRAND_PRIX;
} // isGrandPrix
@ -195,9 +196,11 @@ void GameSetup::addServerInfo(NetworkString* ns)
{
assert(NetworkConfig::get()->isServer());
ns->encodeString(m_server_name_utf8);
ns->addUInt8((uint8_t)ServerConfig::m_server_difficulty)
auto sl = LobbyProtocol::get<ServerLobby>();
assert(sl);
ns->addUInt8((uint8_t)sl->getDifficulty())
.addUInt8((uint8_t)ServerConfig::m_server_max_players)
.addUInt8((uint8_t)ServerConfig::m_server_mode);
.addUInt8((uint8_t)sl->getGameMode());
if (hasExtraSeverInfo())
{
if (isGrandPrix())
@ -228,6 +231,7 @@ void GameSetup::addServerInfo(NetworkString* ns)
ns->addUInt8(0).addFloat(0.0f);
ns->encodeString16(m_message_of_today);
ns->addUInt8((uint8_t)ServerConfig::m_server_configurable);
} // addServerInfo
//-----------------------------------------------------------------------------

View File

@ -340,13 +340,13 @@ public:
/** Returns an unsigned 8-bit integer. */
inline uint8_t getUInt8() const
{
return m_buffer[m_current_offset++];
return m_buffer.at(m_current_offset++);
} // getUInt8
// ------------------------------------------------------------------------
/** Returns an unsigned 8-bit integer. */
inline int8_t getInt8() const
{
return m_buffer[m_current_offset++];
return m_buffer.at(m_current_offset++);
} // getInt8
// ------------------------------------------------------------------------
/** Gets a 4 byte floating point value. */

View File

@ -603,8 +603,7 @@ void ClientLobby::handleServerInfo(Event* event)
NetworkingLobby::getInstance()->addMoreServerInfo(each_line);
u_data = data.getUInt8();
ServerConfig::m_server_mode = u_data;
auto game_mode = ServerConfig::getLocalGameMode();
auto game_mode = ServerConfig::getLocalGameMode(u_data);
race_manager->setMinorMode(game_mode.first);
// We use single mode in network even it's grand prix
race_manager->setMajorMode(RaceManager::MAJOR_MODE_SINGLE);
@ -660,6 +659,8 @@ void ClientLobby::handleServerInfo(Event* event)
for (const core::stringw& motd : motd_line)
NetworkingLobby::getInstance()->addMoreServerInfo(motd);
}
bool server_config = data.getUInt8() == 1;
NetworkingLobby::getInstance()->toggleServerConfigButton(server_config);
} // handleServerInfo
//-----------------------------------------------------------------------------

View File

@ -62,7 +62,8 @@ public:
LE_KICK_HOST,
LE_CHANGE_TEAM,
LE_BAD_TEAM,
LE_BAD_CONNECTION
LE_BAD_CONNECTION,
LE_CONFIG_SERVER
};
enum RejectReason : uint8_t

View File

@ -138,6 +138,8 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL)
m_result_ns->setSynchronous(true);
m_waiting_for_reset = false;
m_server_id_online.store(0);
m_difficulty.store(ServerConfig::m_server_difficulty);
m_game_mode.store(ServerConfig::m_server_mode);
} // ServerLobby
//-----------------------------------------------------------------------------
@ -156,32 +158,14 @@ ServerLobby::~ServerLobby()
} // ~ServerLobby
//-----------------------------------------------------------------------------
void ServerLobby::setup()
void ServerLobby::updateTracksForMode()
{
LobbyProtocol::setup();
auto players = m_game_setup->getConnectedPlayers();
if (m_game_setup->isGrandPrix() && !m_game_setup->isGrandPrixStarted())
{
for (auto player : players)
player->resetGrandPrixData();
}
if (!m_game_setup->isGrandPrix() || !m_game_setup->isGrandPrixStarted())
{
for (auto player : players)
player->setKartName("");
}
StateManager::get()->resetActivePlayers();
// We use maximum 16bit unsigned limit
auto all_k = kart_properties_manager->getAllAvailableKarts();
auto all_t = track_manager->getAllTrackIdentifiers();
if (all_k.size() >= 65536)
all_k.resize(65535);
if (all_t.size() >= 65536)
all_t.resize(65535);
m_available_kts.first = { all_k.begin(), all_k.end() };
m_available_kts.second = { all_t.begin(), all_t.end() };
RaceManager::MinorRaceModeType m = ServerConfig::getLocalGameMode().first;
RaceManager::MinorRaceModeType m =
ServerConfig::getLocalGameMode(m_game_mode.load()).first;
switch (m)
{
case RaceManager::MINOR_MODE_NORMAL_RACE:
@ -250,6 +234,32 @@ void ServerLobby::setup()
break;
}
} // updateTracksForMode
//-----------------------------------------------------------------------------
void ServerLobby::setup()
{
LobbyProtocol::setup();
auto players = m_game_setup->getConnectedPlayers();
if (m_game_setup->isGrandPrix() && !m_game_setup->isGrandPrixStarted())
{
for (auto player : players)
player->resetGrandPrixData();
}
if (!m_game_setup->isGrandPrix() || !m_game_setup->isGrandPrixStarted())
{
for (auto player : players)
player->setKartName("");
}
StateManager::get()->resetActivePlayers();
// We use maximum 16bit unsigned limit
auto all_k = kart_properties_manager->getAllAvailableKarts();
if (all_k.size() >= 65536)
all_k.resize(65535);
m_available_kts.first = { all_k.begin(), all_k.end() };
updateTracksForMode();
m_server_has_loaded_world.store(false);
// Initialise the data structures to detect if all clients and
@ -366,6 +376,7 @@ bool ServerLobby::notifyEventAsynchronous(Event* event)
case LE_CHANGE_TEAM: changeTeam(event); break;
case LE_REQUEST_BEGIN: startSelection(event); break;
case LE_CHAT: handleChat(event); break;
case LE_CONFIG_SERVER: handleServerConfiguration(event); break;
default: break;
} // switch
} // if (event->getType() == EVENT_TYPE_MESSAGE)
@ -554,7 +565,8 @@ void ServerLobby::asynchronousUpdate()
.addUInt32(player->getOnlineId())
.addUInt8(player->getPerPlayerDifficulty())
.addUInt8(player->getLocalPlayerId())
.addUInt8(player->getTeam());
.addUInt8(race_manager->teamEnabled() ?
player->getTeam() : KART_TEAM_NONE);
if (player->getKartName().empty())
{
RandomGenerator rg;
@ -866,7 +878,7 @@ void ServerLobby::startSelection(const Event *event)
if (m_state != WAITING_FOR_START_GAME)
{
Log::warn("ServerLobby",
"Received startSelection while being in state %d",
"Received startSelection while being in state %d.",
m_state.load());
return;
}
@ -1540,7 +1552,7 @@ void ServerLobby::connectionRequested(Event* event)
peer->sendPacket(message, true/*reliable*/, false/*encrypted*/);
peer->reset();
delete message;
Log::verbose("ServerLobby", "Player has incompatible karts / tracks");
Log::verbose("ServerLobby", "Player has incompatible karts / tracks.");
return;
}
@ -1685,8 +1697,7 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
(peer, i == 0 && !online_name.empty() ? online_name : name,
peer->getHostId(), default_kart_color, i == 0 ? online_id : 0,
per_player_difficulty, (uint8_t)i, KART_TEAM_NONE);
if (ServerConfig::m_team_choosing &&
race_manager->teamEnabled())
if (ServerConfig::m_team_choosing)
{
KartTeam cur_team = KART_TEAM_NONE;
if (red_blue.first > red_blue.second)
@ -2600,3 +2611,93 @@ float ServerLobby::getStartupBoostOrPenaltyForKart(uint32_t ping,
k->setStartupBoost(f);
return f;
} // getStartupBoostOrPenaltyForKart
//-----------------------------------------------------------------------------
/*! \brief Called when the server owner request to change game mode or
* difficulty.
* \param event : Event providing the information.
*
* Format of the data :
* Byte 0 1 2
* -----------------------------------------------
* Size | 1 | 1 | 1 |
* Data | difficulty | game mode | soccer goal target |
* -----------------------------------------------
*/
void ServerLobby::handleServerConfiguration(Event* event)
{
if (m_state != WAITING_FOR_START_GAME)
{
Log::warn("ServerLobby",
"Received handleServerConfiguration while being in state %d.",
m_state.load());
return;
}
if (!ServerConfig::m_server_configurable)
{
Log::warn("ServerLobby", "server-configurable is not enabled.");
return;
}
if (event->getPeerSP() != m_server_owner.lock())
{
Log::warn("ServerLobby",
"Client %d is not authorised to config server.",
event->getPeer()->getHostId());
return;
}
NetworkString& data = event->data();
uint8_t new_difficulty = data.getUInt8();
uint8_t new_game_mode = data.getUInt8();
bool new_soccer_goal_target = data.getUInt8() == 1;
auto modes = ServerConfig::getLocalGameMode(new_game_mode);
if (modes.second == RaceManager::MAJOR_MODE_GRAND_PRIX)
{
Log::warn("ServerLobby", "Grand prix is used for new mode.");
return;
}
race_manager->setMinorMode(modes.first);
race_manager->setMajorMode(modes.second);
race_manager->setDifficulty(RaceManager::Difficulty(new_difficulty));
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
m_game_setup->setSoccerGoalTarget(new_soccer_goal_target);
m_difficulty.store(new_difficulty);
m_game_mode.store(new_game_mode);
updateTracksForMode();
auto peers = STKHost::get()->getPeers();
for (auto& peer : peers)
{
auto assets = peer->getClientAssets();
if (!peer->isValidated() || assets.second.empty())
continue;
std::set<std::string> tracks_erase;
for (const std::string& server_track : m_available_kts.second)
{
if (assets.second.find(server_track) == assets.second.end())
{
tracks_erase.insert(server_track);
}
}
if (tracks_erase.size() == m_available_kts.second.size())
{
NetworkString *message = getNetworkString(2);
message->setSynchronous(true);
message->addUInt8(LE_CONNECTION_REFUSED)
.addUInt8(RR_INCOMPATIBLE_DATA);
peer->cleanPlayerProfiles();
peer->sendPacket(message, true/*reliable*/);
peer->reset();
delete message;
Log::verbose("ServerLobby",
"Player has incompatible tracks for new game mode.");
}
}
NetworkString* server_info = getNetworkString();
server_info->setSynchronous(true);
server_info->addUInt8(LE_SERVER_INFO);
m_game_setup->addServerInfo(server_info);
sendMessageToPeers(server_info);
delete server_info;
updatePlayerList();
} // handleServerConfiguration

View File

@ -153,12 +153,16 @@ private:
std::atomic<uint32_t> m_waiting_players_counts;
std::atomic<uint32_t> m_server_id_online;
std::atomic<int> m_difficulty;
std::atomic<int> m_game_mode;
std::atomic<uint64_t> m_last_success_poll_time;
uint64_t m_server_started_at, m_server_delay;
std::atomic<uint32_t> m_server_id_online;
bool m_registered_for_once_only;
bool m_save_server_config;
@ -180,6 +184,8 @@ private:
void createServerIdFile();
void updatePlayerList(bool update_when_reset_server = false);
void updateServerOwner();
void handleServerConfiguration(Event* event);
void updateTracksForMode();
bool checkPeersReady() const
{
bool all_ready = true;
@ -284,6 +290,8 @@ public:
bool allowJoinedPlayersWaiting() const;
void setSaveServerConfig(bool val) { m_save_server_config = val; }
float getStartupBoostOrPenaltyForKart(uint32_t ping, unsigned kart_id);
int getDifficulty() const { return m_difficulty.load(); }
int getGameMode() const { return m_game_mode.load(); }
}; // class ServerLobby
#endif // SERVER_LOBBY_HPP

View File

@ -178,9 +178,9 @@ void writeServerConfigToDisk()
// ----------------------------------------------------------------------------
/** Returns the minor and majar game mode from server database id. */
std::pair<RaceManager::MinorRaceModeType, RaceManager::MajorRaceModeType>
getLocalGameMode()
getLocalGameMode(int mode)
{
switch (m_server_mode)
switch (mode)
{
case 0:
return { RaceManager::MINOR_MODE_NORMAL_RACE,
@ -217,6 +217,13 @@ std::pair<RaceManager::MinorRaceModeType, RaceManager::MajorRaceModeType>
} // getLocalGameMode
// ----------------------------------------------------------------------------
std::pair<RaceManager::MinorRaceModeType, RaceManager::MajorRaceModeType>
getLocalGameModeFromConfig()
{
return getLocalGameMode(m_server_mode);
} // getLocalGameModeFromConfig
// ----------------------------------------------------------------------------
core::stringw getModeName(unsigned id)
{
@ -259,7 +266,7 @@ void loadServerLobbyFromConfig()
if (m_official_tracks_threshold > 1.0f)
m_official_tracks_threshold = 1.0f;
auto modes = getLocalGameMode();
auto modes = getLocalGameModeFromConfig();
race_manager->setMinorMode(modes.first);
race_manager->setMajorMode(modes.second);
unsigned difficulty = m_server_difficulty;
@ -277,7 +284,10 @@ void loadServerLobbyFromConfig()
if (m_min_start_game_players > m_server_max_players)
m_min_start_game_players = 1;
m_team_choosing = false;
m_server_configurable = false;
}
if (modes.second == RaceManager::MAJOR_MODE_GRAND_PRIX)
m_server_configurable = false;
const bool is_soccer =
race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER;

View File

@ -221,6 +221,13 @@ namespace ServerConfig
"validating-player, auto-end, strict-player and owner-less will be "
"turned on."));
SERVER_CFG_PREFIX BoolServerConfigParam m_server_configurable
SERVER_CFG_DEFAULT(BoolServerConfigParam(false, "server-configurable",
"If true, the server owner can config the game mode and difficulty in "
"the GUI of lobby. This option cannot be used with owner-less or "
"grand prix server, and will be automatically turned on if the server "
"was created using the in-game GUI."));
SERVER_CFG_PREFIX FloatServerConfigParam m_flag_return_timemout
SERVER_CFG_DEFAULT(FloatServerConfigParam(20.0f, "flag-return-timemout",
"Time in seconds when a flag is dropped a by player in CTF "
@ -315,7 +322,10 @@ namespace ServerConfig
void writeServerConfigToDisk();
// ------------------------------------------------------------------------
std::pair<RaceManager::MinorRaceModeType, RaceManager::MajorRaceModeType>
getLocalGameMode();
getLocalGameModeFromConfig();
// ------------------------------------------------------------------------
std::pair<RaceManager::MinorRaceModeType, RaceManager::MajorRaceModeType>
getLocalGameMode(int mode);
// ------------------------------------------------------------------------
core::stringw getModeName(unsigned id);
// ------------------------------------------------------------------------

View File

@ -1047,8 +1047,8 @@ void STKHost::handleDirectSocketRequest(Network* direct_socket,
s.addUInt8((uint8_t)(sl->getGameSetup()->getPlayerCount() +
sl->getWaitingPlayersCount()));
s.addUInt16(m_private_port);
s.addUInt8((uint8_t)ServerConfig::m_server_difficulty);
s.addUInt8((uint8_t)ServerConfig::m_server_mode);
s.addUInt8((uint8_t)sl->getDifficulty());
s.addUInt8((uint8_t)sl->getGameMode());
s.addUInt8(!pw.empty());
s.addUInt8((uint8_t)
(sl->getCurrentState() == ServerLobby::WAITING_FOR_START_GAME ?

View File

@ -172,6 +172,9 @@ public:
}
}
// ------------------------------------------------------------------------
std::pair<std::set<std::string>, std::set<std::string> >
getClientAssets() const { return m_available_kts; }
// ------------------------------------------------------------------------
void setPingInterval(uint32_t interval)
{ enet_peer_ping_interval(m_enet_peer, interval); }
// ------------------------------------------------------------------------

View File

@ -93,6 +93,9 @@ void NetworkingLobby::loadedFromFile()
m_start_button = getWidget<IconButtonWidget>("start");
assert(m_start_button!= NULL);
m_config_button = getWidget<IconButtonWidget>("config");
assert(m_config_button!= NULL);
m_text_bubble = getWidget<LabelWidget>("text");
assert(m_text_bubble != NULL);
@ -142,7 +145,7 @@ void NetworkingLobby::init()
{
Screen::init();
getWidget("config")->setVisible(false);
m_server_configurable = false;
m_player_names.clear();
m_allow_change_team = false;
m_has_auto_start_in_server = false;
@ -157,6 +160,7 @@ void NetworkingLobby::init()
m_server_info_height = GUIEngine::getFont()->getDimension(L"X").Height;
m_start_button->setLabel(_("Start race"));
m_start_button->setVisible(false);
m_config_button->setVisible(false);
m_state = LS_CONNECTING;
getWidget("chat")->setVisible(false);
getWidget("chat")->setActive(false);
@ -348,6 +352,9 @@ void NetworkingLobby::onUpdate(float delta)
m_text_bubble->setText(total_msg, true);
}
m_config_button->setVisible(STKHost::get()->isAuthorisedToControl() &&
m_server_configurable);
if (STKHost::get()->isAuthorisedToControl() ||
(m_has_auto_start_in_server &&
m_cur_starting_timer != std::numeric_limits<int64_t>::max()))

View File

@ -76,13 +76,15 @@ private:
int64_t m_cur_starting_timer;
unsigned m_min_start_game_players;
bool m_allow_change_team, m_has_auto_start_in_server;
bool m_allow_change_team, m_has_auto_start_in_server,
m_server_configurable;
GUIEngine::IconButtonWidget* m_back_widget;
GUIEngine::LabelWidget* m_header;
GUIEngine::LabelWidget* m_text_bubble;
GUIEngine::LabelWidget* m_timeout_message;
GUIEngine::IconButtonWidget* m_start_button;
GUIEngine::IconButtonWidget* m_config_button;
GUIEngine::ListWidget* m_player_list;
GUIEngine::TextBoxWidget* m_chat_box;
GUIEngine::ButtonWidget* m_send_button;
@ -142,7 +144,7 @@ public:
void initAutoStartTimer(bool grand_prix_started, unsigned min_players,
float start_timeout, unsigned server_max_player);
void setStartingTimerTo(float t);
void toggleServerConfigButton(bool val) { m_server_configurable = val; }
}; // class NetworkingLobby
#endif