Add ranked server for validated player
This commit is contained in:
parent
a9696792c2
commit
4653089d95
21
src/main.cpp
21
src/main.cpp
@ -598,6 +598,10 @@ void cmdLineHelp()
|
||||
" --disable-lan Disable LAN detection (connect using WAN).\n"
|
||||
" --auto-connect Automatically connect to fist server and start race\n"
|
||||
" --max-players=n Maximum number of clients (server only).\n"
|
||||
" --motd Message showing in all lobby of clients.\n"
|
||||
" --no-validation Allow non validated and unencrypted connection in wan.\n"
|
||||
" --ranked Server will submit ranking to stk addons server.\n"
|
||||
" You require permission for that.\n"
|
||||
" --no-console-log Does not write messages in the console but to\n"
|
||||
" stdout.log.\n"
|
||||
" -h, --help Show this help.\n"
|
||||
@ -1063,7 +1067,11 @@ int handleCmdLine()
|
||||
core::stringw motd = StringUtils::xmlDecode(s);
|
||||
NetworkConfig::get()->setMOTD(motd);
|
||||
}
|
||||
|
||||
if (CommandLine::has("--ranked"))
|
||||
{
|
||||
NetworkConfig::get()->setValidatedPlayers(true);
|
||||
NetworkConfig::get()->setRankedServer(true);
|
||||
}
|
||||
if (CommandLine::has("--server-id-file", &s))
|
||||
{
|
||||
NetworkConfig::get()->setServerIdFile(
|
||||
@ -1140,6 +1148,14 @@ int handleCmdLine()
|
||||
NetworkConfig::get()->setIsServer(true);
|
||||
NetworkConfig::get()->setIsWAN();
|
||||
NetworkConfig::get()->setIsPublicServer();
|
||||
if (CommandLine::has("--no-validation"))
|
||||
{
|
||||
NetworkConfig::get()->setValidatedPlayers(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkConfig::get()->setValidatedPlayers(true);
|
||||
}
|
||||
server_lobby = STKHost::create();
|
||||
Log::info("main", "Creating a WAN server '%s'.", s.c_str());
|
||||
}
|
||||
@ -1149,6 +1165,7 @@ int handleCmdLine()
|
||||
NetworkConfig::get()->setServerName(StringUtils::xmlDecode(s));
|
||||
NetworkConfig::get()->setIsServer(true);
|
||||
NetworkConfig::get()->setIsLAN();
|
||||
NetworkConfig::get()->setValidatedPlayers(false);
|
||||
server_lobby = STKHost::create();
|
||||
Log::info("main", "Creating a LAN server '%s'.", s.c_str());
|
||||
}
|
||||
@ -1162,7 +1179,7 @@ int handleCmdLine()
|
||||
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
|
||||
{
|
||||
LobbyProtocol::get<LobbyProtocol>()->getGameSetup()
|
||||
->setSoccerGoalTarget((bool)n);
|
||||
->setSoccerGoalTarget(n != 0);
|
||||
NetworkConfig::get()->setServerMode(
|
||||
race_manager->getMinorMode(),
|
||||
RaceManager::MAJOR_MODE_SINGLE);
|
||||
|
@ -80,7 +80,7 @@ public:
|
||||
/** \brief Get the players that are in the game
|
||||
* \return A vector containing pointers on the players profiles. */
|
||||
std::vector<std::shared_ptr<NetworkPlayerProfile> >
|
||||
getConnectedPlayers(bool same_index_for_disconnected = false) const
|
||||
getConnectedPlayers() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_players_mutex);
|
||||
std::vector<std::shared_ptr<NetworkPlayerProfile> > players;
|
||||
@ -88,8 +88,6 @@ public:
|
||||
{
|
||||
if (auto player_connected = player_weak.lock())
|
||||
players.push_back(player_connected);
|
||||
else if (same_index_for_disconnected)
|
||||
players.push_back(nullptr);
|
||||
}
|
||||
return players;
|
||||
} // getConnectedPlayers
|
||||
|
@ -50,6 +50,7 @@ NetworkConfig::NetworkConfig()
|
||||
m_is_server = false;
|
||||
m_is_public_server = false;
|
||||
m_is_ranked_server = false;
|
||||
m_validated_players = false;
|
||||
m_done_adding_network_players = false;
|
||||
m_max_players = 4;
|
||||
m_cur_user_id = 0;
|
||||
|
@ -90,6 +90,9 @@ private:
|
||||
* immediately start a race. */
|
||||
bool m_auto_connect;
|
||||
|
||||
/** True if only validated players are allowed to join. */
|
||||
bool m_validated_players;
|
||||
|
||||
bool m_done_adding_network_players;
|
||||
|
||||
/** If this is a server, the server name. */
|
||||
@ -267,7 +270,8 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if the server use multi-session rankings. */
|
||||
bool isRankedServer() const { return m_is_ranked_server; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void setRankedServer(bool val) { m_is_ranked_server = val; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the minor and majar game mode from server database id. */
|
||||
std::pair<RaceManager::MinorRaceModeType, RaceManager::MajorRaceModeType>
|
||||
@ -303,6 +307,10 @@ public:
|
||||
core::stringw getModeName(unsigned id);
|
||||
// ------------------------------------------------------------------------
|
||||
std::vector<GUIEngine::Screen*> getResetScreens(bool lobby = false) const;
|
||||
// ------------------------------------------------------------------------
|
||||
void setValidatedPlayers(bool val) { m_validated_players = val; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool onlyValidatedPlayers() const { return m_validated_players; }
|
||||
|
||||
}; // class NetworkConfig
|
||||
|
||||
|
@ -123,6 +123,7 @@ void LobbyProtocol::configRemoteKart(
|
||||
rki.setGlobalPlayerId(i);
|
||||
rki.setDefaultKartColor(profile->getDefaultKartColor());
|
||||
rki.setPerPlayerDifficulty(profile->getPerPlayerDifficulty());
|
||||
rki.setOnlineId(profile->getOnlineId());
|
||||
// Inform the race manager about the data for this kart.
|
||||
race_manager->setPlayerKart(i, rki);
|
||||
} // for i in players
|
||||
|
@ -91,6 +91,12 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
||||
setHandleDisconnections(true);
|
||||
m_state = SET_PUBLIC_ADDRESS;
|
||||
updateBanList();
|
||||
if (NetworkConfig::get()->isRankedServer())
|
||||
{
|
||||
Log::info("ServerLobby", "This server will submit ranking scores to "
|
||||
"STK addons server, don't bother host one if you don't have the "
|
||||
"corresponding permission, they will be rejected if so.");
|
||||
}
|
||||
} // ServerLobby
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -291,6 +297,7 @@ void ServerLobby::asynchronousUpdate()
|
||||
}
|
||||
case ACCEPTING_CLIENTS:
|
||||
{
|
||||
clearDisconnectedRankedPlayer();
|
||||
// Only poll the STK server if this is a WAN server.
|
||||
if (NetworkConfig::get()->isWAN())
|
||||
checkIncomingConnectionRequests();
|
||||
@ -759,9 +766,6 @@ void ServerLobby::checkRaceFinished()
|
||||
total->addUInt32(last_score).addUInt32(cur_score)
|
||||
.addFloat(overall_time);
|
||||
}
|
||||
|
||||
if (NetworkConfig::get()->isRankedServer())
|
||||
computeNewRankings();
|
||||
}
|
||||
else if (race_manager->modeHasLaps())
|
||||
{
|
||||
@ -769,6 +773,11 @@ void ServerLobby::checkRaceFinished()
|
||||
static_cast<LinearWorld*>(World::getWorld())->getFastestLapTicks();
|
||||
total->addUInt32(fastest_lap);
|
||||
}
|
||||
if (NetworkConfig::get()->isRankedServer())
|
||||
{
|
||||
computeNewRankings();
|
||||
submitRankingsToAddons();
|
||||
}
|
||||
|
||||
stopCurrentRace();
|
||||
// Set the delay before the server forces all clients to exit the race
|
||||
@ -782,85 +791,79 @@ void ServerLobby::checkRaceFinished()
|
||||
} // checkRaceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Compute the new player's rankings in ranked servers
|
||||
* //FIXME : this function assumes that m_rankings,
|
||||
* m_num_ranked_races and m_max_ranking
|
||||
* are correctly filled before
|
||||
* It also assumes that the data stored by them
|
||||
* is written back to the main list after the GP
|
||||
/** Compute the new player's rankings used in ranked servers
|
||||
*/
|
||||
void ServerLobby::computeNewRankings()
|
||||
{
|
||||
auto players = m_game_setup->getConnectedPlayers(true/*same_index_for_disconnected*/);
|
||||
|
||||
assert (m_rankings.size() == players.size() &&
|
||||
m_num_ranked_races.size() == players.size() &&
|
||||
m_max_ranking.size() == players.size() );
|
||||
|
||||
// No ranking yet for battle mode
|
||||
// TODO : separate rankings for time-trial and normal ??
|
||||
// No ranking for battle mode
|
||||
if (!race_manager->modeHasLaps())
|
||||
return;
|
||||
|
||||
// Using a vector of vector, it would be possible to fill
|
||||
// all j < i v[i][j] with -v[j][i]
|
||||
// Would this be worth it ?
|
||||
std::vector<double> ranking_change;
|
||||
std::vector<double> scores_change;
|
||||
std::vector<double> new_scores;
|
||||
|
||||
auto players = m_game_setup->getPlayers();
|
||||
for (unsigned i = 0; i < players.size(); i++)
|
||||
{
|
||||
m_rankings[i] += distributeBasePoints(i);
|
||||
const uint32_t id = race_manager->getKartInfo(i).getOnlineId();
|
||||
new_scores.push_back(m_scores.at(id));
|
||||
new_scores[i] += distributeBasePoints(id);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < players.size(); i++)
|
||||
{
|
||||
ranking_change.push_back(0);
|
||||
|
||||
int player1_ranking = m_rankings[i];
|
||||
scores_change.push_back(0.0);
|
||||
|
||||
double player1_scores = new_scores[i];
|
||||
// If the player has quitted before the race end,
|
||||
// the value will be incorrect, but it will not be used
|
||||
float player1_time = race_manager->getKartRaceTime(i);
|
||||
float player1_factor = computeRankingFactor(i);
|
||||
double player1_time = race_manager->getKartRaceTime(i);
|
||||
double player1_factor =
|
||||
computeRankingFactor(race_manager->getKartInfo(i).getOnlineId());
|
||||
|
||||
for (unsigned j = 0; j < players.size(); i++)
|
||||
for (unsigned j = 0; j < players.size(); j++)
|
||||
{
|
||||
// Don't compare a player with itself
|
||||
// Don't compare a player with himself
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
double result = 0.0f;
|
||||
double expected_result = 0.0f;
|
||||
double ranking_importance = 0.0f;
|
||||
double result = 0.0;
|
||||
double expected_result = 0.0;
|
||||
double ranking_importance = 0.0;
|
||||
|
||||
// No change between two quitting players
|
||||
if (!players[i] && !players[j])
|
||||
if (players[i].expired() && players[j].expired())
|
||||
continue;
|
||||
|
||||
int player2_ranking = m_rankings[j];
|
||||
float player2_time = race_manager->getKartRaceTime(j);
|
||||
double player2_scores = new_scores[j];
|
||||
double player2_time = race_manager->getKartRaceTime(j);
|
||||
|
||||
// Compute the expected result using an ELO-like function
|
||||
double diff = (double) player2_ranking - player1_ranking;
|
||||
expected_result = 1.0f/(1.0f+std::pow(10.0f, diff/(BASE_RANKING_POINTS*getModeSpread()/(2.0f))));
|
||||
double diff = player2_scores - player1_scores;
|
||||
expected_result = 1.0/ (1.0 + std::pow(10.0,
|
||||
diff / (BASE_RANKING_POINTS * getModeSpread() / 2.0)));
|
||||
|
||||
// Compute the result and race ranking importance
|
||||
float player_factors = std::max(player1_factor,
|
||||
computeRankingFactor(j) );
|
||||
|
||||
float mode_factor = getModeFactor();
|
||||
double player_factors = std::max(player1_factor,
|
||||
computeRankingFactor(
|
||||
race_manager->getKartInfo(j).getOnlineId()));
|
||||
|
||||
if (!players[i])
|
||||
double mode_factor = getModeFactor();
|
||||
|
||||
if (players[i].expired())
|
||||
{
|
||||
result = 0.0f;
|
||||
ranking_importance =
|
||||
mode_factor*MAX_SCALING_TIME*MAX_POINTS_PER_SECOND*player_factors;
|
||||
result = 0.0;
|
||||
ranking_importance = mode_factor *
|
||||
MAX_SCALING_TIME * MAX_POINTS_PER_SECOND * player_factors;
|
||||
}
|
||||
else if (!players[j])
|
||||
else if (players[j].expired())
|
||||
{
|
||||
result = 1.0f;
|
||||
ranking_importance =
|
||||
mode_factor*MAX_SCALING_TIME*MAX_POINTS_PER_SECOND*player_factors;
|
||||
result = 1.0;
|
||||
ranking_importance = mode_factor *
|
||||
MAX_SCALING_TIME * MAX_POINTS_PER_SECOND * player_factors;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -868,88 +871,91 @@ void ServerLobby::computeNewRankings()
|
||||
// Otherwise, it is averaged between 0 and 1.
|
||||
if (player1_time <= player2_time)
|
||||
{
|
||||
result = (player2_time - player1_time)/(player1_time/20);
|
||||
result = std::min( (double) 1.0f, 0.5f + result);
|
||||
result =
|
||||
(player2_time - player1_time) / (player1_time / 20.0);
|
||||
result = std::min(1.0, 0.5 + result);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (player1_time - player2_time)/(player2_time/20);
|
||||
result = std::max( (double) 0.0f, 0.5f - result);
|
||||
result =
|
||||
(player1_time - player2_time) / (player2_time / 20.0);
|
||||
result = std::max(0.0, 0.5 - result);
|
||||
}
|
||||
ranking_importance = mode_factor * std::min ( std::max (player1_time, player2_time),
|
||||
MAX_SCALING_TIME ) * MAX_POINTS_PER_SECOND * player_factors;
|
||||
ranking_importance = mode_factor *
|
||||
std::min(
|
||||
std::max(player1_time, player2_time), MAX_SCALING_TIME) *
|
||||
MAX_POINTS_PER_SECOND * player_factors;
|
||||
}
|
||||
// Compute the ranking change
|
||||
ranking_change[i] += ranking_importance * (result - expected_result);
|
||||
scores_change[i] +=
|
||||
ranking_importance * (result - expected_result);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't merge it in the main loop as m_rankings value are used there
|
||||
// Don't merge it in the main loop as new_scores value are used there
|
||||
for (unsigned i = 0; i < players.size(); i++)
|
||||
{
|
||||
m_rankings[i] += ranking_change[i];
|
||||
|
||||
if (m_rankings[i] > m_max_ranking[i])
|
||||
m_max_ranking[i] = m_rankings[i];
|
||||
m_num_ranked_races[i]++;
|
||||
new_scores[i] += scores_change[i];
|
||||
const uint32_t id = race_manager->getKartInfo(i).getOnlineId();
|
||||
m_scores.at(id) = new_scores[i];
|
||||
if (m_scores.at(id) > m_max_scores.at(id))
|
||||
m_max_scores.at(id) = m_scores.at(id);
|
||||
m_num_ranked_races.at(id)++;
|
||||
}
|
||||
} //computeNewRankings
|
||||
} // computeNewRankings
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Compute the ranking factor, used to make top rankings more stable
|
||||
* and to allow new players to faster get to an appropriate ranking
|
||||
*/
|
||||
float ServerLobby::computeRankingFactor(unsigned int player_id)
|
||||
double ServerLobby::computeRankingFactor(uint32_t online_id)
|
||||
{
|
||||
double max_points = m_max_ranking[player_id];
|
||||
int num_races = m_num_ranked_races[player_id];
|
||||
double max_points = m_max_scores.at(online_id);
|
||||
unsigned num_races = m_num_ranked_races.at(online_id);
|
||||
|
||||
if ( max_points >= (BASE_RANKING_POINTS * 2.0f))
|
||||
return 0.4f;
|
||||
else if (max_points >= (BASE_RANKING_POINTS * 1.75f) || num_races > 500)
|
||||
return 0.5f;
|
||||
else if (max_points >= (BASE_RANKING_POINTS * 1.5f) || num_races > 250)
|
||||
return 0.6f;
|
||||
else if (max_points >= (BASE_RANKING_POINTS * 1.25f) || num_races > 100)
|
||||
return 0.7f;
|
||||
if (max_points >= (BASE_RANKING_POINTS * 2.0))
|
||||
return 0.4;
|
||||
else if (max_points >= (BASE_RANKING_POINTS * 1.75) || num_races > 500)
|
||||
return 0.5;
|
||||
else if (max_points >= (BASE_RANKING_POINTS * 1.5) || num_races > 250)
|
||||
return 0.6;
|
||||
else if (max_points >= (BASE_RANKING_POINTS * 1.25) || num_races > 100)
|
||||
return 0.7;
|
||||
// The base ranking points are not distributed all at once
|
||||
// So it's not guaranteed a player reach them
|
||||
else if (max_points >= (BASE_RANKING_POINTS ) || num_races > 50)
|
||||
return 0.8f;
|
||||
else if (max_points >= (BASE_RANKING_POINTS) || num_races > 50)
|
||||
return 0.8;
|
||||
else
|
||||
return 1.0f;
|
||||
return 1.0;
|
||||
|
||||
} //computeRankingFactor
|
||||
} // computeRankingFactor
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the mode race importance factor,
|
||||
* used to make ranking move slower in more random modes.
|
||||
*/
|
||||
float ServerLobby::getModeFactor()
|
||||
double ServerLobby::getModeFactor()
|
||||
{
|
||||
if (race_manager->isTimeTrialMode())
|
||||
return 1.0f;
|
||||
|
||||
//else
|
||||
return 0.4f;
|
||||
}
|
||||
return 1.0;
|
||||
return 0.4;
|
||||
} // getModeFactor
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the mode spread factor, used so that a similar difference in
|
||||
* skill will result in a similar ranking difference in more random modes.
|
||||
*/
|
||||
float ServerLobby::getModeSpread()
|
||||
double ServerLobby::getModeSpread()
|
||||
{
|
||||
if (race_manager->isTimeTrialMode())
|
||||
return 1.0f;
|
||||
return 1.0;
|
||||
|
||||
//else
|
||||
//TODO : the value used here for normal races is a wild guess.
|
||||
//TODO: the value used here for normal races is a wild guess.
|
||||
// When hard data to the spread tendencies of time-trial
|
||||
// and normal mode becomes available, update this to make
|
||||
// the spreads more comparable
|
||||
return 1.4f;
|
||||
}
|
||||
return 1.4;
|
||||
} // getModeSpread
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Manages the distribution of the base points.
|
||||
@ -958,14 +964,18 @@ float ServerLobby::getModeSpread()
|
||||
* The first half is distributed when the player enters
|
||||
* for the first time in the ranked server.
|
||||
*/
|
||||
float ServerLobby::distributeBasePoints(unsigned int player_id)
|
||||
double ServerLobby::distributeBasePoints(uint32_t online_id)
|
||||
{
|
||||
int num_races = m_num_ranked_races[player_id];
|
||||
unsigned num_races = m_num_ranked_races.at(online_id);
|
||||
if (num_races < 45)
|
||||
return (BASE_RANKING_POINTS/2000.0f * std::max((45-num_races),4)*2.0f);
|
||||
{
|
||||
return
|
||||
(BASE_RANKING_POINTS / 2000.0 * std::max((45u - num_races), 4u) *
|
||||
2.0);
|
||||
}
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
return 0.0;
|
||||
} // distributeBasePoints
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Stop any race currently in server, should only be called in main thread.
|
||||
@ -1013,6 +1023,26 @@ void ServerLobby::clientDisconnected(Event* event)
|
||||
delete msg;
|
||||
} // clientDisconnected
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::clearDisconnectedRankedPlayer()
|
||||
{
|
||||
for (auto it = m_ranked_players.begin(); it != m_ranked_players.end();)
|
||||
{
|
||||
if (it->second.expired())
|
||||
{
|
||||
const uint32_t id = it->first;
|
||||
m_scores.erase(id);
|
||||
m_max_scores.erase(id);
|
||||
m_num_ranked_races.erase(id);
|
||||
it = m_ranked_players.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
} // clearDisconnectedRankedPlayer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::connectionRequested(Event* event)
|
||||
{
|
||||
@ -1143,6 +1173,26 @@ void ServerLobby::connectionRequested(Event* event)
|
||||
return;
|
||||
}
|
||||
|
||||
// Reject non-valiated player joinning if WAN server and not disabled
|
||||
// encforement of validation, unless it's player from localhost or lan
|
||||
// And no duplicated online id or split screen players in ranked server
|
||||
if ((encrypted_size == 0 &&
|
||||
!(peer->getAddress().isPublicAddressLocalhost() ||
|
||||
peer->getAddress().isLAN()) &&
|
||||
NetworkConfig::get()->isWAN() &&
|
||||
NetworkConfig::get()->onlyValidatedPlayers()) ||
|
||||
((player_count != 1 || m_scores.find(online_id) != m_scores.end()) &&
|
||||
NetworkConfig::get()->isRankedServer()))
|
||||
{
|
||||
NetworkString* message = getNetworkString(2);
|
||||
message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_INVALID_PLAYER);
|
||||
peer->sendPacket(message, true/*reliable*/, false/*encrypted*/);
|
||||
peer->reset();
|
||||
delete message;
|
||||
Log::verbose("ServerLobby", "Player refused: invalid player");
|
||||
return;
|
||||
}
|
||||
|
||||
if (encrypted_size != 0)
|
||||
{
|
||||
m_pending_connection[peer] = std::make_pair(online_id,
|
||||
@ -1177,6 +1227,19 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
|
||||
return;
|
||||
}
|
||||
|
||||
// Check again for duplicated online id in ranked server
|
||||
if (m_scores.find(online_id) != m_scores.end() &&
|
||||
NetworkConfig::get()->isRankedServer())
|
||||
{
|
||||
NetworkString* message = getNetworkString(2);
|
||||
message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_INVALID_PLAYER);
|
||||
peer->sendPacket(message, true/*reliable*/, false/*encrypted*/);
|
||||
peer->reset();
|
||||
delete message;
|
||||
Log::verbose("ServerLobby", "Player refused: invalid player");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned player_count = data.getUInt8();
|
||||
for (unsigned i = 0; i < player_count; i++)
|
||||
{
|
||||
@ -1233,6 +1296,11 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
|
||||
npp->getOnlineId(), peer->getAddress().toString().c_str());
|
||||
}
|
||||
updatePlayerList();
|
||||
|
||||
if (NetworkConfig::get()->isRankedServer())
|
||||
{
|
||||
getRankingForPlayer(peer->getPlayerProfiles()[0]);
|
||||
}
|
||||
} // handleUnencryptedConnection
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1649,3 +1717,82 @@ bool ServerLobby::decryptConnectionRequest(std::shared_ptr<STKPeer> peer,
|
||||
}
|
||||
return false;
|
||||
} // decryptConnectionRequest
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::getRankingForPlayer(std::shared_ptr<NetworkPlayerProfile> p)
|
||||
{
|
||||
Online::XMLRequest* request = new Online::XMLRequest();
|
||||
NetworkConfig::get()->setUserDetails(request, "get-ranking");
|
||||
|
||||
const uint32_t id = p->getOnlineId();
|
||||
request->addParameter("id", id);
|
||||
request->executeNow();
|
||||
|
||||
const XMLNode* result = request->getXMLData();
|
||||
std::string rec_success;
|
||||
|
||||
// Default result
|
||||
double score = 2000.0;
|
||||
double max_score = 2000.0;
|
||||
unsigned num_races = 0;
|
||||
if (result->get("success", &rec_success))
|
||||
{
|
||||
if (rec_success == "yes")
|
||||
{
|
||||
result->get("scores", &score);
|
||||
result->get("max-scores", &max_score);
|
||||
result->get("num-races-done", &num_races);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ServerLobby", "No ranking info found.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ServerLobby", "No ranking info found.");
|
||||
}
|
||||
m_ranked_players[id] = p;
|
||||
m_scores[id] = score;
|
||||
m_max_scores[id] = max_score;
|
||||
m_num_ranked_races[id] = num_races;
|
||||
delete request;
|
||||
} // getRankingForPlayer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ServerLobby::submitRankingsToAddons()
|
||||
{
|
||||
// No ranking for battle mode
|
||||
if (!race_manager->modeHasLaps())
|
||||
return;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
class SumbitRankingRequest : public Online::XMLRequest
|
||||
{
|
||||
public:
|
||||
SumbitRankingRequest(uint32_t online_id, double scores,
|
||||
double max_scores, unsigned num_races)
|
||||
: XMLRequest(true)
|
||||
{
|
||||
addParameter("id", online_id);
|
||||
addParameter("scores", scores);
|
||||
addParameter("max-scores", max_scores);
|
||||
addParameter("num-races-done", num_races);
|
||||
}
|
||||
}; // UpdatePlayerRankingRequest
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
|
||||
{
|
||||
const uint32_t id = race_manager->getKartInfo(i).getOnlineId();
|
||||
SumbitRankingRequest* request = new SumbitRankingRequest
|
||||
(id, m_scores.at(id), m_max_scores.at(id),
|
||||
m_num_ranked_races.at(id));
|
||||
NetworkConfig::get()->setUserDetails(request, "submit-ranking");
|
||||
Log::info("ServerLobby", "Submiting ranking for %s (%d) : %lf, %lf %d",
|
||||
StringUtils::wideToUtf8(
|
||||
race_manager->getKartInfo(i).getPlayerName()).c_str(), id,
|
||||
m_scores.at(id), m_max_scores.at(id), m_num_ranked_races.at(id));
|
||||
request->queue();
|
||||
}
|
||||
} // submitRankingsToAddons
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <tuple>
|
||||
|
||||
class BareNetworkString;
|
||||
class NetworkPlayerProfile;
|
||||
class STKPeer;
|
||||
|
||||
class ServerLobby : public LobbyProtocol
|
||||
@ -91,15 +92,22 @@ private:
|
||||
std::owner_less<std::weak_ptr<STKPeer> > > m_pending_connection;
|
||||
|
||||
/* Ranking related variables */
|
||||
|
||||
// If updating the base points, update the base points distribution in DB
|
||||
const float BASE_RANKING_POINTS = 4000.0f;
|
||||
const float MAX_SCALING_TIME = 600.0f;
|
||||
const float MAX_POINTS_PER_SECOND = 0.125f;
|
||||
const double BASE_RANKING_POINTS = 4000.0;
|
||||
const double MAX_SCALING_TIME = 600.0;
|
||||
const double MAX_POINTS_PER_SECOND = 0.125;
|
||||
|
||||
std::vector<double> m_rankings; // TODO : convert from and to int when communicating with the server. Think to round it correctly
|
||||
std::vector<unsigned int> m_num_ranked_races;
|
||||
std::vector<double> m_max_ranking;
|
||||
/** Online id to profile map, handling disconnection in ranked server */
|
||||
std::map<uint32_t, std::weak_ptr<NetworkPlayerProfile> > m_ranked_players;
|
||||
|
||||
/** Multi-session ranking scores for each current player */
|
||||
std::map<uint32_t, double> m_scores;
|
||||
|
||||
/** The maximum ranking scores achieved for each current player */
|
||||
std::map<uint32_t, double> m_max_scores;
|
||||
|
||||
/** Number of ranked races done for each current players */
|
||||
std::map<uint32_t, unsigned> m_num_ranked_races;
|
||||
|
||||
// connection management
|
||||
void clientDisconnected(Event* event);
|
||||
@ -160,11 +168,15 @@ private:
|
||||
const irr::core::stringw& online_name);
|
||||
std::tuple<std::string, uint8_t, bool, bool> handleVote();
|
||||
void stopCurrentRace();
|
||||
|
||||
void getRankingForPlayer(std::shared_ptr<NetworkPlayerProfile> p);
|
||||
void submitRankingsToAddons();
|
||||
void computeNewRankings();
|
||||
float computeRankingFactor(unsigned int player_id);
|
||||
float distributeBasePoints(unsigned int player_id);
|
||||
float getModeFactor();
|
||||
float getModeSpread();
|
||||
void clearDisconnectedRankedPlayer();
|
||||
double computeRankingFactor(uint32_t online_id);
|
||||
double distributeBasePoints(uint32_t online_id);
|
||||
double getModeFactor();
|
||||
double getModeSpread();
|
||||
|
||||
public:
|
||||
ServerLobby();
|
||||
|
@ -52,6 +52,7 @@ class RemoteKartInfo
|
||||
bool m_network_player;
|
||||
PerPlayerDifficulty m_difficulty;
|
||||
float m_default_kart_color;
|
||||
uint32_t m_online_id;
|
||||
public:
|
||||
RemoteKartInfo(int player_id, const std::string& kart_name,
|
||||
const irr::core::stringw& user_name, int host_id,
|
||||
@ -61,21 +62,21 @@ public:
|
||||
m_host_id(host_id), m_soccer_team(SOCCER_TEAM_NONE),
|
||||
m_network_player(network),
|
||||
m_difficulty(PLAYER_DIFFICULTY_NORMAL),
|
||||
m_default_kart_color(0.0f)
|
||||
m_default_kart_color(0.0f), m_online_id(0)
|
||||
{}
|
||||
RemoteKartInfo(const std::string& kart_name) : m_kart_name(kart_name),
|
||||
m_user_name(""), m_local_player_id(-1),
|
||||
m_global_player_id(-1), m_host_id(-1),
|
||||
m_soccer_team(SOCCER_TEAM_NONE), m_network_player(false),
|
||||
m_difficulty(PLAYER_DIFFICULTY_NORMAL),
|
||||
m_default_kart_color(0.0f)
|
||||
m_default_kart_color(0.0f), m_online_id(0)
|
||||
{}
|
||||
RemoteKartInfo() : m_kart_name(""), m_user_name(""),
|
||||
m_local_player_id(-1), m_global_player_id(-1),
|
||||
m_host_id(-1), m_soccer_team(SOCCER_TEAM_NONE),
|
||||
m_network_player(false),
|
||||
m_difficulty(PLAYER_DIFFICULTY_NORMAL),
|
||||
m_default_kart_color(0.0f)
|
||||
m_default_kart_color(0.0f), m_online_id(0)
|
||||
{}
|
||||
void setKartName(const std::string& n) { m_kart_name = n; }
|
||||
void setPlayerName(const irr::core::stringw& u) { m_user_name = u; }
|
||||
@ -87,6 +88,7 @@ public:
|
||||
void setDefaultKartColor(float value) { m_default_kart_color = value; }
|
||||
void setPerPlayerDifficulty(PerPlayerDifficulty value)
|
||||
{ m_difficulty = value; }
|
||||
void setOnlineId(uint32_t id) { m_online_id = id; }
|
||||
int getHostId() const { return m_host_id; }
|
||||
int getLocalPlayerId() const { return m_local_player_id; }
|
||||
int getGlobalPlayerId() const { return m_global_player_id; }
|
||||
@ -96,6 +98,7 @@ public:
|
||||
SoccerTeam getSoccerTeam() const { return m_soccer_team; }
|
||||
PerPlayerDifficulty getDifficulty() const { return m_difficulty; }
|
||||
float getDefaultKartColor() const { return m_default_kart_color; }
|
||||
uint32_t getOnlineId() const { return m_online_id; }
|
||||
|
||||
bool operator<(const RemoteKartInfo& other) const
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user