Skip to content

Commit

Permalink
BattleGround: Wave 1 of safeguards against race conditions
Browse files Browse the repository at this point in the history
BattleGround handler and BattleGround class still need to be massively reworked but this makes it a little bette
  • Loading branch information
killerwife committed Aug 17, 2024
1 parent 0924070 commit 618cfc7
Show file tree
Hide file tree
Showing 20 changed files with 239 additions and 79 deletions.
16 changes: 12 additions & 4 deletions src/game/BattleGround/BattleGround.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,12 @@ BattleGround::~BattleGround()
// skip template bgs as they were never added to visible bg list
BattleGroundBracketId bracketId = GetBracketId();
if (bracketId != BG_BRACKET_ID_TEMPLATE)
sBattleGroundMgr.DeleteClientVisibleInstanceId(GetTypeId(), bracketId, GetClientInstanceId());
{
sBattleGroundMgr.GetMessager().AddMessage([typeId = GetTypeId(), bracketId, clientInstanceId = GetClientInstanceId()](BattleGroundMgr* mgr)
{
mgr->DeleteClientVisibleInstanceId(typeId, bracketId, clientInstanceId);
});
}

// unload map
// map can be null at bg destruction
Expand Down Expand Up @@ -1368,7 +1373,10 @@ void BattleGround::RemovePlayerAtLeave(ObjectGuid playerGuid, bool isOnTransport
{
// a player has left the battleground, so there are free slots -> add to queue
AddToBgFreeSlotQueue();
sBattleGroundMgr.ScheduleQueueUpdate(0, ARENA_TYPE_NONE, bgQueueTypeId, bgTypeId, GetBracketId());
sBattleGroundMgr.GetMessager().AddMessage([bgQueueTypeId, bgTypeId, bracketId = GetBracketId()](BattleGroundMgr* mgr)
{
mgr->ScheduleQueueUpdate(0, ARENA_TYPE_NONE, bgQueueTypeId, bgTypeId, bracketId);
});
}

// Let others know
Expand Down Expand Up @@ -1845,7 +1853,7 @@ Team BattleGround::GetPrematureWinner()
*/
void BattleGround::OnObjectDBLoad(Creature* creature)
{
const BattleGroundEventIdx eventId = sBattleGroundMgr.GetCreatureEventIndex(creature->GetDbGuid());
const BattleGroundEventIdx eventId = GetBgMap()->GetMapDataContainer().GetCreatureEventIndex(creature->GetDbGuid());
if (eventId.event1 == BG_EVENT_NONE)
return;

Expand Down Expand Up @@ -1876,7 +1884,7 @@ uint32 BattleGround::GetSingleCreatureGuid(uint8 event1, uint8 event2)
*/
void BattleGround::OnObjectDBLoad(GameObject* obj)
{
const BattleGroundEventIdx eventId = sBattleGroundMgr.GetGameObjectEventIndex(obj->GetDbGuid());
const BattleGroundEventIdx eventId = GetBgMap()->GetMapDataContainer().GetGameObjectEventIndex(obj->GetDbGuid());
if (eventId.event1 == BG_EVENT_NONE)
return;

Expand Down
3 changes: 2 additions & 1 deletion src/game/BattleGround/BattleGround.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "Maps/Map.h"
#include "Util/ByteBuffer.h"
#include "Entities/ObjectGuid.h"
#include "BattleGround/BattleGroundDefines.h"

// magic event-numbers
#define BG_EVENT_NONE 255
Expand Down Expand Up @@ -642,7 +643,7 @@ class BattleGround
// returns the other team index
static PvpTeamIndex GetOtherTeamIndex(PvpTeamIndex teamIdx) { return teamIdx == TEAM_INDEX_ALLIANCE ? TEAM_INDEX_HORDE : TEAM_INDEX_ALLIANCE; }

// checke if player is inside battleground
// check if player is inside battleground
bool IsPlayerInBattleGround(ObjectGuid /*playerGuid*/);

// Handle script condition fulfillment
Expand Down
2 changes: 1 addition & 1 deletion src/game/BattleGround/BattleGroundAB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ void BattleGroundAB::HandlePlayerClickedOnFlag(Player* player, GameObject* go)
uint32 factionStrig = 0;

// process battleground event
uint8 event = (sBattleGroundMgr.GetGameObjectEventIndex(go->GetDbGuid())).event1;
uint8 event = (GetBgMap()->GetMapDataContainer().GetGameObjectEventIndex(go->GetDbGuid())).event1;
if (event >= BG_AB_MAX_NODES) // not a node
return;

Expand Down
4 changes: 2 additions & 2 deletions src/game/BattleGround/BattleGroundAV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,12 +650,12 @@ void BattleGroundAV::HandlePlayerClickedOnFlag(Player* player, GameObject* go)

DEBUG_LOG("BattleGroundAV: Player from team %u clicked on gameobject entry %u", player->GetTeam(), go->GetEntry());

uint8 event = (sBattleGroundMgr.GetGameObjectEventIndex(go->GetDbGuid())).event1;
uint8 event = (GetBgMap()->GetMapDataContainer().GetGameObjectEventIndex(go->GetDbGuid())).event1;
if (event >= BG_AV_MAX_NODES) // not a node
return;
AVNodeIds node = AVNodeIds(event);

switch ((sBattleGroundMgr.GetGameObjectEventIndex(go->GetDbGuid())).event2 % BG_AV_MAX_STATES)
switch ((GetBgMap()->GetMapDataContainer().GetGameObjectEventIndex(go->GetDbGuid())).event2 % BG_AV_MAX_STATES)
{
case POINT_CONTROLLED:
ProcessPlayerAssaultsPoint(player, node);
Expand Down
55 changes: 55 additions & 0 deletions src/game/BattleGround/BattleGroundDefines.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#ifndef MANGOSSERVER_BATTLEGROUND_DEFINES_H
#define MANGOSSERVER_BATTLEGROUND_DEFINES_H

#include "Common.h"

// indexes of BattlemasterList.dbc
enum BattleGroundTypeId
{
BATTLEGROUND_TYPE_NONE = 0,
BATTLEGROUND_AV = 1,
BATTLEGROUND_WS = 2,
BATTLEGROUND_AB = 3,
BATTLEGROUND_NA = 4,
BATTLEGROUND_BE = 5,
BATTLEGROUND_AA = 6, // all arenas
BATTLEGROUND_EY = 7,
BATTLEGROUND_RL = 8,
BATTLEGROUND_SA = 9,
BATTLEGROUND_DS = 10,
BATTLEGROUND_RV = 11,
BATTLEGROUND_IC = 30,
BATTLEGROUND_RB = 32 // random battleground
};
#define MAX_BATTLEGROUND_TYPE_ID 33

enum ArenaType
{
ARENA_TYPE_NONE = 0, // used for mark non-arenas or problematic cases
ARENA_TYPE_2v2 = 2,
ARENA_TYPE_3v3 = 3,
ARENA_TYPE_5v5 = 5
};

inline bool IsArenaTypeValid(ArenaType type) { return type == ARENA_TYPE_2v2 || type == ARENA_TYPE_3v3 || type == ARENA_TYPE_5v5; }

#endif // MANGOSSERVER_BATTLEGROUND_DEFINES_H

2 changes: 1 addition & 1 deletion src/game/BattleGround/BattleGroundHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket& recv_data)
if (uint32 pauseTimer = pCreature->GetInteractionPauseTimer())
pCreature->GetMotionMaster()->PauseWaypoints(pauseTimer);

BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(pCreature->GetEntry());
BattleGroundTypeId bgTypeId = GetPlayer()->GetMap()->GetMapDataContainer().GetBattleMasterBG(pCreature->GetEntry());

if (bgTypeId == BATTLEGROUND_TYPE_NONE)
return;
Expand Down
50 changes: 40 additions & 10 deletions src/game/BattleGround/BattleGroundMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1295,6 +1295,8 @@ void BattleGroundMgr::DeleteAllBattleGrounds()
*/
void BattleGroundMgr::Update(uint32 diff)
{
m_messager.Execute(this);

// update scheduled queues
if (!m_queueUpdateScheduler.empty())
{
Expand Down Expand Up @@ -2658,9 +2660,9 @@ uint32 BattleGroundMgr::GetPrematureFinishTime() const
/**
Method that loads battlemaster entries from DB
*/
void BattleGroundMgr::LoadBattleMastersEntry()
void BattleGroundMgr::LoadBattleMastersEntry(bool reload)
{
m_battleMastersMap.clear(); // need for reload case
std::shared_ptr<BattleMastersMap> newBattleMastersMap = std::make_shared<BattleMastersMap>();

auto queryResult = WorldDatabase.Query("SELECT entry,bg_template FROM battlemaster_entry");

Expand Down Expand Up @@ -2692,10 +2694,23 @@ void BattleGroundMgr::LoadBattleMastersEntry()
continue;
}

m_battleMastersMap[entry] = BattleGroundTypeId(bgTypeId);
(*newBattleMastersMap)[entry] = BattleGroundTypeId(bgTypeId);
}
while (queryResult->NextRow());

m_battleMastersMap = newBattleMastersMap;

if (reload)
{
sMapMgr.DoForAllMaps([battleMasters = newBattleMastersMap](Map* map)
{
map->GetMessager().AddMessage([battleMasters](Map* map)
{
map->GetMapDataContainer().SetBattleMastersMap(battleMasters);
});
});
}

sLog.outString(">> Loaded %u battlemaster entries", count);
sLog.outString();
}
Expand Down Expand Up @@ -2749,15 +2764,15 @@ bool BattleGroundMgr::IsBgWeekend(BattleGroundTypeId bgTypeId)
/**
Method that loads battleground events used in battleground scripts
*/
void BattleGroundMgr::LoadBattleEventIndexes()
void BattleGroundMgr::LoadBattleEventIndexes(bool reload)
{
BattleGroundEventIdx events;
events.event1 = BG_EVENT_NONE;
events.event2 = BG_EVENT_NONE;
m_gameObjectBattleEventIndexMap.clear(); // need for reload case
m_gameObjectBattleEventIndexMap[static_cast<uint32>(-1)] = events;
m_creatureBattleEventIndexMap.clear(); // need for reload case
m_creatureBattleEventIndexMap[static_cast<uint32>(-1)] = events;
std::shared_ptr<GameObjectBattleEventIndexesMap> newGameObjectIndexes = std::make_shared<GameObjectBattleEventIndexesMap>();
(*newGameObjectIndexes)[static_cast<uint32>(-1)] = events;
std::shared_ptr<CreatureBattleEventIndexesMap> newCreatureIndexes = std::make_shared<CreatureBattleEventIndexesMap>();
(*newCreatureIndexes)[static_cast<uint32>(-1)] = events;

uint32 count = 0;

Expand Down Expand Up @@ -2846,14 +2861,29 @@ void BattleGroundMgr::LoadBattleEventIndexes()
}

if (gameobject)
m_gameObjectBattleEventIndexMap[dbTableGuidLow] = events;
(*newGameObjectIndexes)[dbTableGuidLow] = events;
else
m_creatureBattleEventIndexMap[dbTableGuidLow] = events;
(*newCreatureIndexes)[dbTableGuidLow] = events;

++count;
}
while (queryResult->NextRow());

m_gameObjectBattleEventIndexMap = newGameObjectIndexes;
m_creatureBattleEventIndexMap = newCreatureIndexes;

if (reload)
{
sMapMgr.DoForAllMaps([gameobjects = newGameObjectIndexes, creatures = newCreatureIndexes](Map* map)
{
map->GetMessager().AddMessage([gameobjects, creatures](Map* map)
{
map->GetMapDataContainer().SetGameObjectEventIndexes(gameobjects);
map->GetMapDataContainer().SetCreatureEventIndexes(creatures);
});
});
}

sLog.outString(">> Loaded %u battleground eventindexes", count);
sLog.outString();
}
35 changes: 22 additions & 13 deletions src/game/BattleGround/BattleGroundMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,35 +248,40 @@ class BattleGroundMgr
void ToggleArenaTesting();
void ToggleTesting();

void LoadBattleMastersEntry();
void LoadBattleMastersEntry(bool reload);
BattleGroundTypeId GetBattleMasterBG(uint32 entry) const
{
BattleMastersMap::const_iterator itr = m_battleMastersMap.find(entry);
if (itr != m_battleMastersMap.end())
BattleMastersMap::const_iterator itr = m_battleMastersMap->find(entry);
if (itr != m_battleMastersMap->end())
return itr->second;

return BATTLEGROUND_TYPE_NONE;
}
std::shared_ptr<BattleMastersMap> GetBattleMastersMap() const { return m_battleMastersMap; }

void LoadBattleEventIndexes();
void LoadBattleEventIndexes(bool reload);
const BattleGroundEventIdx GetCreatureEventIndex(uint32 dbGuid) const
{
CreatureBattleEventIndexesMap::const_iterator itr = m_creatureBattleEventIndexMap.find(dbGuid);
if (itr != m_creatureBattleEventIndexMap.end())
CreatureBattleEventIndexesMap::const_iterator itr = m_creatureBattleEventIndexMap->find(dbGuid);
if (itr != m_creatureBattleEventIndexMap->end())
return itr->second;

return m_creatureBattleEventIndexMap.find(static_cast<uint32>(-1))->second;
return m_creatureBattleEventIndexMap->find(static_cast<uint32>(-1))->second;
}

std::shared_ptr<CreatureBattleEventIndexesMap> GetCreatureEventIndexes() const { return m_creatureBattleEventIndexMap; }

const BattleGroundEventIdx GetGameObjectEventIndex(uint32 dbGuid) const
{
GameObjectBattleEventIndexesMap::const_iterator itr = m_gameObjectBattleEventIndexMap.find(dbGuid);
if (itr != m_gameObjectBattleEventIndexMap.end())
GameObjectBattleEventIndexesMap::const_iterator itr = m_gameObjectBattleEventIndexMap->find(dbGuid);
if (itr != m_gameObjectBattleEventIndexMap->end())
return itr->second;

return m_gameObjectBattleEventIndexMap.find(static_cast<uint32>(-1))->second;
return m_gameObjectBattleEventIndexMap->find(static_cast<uint32>(-1))->second;
}

std::shared_ptr<GameObjectBattleEventIndexesMap> GetGameObjectEventIndexes() const { return m_gameObjectBattleEventIndexMap; }

bool IsArenaTesting() const { return m_arenaTesting; }
bool IsTesting() const { return m_testing; }

Expand All @@ -291,11 +296,13 @@ class BattleGroundMgr
static bool IsBgWeekend(BattleGroundTypeId /*bgTypeId*/);

std::set<uint32> const& GetUsedRefLootIds() const { return m_usedRefloot; }

Messager<BattleGroundMgr>& GetMessager() { return m_messager; }
private:
std::mutex schedulerLock;
BattleMastersMap m_battleMastersMap;
CreatureBattleEventIndexesMap m_creatureBattleEventIndexMap;
GameObjectBattleEventIndexesMap m_gameObjectBattleEventIndexMap;
std::shared_ptr<BattleMastersMap> m_battleMastersMap;
std::shared_ptr<CreatureBattleEventIndexesMap> m_creatureBattleEventIndexMap;
std::shared_ptr<GameObjectBattleEventIndexesMap> m_gameObjectBattleEventIndexMap;

/* Battlegrounds */
BattleGroundSet m_battleGrounds[MAX_BATTLEGROUND_TYPE_ID];
Expand All @@ -308,6 +315,8 @@ class BattleGroundMgr
bool m_arenaTesting;
bool m_testing;
std::set<uint32> m_usedRefloot;

Messager<BattleGroundMgr> m_messager;
};

