Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/engine/db/world_characters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ void Characters::push_front(const CharData::shared_ptr &character) {
}
character->subscribe_for_rnum_changes(m_rnum_change_observer);

if (!character->IsNpc()) {
m_players.insert(character.get()); // #3414: все игроки в игре
}

if (character->purged()) {
/*
* Anton Gorev (2017/10/29): It is possible is character quit the game without
Expand Down Expand Up @@ -166,6 +170,8 @@ void Characters::remove(CharData *character) {
character->ZeroCooldowns();
chardata_cooldown_list.erase(clist);
}
m_active.erase(character); // #3414: убрать из активного набора
m_players.erase(character); // #3414: убрать из списка игроков
m_list.erase(index_i->second);
m_character_raw_ptr_to_character_ptr.erase(index_i);
auto tmp_it = std::find_if(combat_list.begin(), combat_list.end(), [character] (auto it) {return (it.ch == character); });
Expand Down
19 changes: 19 additions & 0 deletions src/engine/db/world_characters.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <functional>
#include <unordered_map>
#include <unordered_set>
#include <vector>

class Characters {
public:
Expand Down Expand Up @@ -54,6 +55,22 @@ class Characters {
void AddToExtractedList(CharData *ch);
void PurgeExtractedList();

// #3414: активный набор для point_update. Мобы помечаются в mobile_activity
// (mark_active) и сбрасываются каждый point_update (clear_active); игроки
// держатся постоянно (наполняется в push_front, чистится в remove).
void mark_active(CharData *ch) { m_active.insert(ch); }
const auto &active() const { return m_active; }
const auto &players() const { return m_players; }
void clear_active() { m_active.clear(); }
// Снимок набора для point_update: активные мобы + все игроки (одним вектором).
std::vector<CharData *> active_and_players() const {
std::vector<CharData *> result;
result.reserve(m_active.size() + m_players.size());
result.insert(result.end(), m_active.begin(), m_active.end());
result.insert(result.end(), m_players.begin(), m_players.end());
return result;
}

private:
using character_raw_ptr_to_character_ptr_t = std::unordered_map<const void *, list_t::iterator>;
using set_t = std::unordered_set<const CharData *>;
Expand All @@ -63,6 +80,8 @@ class Characters {
std::unordered_set<CharData *> m_extracted_list;
character_raw_ptr_to_character_ptr_t m_character_raw_ptr_to_character_ptr;
vnum_to_characters_set_t m_vnum_to_characters_set;
std::unordered_set<CharData *> m_active; // #3414: активные мобы (за окно между point_update)
std::unordered_set<CharData *> m_players; // #3414: все игроки в игре
CharacterRNum_ChangeObserver::shared_ptr m_rnum_change_observer;
list_t m_purge_list;
set_t m_purge_set;
Expand Down
1 change: 1 addition & 0 deletions src/gameplay/ai/mobact.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,7 @@ void mobile_activity(int activity_level, int missed_pulses) {
continue;
}
++processed_mobs;
character_list.mark_active(ch.get()); // #3414: запомнить активного моба для point_update

// Examine call for special procedure
if (ch->IsFlagged(EMobFlag::kSpec) && !no_specials) {
Expand Down
14 changes: 9 additions & 5 deletions src/gameplay/core/game_limits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1534,13 +1534,17 @@ void point_update() {
double t_cond = 0.0, t_hp = 0.0, t_mob = 0.0, t_move = 0.0, t_pos = 0.0, t_idle = 0.0;
std::size_t scanned = 0, profiled_chars = 0;

for (auto &ch : character_list) {
const auto i = ch.get();
++scanned;
// #3414: вместо скана всего character_list -- только активные мобы (их
// помечает mobile_activity) и все игроки в игре. Снимок, чтобы отложенные
// extract не ломали обход set'ов между итерациями.
const auto to_update = character_list.active_and_players();
character_list.clear_active();

if (i->purged() || (i->IsNpc() && !i->in_used_zone())) {
for (auto *i : to_update) {
++scanned;
if (i->purged()) {
continue;
}
}

if (i->IsNpc()) {
i->inc_restore_timer(kSecsPerMudHour);
Expand Down
Loading