Lessen breakup kicks and more (#625)
This commit is contained in:
@ -73,13 +73,13 @@ namespace big
|
||||
|
||||
void mobile_service::register_vehicles()
|
||||
{
|
||||
const auto array_size = *mobile::vehicle_global.as<int*>();
|
||||
const auto array_size = *scr_globals::vehicle_global.as<int*>();
|
||||
for (int i = 0; i < array_size; i++)
|
||||
{
|
||||
if (i % 100 == 0)
|
||||
script::get_current()->yield();
|
||||
|
||||
auto veh_idx_global = mobile::vehicle_global.at(i, 142);
|
||||
auto veh_idx_global = scr_globals::vehicle_global.at(i, 142);
|
||||
|
||||
const auto hash = *veh_idx_global.at(66).as<Hash*>();
|
||||
const auto& it = m_pv_lookup.find(i);
|
||||
|
@ -41,7 +41,7 @@ namespace big
|
||||
|
||||
for (auto& p : json.items())
|
||||
{
|
||||
m_players[std::stoi(p.key())] = p.value().get<persistent_player>();
|
||||
m_players[std::stoll(p.key())] = p.value().get<persistent_player>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
40
src/services/players/rate_limiter.hpp
Normal file
40
src/services/players/rate_limiter.hpp
Normal 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;
|
||||
}
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user