#define sBattleGroundMgr MaNGOS::Singleton<BattleGroundMgr>::Instance()
Expand Down
20 changes: 16 additions & 4 deletions src/game/Chat/Level3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,10 @@ bool ChatHandler::HandleReloadItemRequiredTragetCommand(char* /*args*/)
bool ChatHandler::HandleReloadBattleEventCommand(char* /*args*/)
{
sLog.outString("Re-Loading BattleGround Eventindexes...");
sBattleGroundMgr.LoadBattleEventIndexes();
sBattleGroundMgr.GetMessager().AddMessage([](BattleGroundMgr* mgr)
{
mgr->LoadBattleEventIndexes(true);
});
SendGlobalSysMessage("DB table `gameobject_battleground` and `creature_battleground` reloaded.");
return true;
}
Expand Down Expand Up @@ -7224,7 +7227,10 @@ bool ChatHandler::HandleSendMessageCommand(char* args)

bool ChatHandler::HandleArenaFlushPointsCommand(char* /*args*/)
{
sBattleGroundMgr.DistributeArenaPoints();
sBattleGroundMgr.GetMessager().AddMessage([](BattleGroundMgr* mgr)
{
mgr->DistributeArenaPoints();
});
return true;
}

Expand All @@ -7237,7 +7243,10 @@ bool ChatHandler::HandleArenaSeasonRewardsCommand(char* args)
if (seasonId > 4 || seasonId == 0)
return false;

