mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-02-02 02:13:47 +00:00
Add thread safety for group operations (#1816)
Fixes crashes and race conditions when bots perform group/guild/arena operations by moving thread-unsafe code to world thread. Potentially fixes #1124 ## Changes - Added operation queue system that runs in world thread - Group operations (invite, remove, convert to raid, set leader) now queued - Arena formation refactored to use queue - Guild operations changed to use packet queueing ## Testing Set `MapUpdate.Threads` > 1 in worldserver.conf to enable multiple map threads, then test: - Group formation and disbanding - Arena team formation - Guild operations (invite, promote, demote, remove) - Run with TSAN cmake ../ \ -DCMAKE_CXX_FLAGS="-fsanitize=thread -g -O1" \ -DCMAKE_C_FLAGS="-fsanitize=thread -g -O1" \ -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=thread" \ -DCMAKE_INSTALL_PREFIX=/path/to/install \ -DCMAKE_BUILD_TYPE=RelWithDebInfo build export TSAN_OPTIONS="log_path=tsan_report:halt_on_error=0:second_deadlock_stack=1" ./worldserver The crashes/race conditions should no longer occur with concurrent map threads. ## New Files - `PlayerbotOperation.h` - Base class defining the operation interface (Execute, IsValid, GetPriority) - `PlayerbotOperations.h` - Concrete implementations: GroupInviteOperation, GroupRemoveMemberOperation, GroupConvertToRaidOperation, GroupSetLeaderOperation, ArenaGroupFormationOperation - `PlayerbotWorldThreadProcessor.h/cpp` - Singleton processor with mutex-protected queue, processes operations in WorldScript::OnUpdate hook, handles batch processing and validation --------- Co-authored-by: blinkysc <blinkysc@users.noreply.github.com> Co-authored-by: SaW <swerkhoven@outlook.com> Co-authored-by: bash <hermensb@gmail.com>
This commit is contained in:
@@ -9,7 +9,9 @@
|
||||
#include "Event.h"
|
||||
#include "GuildMgr.h"
|
||||
#include "Log.h"
|
||||
#include "PlayerbotOperations.h"
|
||||
#include "Playerbots.h"
|
||||
#include "PlayerbotWorldThreadProcessor.h"
|
||||
#include "ServerFacade.h"
|
||||
|
||||
bool InviteToGroupAction::Invite(Player* inviter, Player* player)
|
||||
@@ -27,7 +29,10 @@ bool InviteToGroupAction::Invite(Player* inviter, Player* player)
|
||||
{
|
||||
if (GET_PLAYERBOT_AI(player) && !GET_PLAYERBOT_AI(player)->IsRealPlayer())
|
||||
if (!group->isRaidGroup() && group->GetMembersCount() > 4)
|
||||
group->ConvertToRaid();
|
||||
{
|
||||
auto convertOp = std::make_unique<GroupConvertToRaidOperation>(inviter->GetGUID());
|
||||
sPlayerbotWorldProcessor->QueueOperation(std::move(convertOp));
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket p;
|
||||
@@ -89,7 +94,10 @@ bool InviteNearbyToGroupAction::Execute(Event event)
|
||||
// When inviting the 5th member of the group convert to raid for future invites.
|
||||
if (group && botAI->GetGrouperType() > GrouperType::LEADER_5 && !group->isRaidGroup() &&
|
||||
bot->GetGroup()->GetMembersCount() > 3)
|
||||
group->ConvertToRaid();
|
||||
{
|
||||
auto convertOp = std::make_unique<GroupConvertToRaidOperation>(bot->GetGUID());
|
||||
sPlayerbotWorldProcessor->QueueOperation(std::move(convertOp));
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->inviteChat && sRandomPlayerbotMgr->IsRandomBot(bot))
|
||||
{
|
||||
@@ -221,7 +229,8 @@ bool InviteGuildToGroupAction::Execute(Event event)
|
||||
if (group && botAI->GetGrouperType() > GrouperType::LEADER_5 && !group->isRaidGroup() &&
|
||||
bot->GetGroup()->GetMembersCount() > 3)
|
||||
{
|
||||
group->ConvertToRaid();
|
||||
auto convertOp = std::make_unique<GroupConvertToRaidOperation>(bot->GetGUID());
|
||||
sPlayerbotWorldProcessor->QueueOperation(std::move(convertOp));
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->inviteChat &&
|
||||
@@ -362,7 +371,10 @@ bool LfgAction::Execute(Event event)
|
||||
if (param.empty() || param == "5" || group->isRaidGroup())
|
||||
return false; // Group or raid is full so stop trying.
|
||||
else
|
||||
group->ConvertToRaid(); // We want a raid but are in a group so convert and continue.
|
||||
{
|
||||
auto convertOp = std::make_unique<GroupConvertToRaidOperation>(requester->GetGUID());
|
||||
sPlayerbotWorldProcessor->QueueOperation(std::move(convertOp));
|
||||
}
|
||||
}
|
||||
|
||||
Group::MemberSlotList const& groupSlot = group->GetMemberSlots();
|
||||
|
||||
Reference in New Issue
Block a user