Lessen breakup kicks and more (#625)

This commit is contained in:
maybegreat48
2022-11-21 15:42:12 +00:00
committed by GitHub
parent abad615531
commit 64b47779e8
46 changed files with 1109 additions and 146 deletions

View File

@ -2,6 +2,7 @@
#include "player_service.hpp"
#include "vehicle/CVehicle.hpp"
#include "network/snSession.hpp"
#include "rate_limiter.hpp"
namespace big
{
@ -33,21 +34,25 @@ namespace big
[[nodiscard]] CPlayerInfo* get_player_info() const;
[[nodiscard]] class rage::snPlayer* get_session_player();
[[nodiscard]] class rage::snPeer* get_session_peer();
[[nodiscard]] uint8_t id() const;
[[nodiscard]] bool is_friend() const;
[[nodiscard]] bool is_host() const;
[[nodiscard]] bool is_valid() const;
bool off_radar = false;
bool never_wanted = false;
bool semi_godmode = false;
std::chrono::system_clock::time_point m_last_transition_msg_sent{};
int m_num_failed_transition_attempts = 0;
rate_limiter m_host_migration_rate_limit{ 1s, 20 };
rate_limiter m_play_sound_rate_limit{ 1s, 10 };
bool exposed_desync_protection = false;
bool is_modder = false;
bool block_join = false;
int block_join_reason = 0;
bool is_spammer = false;
protected:
bool equals(const CNetGamePlayer* net_game_player) const;

View File

@ -30,15 +30,6 @@ namespace big
m_players.clear();
}
player_ptr player_service::get_by_name(std::string name)
{
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
if (const auto it = m_players.find(name); it != m_players.end())
return it->second;
return nullptr;
}
player_ptr player_service::get_by_msg_id(uint32_t msg_id) const
{
for (const auto& [_, player] : m_players)
@ -49,7 +40,7 @@ namespace big
player_ptr player_service::get_by_id(uint32_t id) const
{
for (const auto& [name, player] : m_players)
for (const auto& [_, player] : m_players)
if (player->id() == id)
return player;
return nullptr;
@ -57,7 +48,7 @@ namespace big
player_ptr player_service::get_by_host_token(uint64_t token) const
{
for (const auto& [name, player] : m_players)
for (const auto& [_, player] : m_players)
if (player->get_net_data()->m_host_token == token)
return player;
return nullptr;
@ -83,10 +74,10 @@ namespace big
if (net_game_player == nullptr || net_game_player == *m_self) return;
auto plyr = std::make_shared<player>(net_game_player);
m_players.emplace(
plyr->to_lowercase_identifier(),
m_players.insert({
plyr->get_name(),
std::move(plyr)
);
});
}
void player_service::player_leave(CNetGamePlayer* net_game_player)
@ -95,8 +86,10 @@ namespace big
if (m_selected_player && m_selected_player->equals(net_game_player))
m_selected_player = m_dummy;
auto plyr = std::make_unique<player>(net_game_player);
m_players.erase(plyr->to_lowercase_identifier());
if (auto it = std::find_if(m_players.begin(), m_players.end(), [net_game_player](const auto& p) { return p.second->id() == net_game_player->m_player_id; }); it != m_players.end())
{
m_players.erase(it);
}
}
void player_service::set_selected(player_ptr plyr)

View File

@ -7,7 +7,7 @@ namespace big
using player_ptr = std::shared_ptr<player>;
using player_entry = std::pair<std::string, player_ptr>;
using players = std::map<std::string, player_ptr>;
using players = std::multimap<std::string, player_ptr>;
class player_service final
{
@ -33,7 +33,6 @@ namespace big
[[nodiscard]] player_ptr get_self();
[[nodiscard]] player_ptr get_by_name(std::string name);
[[nodiscard]] player_ptr get_by_msg_id(uint32_t msg_id) const;
[[nodiscard]] player_ptr get_by_id(uint32_t id) const;
[[nodiscard]] player_ptr get_by_host_token(uint64_t token) const;
@ -45,7 +44,7 @@ namespace big
players& players()
{ return m_players; }
void iterate(const std::function< void(const player_entry &entry) > func)
void iterate(const std::function< void(const player_entry &entry)> func)
{ for (const auto &iter : m_players) func(iter); }
void set_selected(player_ptr plyr);

View File

@ -0,0 +1,40 @@
#pragma once
namespace big
{
class rate_limiter
{
std::uint32_t m_attempts_allowed_in_time_period;
std::chrono::milliseconds m_time_period;
std::chrono::system_clock::time_point m_last_event_time{};
std::uint32_t m_num_attempts_allowed = 0;
public:
rate_limiter(std::chrono::milliseconds time_period, std::uint32_t num_allowed_attempts) :
m_attempts_allowed_in_time_period(num_allowed_attempts),
m_time_period(time_period)
{
}
// Returns true if the rate limit has been exceeded
bool process()
{
if (std::chrono::system_clock::now() - m_last_event_time < m_time_period)
{
if (++m_num_attempts_allowed > m_attempts_allowed_in_time_period)
return true;
}
else
{
m_last_event_time = std::chrono::system_clock::now();
m_num_attempts_allowed = 1;
}
return false;
}
// Check if the rate limit was exceeded by the last process() call. Use this to prevent the player from being flooded with notifications
bool exceeded_last_process()
{
return (m_num_attempts_allowed - 1) == m_attempts_allowed_in_time_period;
}
};
}