sBattleGroundMgr.RewardArenaSeason(seasonId);
sBattleGroundMgr.GetMessager().AddMessage([seasonId](BattleGroundMgr* mgr)
{
mgr->RewardArenaSeason(seasonId);
});
return true;
}

Expand All @@ -7251,7 +7260,10 @@ bool ChatHandler::HandleArenaDataReset(char* args)
}

PSendSysMessage("Resetting all arena data.");
sBattleGroundMgr.ResetAllArenaData();
sBattleGroundMgr.GetMessager().AddMessage([](BattleGroundMgr* mgr)
{
mgr->ResetAllArenaData();
});
return true;
}

Expand Down
10 changes: 8 additions & 2 deletions src/game/Chat/debugcmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -741,13 +741,19 @@ bool ChatHandler::HandleDebugGetItemStateCommand(char* args)

bool ChatHandler::HandleDebugBattlegroundCommand(char* /*args*/)
{
sBattleGroundMgr.ToggleTesting();
sBattleGroundMgr.GetMessager().AddMessage([](BattleGroundMgr* mgr)
{
mgr->ToggleTesting();
});
return true;
}

bool ChatHandler::HandleDebugArenaCommand(char* /*args*/)
{
sBattleGroundMgr.ToggleArenaTesting();
sBattleGroundMgr.GetMessager().AddMessage([](BattleGroundMgr* mgr)
{
mgr->ToggleArenaTesting();
});
return true;
}

Expand Down
Loading

0 comments on commit 618cfc7

Please sign in to comment.