[Shared Tasks] Avoid erasing shared tasks while iterating (#2348)

This wasn't safe since the erase would invalidate iterators used
internally by the range loops.

Shared tasks with no members are now also cleaned up

Make GetMembers return reference instead of copy (this is used a lot)

Add rule for shared task terminate time for easier debugging
This commit is contained in:
hg 2022-07-31 14:24:21 -04:00 committed by GitHub
parent 0dfc6eaa15
commit c4a99aabd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 21 deletions

View File

@ -556,6 +556,7 @@ RULE_BOOL(TaskSystem, KeepOneRecordPerCompletedTask, true, "Keep only one record
RULE_BOOL(TaskSystem, EnableTaskProximity, true, "Enable task proximity system")
RULE_INT(TaskSystem, RequestCooldownTimerSeconds, 15, "Seconds between allowing characters to request tasks (live-like default: 15 seconds)")
RULE_INT(TaskSystem, SharedTasksWorldProcessRate, 6000, "Timer interval (milliseconds) that shared tasks are processed in world")
RULE_INT(TaskSystem, SharedTasksTerminateTimerMS, 120000, "Delay (milliseconds) until a shared task is terminated if requirements are no longer met after member removal (default: 2 minutes)")
RULE_CATEGORY_END()
RULE_CATEGORY(Range)

View File

@ -7,7 +7,7 @@ std::vector<SharedTaskActivityStateEntry> SharedTask::GetActivityState() const
return m_shared_task_activity_state;
}
std::vector<SharedTaskMember> SharedTask::GetMembers() const
const std::vector<SharedTaskMember>& SharedTask::GetMembers() const
{
return m_members;
}

View File

@ -183,7 +183,7 @@ public:
SharedTaskMember FindMemberFromCharacterName(const std::string& character_name) const;
SharedTaskMember GetLeader() const;
std::vector<SharedTaskActivityStateEntry> GetActivityState() const;
std::vector<SharedTaskMember> GetMembers() const;
const std::vector<SharedTaskMember>& GetMembers() const;
// getters
const std::vector<TaskActivitiesRepository::TaskActivities> &GetTaskActivityData() const;

View File

@ -241,20 +241,6 @@ void SharedTaskManager::RemoveEveryoneFromSharedTask(SharedTask *t, uint32 reque
PrintSharedTaskState();
}
void SharedTaskManager::Terminate(SharedTask* s)
{
LogTasksDetail("[Process] Terminating shared task [{}]", s->GetDbSharedTask().id);
for (const auto& member : s->GetMembers())
{
SendRemovePlayerFromSharedTaskPacket(member.character_id, s->GetTaskData().id, true);
client_list.SendCharacterMessageID(member.character_id, Chat::Yellow, TaskStr::HAS_ENDED, {s->GetTaskData().title});
}
RemoveAllMembersFromDynamicZones(s);
DeleteSharedTask(s->GetDbSharedTask().id);
}
void SharedTaskManager::DeleteSharedTask(int64 shared_task_id)
{
LogTasksDetail(
@ -1679,14 +1665,21 @@ void SharedTaskManager::SetSharedTasks(const std::vector<SharedTask> &shared_tas
SharedTaskManager *SharedTaskManager::PurgeExpiredSharedTasks()
{
std::vector<int64_t> delete_tasks;
auto now = std::time(nullptr);
for (auto &s: m_shared_tasks) {
if (s.GetDbSharedTask().expire_time > 0 && s.GetDbSharedTask().expire_time <= now) {
LogTasksDetail("[PurgeExpiredSharedTasks] Deleting expired task [{}]", s.GetDbSharedTask().id);
DeleteSharedTask(s.GetDbSharedTask().id);
delete_tasks.push_back(s.GetDbSharedTask().id);
}
}
for (int64_t shared_task_id : delete_tasks)
{
DeleteSharedTask(shared_task_id);
}
return this;
}
@ -1764,7 +1757,7 @@ void SharedTaskManager::HandleCompletedTask(SharedTask* s)
void SharedTaskManager::StartTerminateTimer(SharedTask* s)
{
s->terminate_timer.Start(120000); // 2min
s->terminate_timer.Start(RuleI(TaskSystem, SharedTasksTerminateTimerMS));
SendMembersMessageID(s, Chat::Red, TaskStr::REQS_TWO_MIN);
}
@ -1775,11 +1768,27 @@ void SharedTaskManager::Process()
return;
}
std::vector<int64_t> delete_tasks;
for (auto& shared_task : m_shared_tasks)
{
if (shared_task.terminate_timer.Check())
if (shared_task.GetMembers().empty() || shared_task.terminate_timer.Check())
{
Terminate(&shared_task);
LogTasksDetail("[Process] Terminating shared task [{}]", shared_task.GetDbSharedTask().id);
for (const auto& member : shared_task.GetMembers())
{
SendRemovePlayerFromSharedTaskPacket(member.character_id, shared_task.GetTaskData().id, true);
client_list.SendCharacterMessageID(member.character_id, Chat::Yellow, TaskStr::HAS_ENDED, {shared_task.GetTaskData().title});
}
RemoveAllMembersFromDynamicZones(&shared_task);
// avoid erasing from m_shared_tasks while iterating it
delete_tasks.push_back(shared_task.GetDbSharedTask().id);
}
}
for (int64_t shared_task_id : delete_tasks)
{
DeleteSharedTask(shared_task_id);
}
}

View File

@ -132,7 +132,6 @@ protected:
void RecordSharedTaskCompletion(SharedTask *s);
void RemoveAllMembersFromDynamicZones(SharedTask *s);
void StartTerminateTimer(SharedTask* s);
void Terminate(SharedTask* s);
// memory search
std::vector<SharedTaskMember> FindCharactersInSharedTasks(const std::vector<uint32_t> &find_characters);