diff options
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Groups/Group.cpp | 75 | ||||
-rw-r--r-- | src/server/game/Groups/Group.h | 5 | ||||
-rw-r--r-- | src/server/game/Groups/GroupInstanceRefManager.h | 43 | ||||
-rw-r--r-- | src/server/game/Groups/GroupInstanceReference.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Groups/GroupInstanceReference.h | 40 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Maps/Map.h | 4 | ||||
-rw-r--r-- | src/server/game/Maps/MapManager.cpp | 2 |
9 files changed, 141 insertions, 98 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 5b4d2f42231..6018cdeee61 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -19353,46 +19353,26 @@ bool Player::CheckInstanceValidity(bool /*isLogin*/) // non-instances are always valid Map* map = FindMap(); - if (!map || !map->IsDungeon()) + InstanceMap* instance = map ? map->ToInstanceMap() : nullptr; + if (!instance) return true; + Group* group = GetGroup(); // raid instances require the player to be in a raid group to be valid if (map->IsRaid() && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID) && (map->GetEntry()->Expansion() >= sWorld->getIntConfig(CONFIG_EXPANSION))) - if (!GetGroup() || !GetGroup()->isRaidGroup()) + if (!group || !group->isRaidGroup()) return false; - if (Group* group = GetGroup()) + if (group) { - // check if player's group is bound to this instance - InstanceGroupBind* bind = group->GetBoundInstance(map->GetDifficultyID(), map->GetId()); - if (!bind || !bind->save || bind->save->GetInstanceId() != map->GetInstanceId()) + if (group != instance->GetOwningGroup()) return false; - - Map::PlayerList const& players = map->GetPlayers(); - if (!players.isEmpty()) - for (Map::PlayerList::const_iterator it = players.begin(); it != players.end(); ++it) - { - if (Player* otherPlayer = it->GetSource()) - { - if (otherPlayer->IsGameMaster()) - continue; - if (!otherPlayer->m_InstanceValid) // ignore players that currently have a homebind timer active - continue; - if (group != otherPlayer->GetGroup()) - return false; - } - } } else { // instance is invalid if we are not grouped and there are other players if (map->GetPlayersCountExceptGMs() > 1) return false; - - // check if the player is bound to this instance - InstancePlayerBind* bind = GetBoundInstance(map->GetId(), map->GetDifficultyID()); - if (!bind || !bind->save || bind->save->GetInstanceId() != map->GetInstanceId()) - return false; } return true; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 127b0dab275..f8929654908 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -193,7 +193,8 @@ bool Group::Create(Player* leader) CharacterDatabase.Execute(stmt); - Group::ConvertLeaderInstancesToGroup(leader, this, false); + if (InstanceMap* leaderInstance = leader->GetMap()->ToInstanceMap()) + leaderInstance->TrySetOwningGroup(this); bool addMemberResult = AddMember(leader); ASSERT(addMemberResult); // If the leader can't be added to a new group because it appears full, something is clearly wrong. @@ -715,9 +716,6 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid, int8 partyIndex) } } - // Copy the permanent binds from the new leader to the group - Group::ConvertLeaderInstancesToGroup(newLeader, this, true); - // Update the group leader CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_LEADER); @@ -744,43 +742,6 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid, int8 partyIndex) BroadcastPacket(groupNewLeader.Write(), true); } -/// convert the player's binds to the group -void Group::ConvertLeaderInstancesToGroup(Player* player, Group* group, bool switchLeader) -{ - // copy all binds to the group, when changing leader it's assumed the character - // will not have any solo binds - for (auto difficultyItr = player->m_boundInstances.begin(); difficultyItr != player->m_boundInstances.end(); ++difficultyItr) - { - for (auto itr = difficultyItr->second.begin(); itr != difficultyItr->second.end();) - { - if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficultyID(), itr->first)) - if (itr->second.extendState) // not expired - group->BindToInstance(itr->second.save, itr->second.perm, false); - - // permanent binds are not removed - if (switchLeader && !itr->second.perm) - { - // increments itr in call - player->UnbindInstance(itr, difficultyItr, false); - } - else - ++itr; - } - } - - /* if group leader is in a non-raid dungeon map and nobody is actually bound to this map then the group can "take over" the instance * - * (example: two-player group disbanded by disconnect where the player reconnects within 60 seconds and the group is reformed) */ - if (Map* playerMap = player->FindMap()) - if (!switchLeader && playerMap->IsNonRaidDungeon()) - if (InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(playerMap->GetInstanceId())) - if (save->GetGroupCount() == 0 && save->GetPlayerCount() == 0) - { - TC_LOG_DEBUG("maps", "Group::ConvertLeaderInstancesToGroup: Group for player %s is taking over unbound instance map %d with Id %d", player->GetName().c_str(), playerMap->GetId(), playerMap->GetInstanceId()); - // if nobody is saved to this, then the save wasn't permanent - group->BindToInstance(save, false, false); - } -} - void Group::Disband(bool hideDestroy /* = false */) { sScriptMgr->OnGroupDisband(this); @@ -1596,37 +1557,9 @@ InstanceGroupBind* Group::GetBoundInstance(Difficulty difficulty, uint32 mapId) return nullptr; } -InstanceGroupBind* Group::BindToInstance(InstanceSave* save, bool permanent, bool load) +void Group::LinkOwnedInstance(GroupInstanceReference* ref) { - if (!save || isBGGroup() || isBFGroup()) - return nullptr; - - InstanceGroupBind& bind = m_boundInstances[save->GetDifficultyID()][save->GetMapId()]; - if (!load && (!bind.save || permanent != bind.perm || save != bind.save)) - { - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GROUP_INSTANCE); - - stmt->setUInt32(0, m_dbStoreId); - stmt->setUInt32(1, save->GetInstanceId()); - stmt->setBool(2, permanent); - - CharacterDatabase.Execute(stmt); - } - - if (bind.save != save) - { - if (bind.save) - bind.save->RemoveGroup(this); - save->AddGroup(this); - } - - bind.save = save; - bind.perm = permanent; - if (!load) - TC_LOG_DEBUG("maps", "Group::BindToInstance: %s, storage id: %u is now bound to map %d, instance %d, difficulty %d", - GetGUID().ToString().c_str(), m_dbStoreId, save->GetMapId(), save->GetInstanceId(), static_cast<uint32>(save->GetDifficultyID())); - - return &bind; + m_ownedInstancesMgr.insertLast(ref); } void Group::UnbindInstance(uint32 mapid, uint8 difficulty, bool unload) diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index e3236b7eb6d..7860a81fd5c 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -20,6 +20,7 @@ #include "DBCEnums.h" #include "DatabaseEnvFwd.h" +#include "GroupInstanceRefManager.h" #include "GroupRefManager.h" #include "Object.h" #include "RaceMask.h" @@ -216,7 +217,6 @@ class TC_GAME_API Group bool AddMember(Player* player); bool RemoveMember(ObjectGuid guid, RemoveMethod method = GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker = ObjectGuid::Empty, const char* reason = nullptr); void ChangeLeader(ObjectGuid guid, int8 partyIndex = 0); - static void ConvertLeaderInstancesToGroup(Player* player, Group* group, bool switchLeader); void SetLootMethod(LootMethod method); void SetLooterGuid(ObjectGuid guid); void SetMasterLooterGuid(ObjectGuid guid); @@ -364,6 +364,8 @@ class TC_GAME_API Group m_recentInstances[mapId] = { instanceOwner, instanceId }; } + void LinkOwnedInstance(GroupInstanceReference* ref); + void UnbindInstance(uint32 mapid, uint8 difficulty, bool unload = false); InstanceGroupBind* GetBoundInstance(Player* player); InstanceGroupBind* GetBoundInstance(Map* aMap); @@ -410,6 +412,7 @@ class TC_GAME_API Group ObjectGuid m_masterLooterGuid; BoundInstancesMap m_boundInstances; std::unordered_map<uint32 /*mapId*/, std::pair<ObjectGuid /*instanceOwner*/, uint32 /*instanceId*/>> m_recentInstances; + GroupInstanceRefManager m_ownedInstancesMgr; uint8* m_subGroupsCounts; ObjectGuid m_guid; uint32 m_dbStoreId; // Represents the ID used in database (Can be reused by other groups if group was disbanded) diff --git a/src/server/game/Groups/GroupInstanceRefManager.h b/src/server/game/Groups/GroupInstanceRefManager.h new file mode 100644 index 00000000000..af6015f2355 --- /dev/null +++ b/src/server/game/Groups/GroupInstanceRefManager.h @@ -0,0 +1,43 @@ +/* + * This file is part of the TrinityCore 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GroupInstanceRefManager_h__ +#define GroupInstanceRefManager_h__ + +#include "GroupInstanceReference.h" +#include "RefManager.h" + +class Group; +class InstanceMap; + +class GroupInstanceRefManager : public RefManager<Group, InstanceMap> +{ +public: + typedef LinkedListHead::Iterator<GroupInstanceReference> iterator; + typedef LinkedListHead::Iterator<GroupInstanceReference const> const_iterator; + + GroupInstanceReference* getFirst() { return ((GroupInstanceReference*)RefManager<Group, InstanceMap>::getFirst()); } + GroupInstanceReference const* getFirst() const { return ((GroupInstanceReference const*)RefManager<Group, InstanceMap>::getFirst()); } + + iterator begin() { return iterator(getFirst()); } + iterator end() { return iterator(nullptr); } + + const_iterator begin() const { return const_iterator(getFirst()); } + const_iterator end() const { return const_iterator(nullptr); } +}; + +#endif // GroupInstanceRefManager_h__ diff --git a/src/server/game/Groups/GroupInstanceReference.cpp b/src/server/game/Groups/GroupInstanceReference.cpp new file mode 100644 index 00000000000..2628bb8074c --- /dev/null +++ b/src/server/game/Groups/GroupInstanceReference.cpp @@ -0,0 +1,32 @@ +/* + * This file is part of the TrinityCore 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, see <http://www.gnu.org/licenses/>. + */ + +#include "Group.h" +#include "GroupInstanceReference.h" + +void GroupInstanceReference::targetObjectBuildLink() +{ + getTarget()->LinkOwnedInstance(this); +} + +void GroupInstanceReference::targetObjectDestroyLink() +{ +} + +void GroupInstanceReference::sourceObjectDestroyLink() +{ +} diff --git a/src/server/game/Groups/GroupInstanceReference.h b/src/server/game/Groups/GroupInstanceReference.h new file mode 100644 index 00000000000..effe449d453 --- /dev/null +++ b/src/server/game/Groups/GroupInstanceReference.h @@ -0,0 +1,40 @@ +/* + * This file is part of the TrinityCore 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GroupInstanceReference_h__ +#define GroupInstanceReference_h__ + +#include "LinkedReference/Reference.h" + +class Group; +class InstanceMap; + +class TC_GAME_API GroupInstanceReference : public Reference<Group, InstanceMap> +{ +public: + GroupInstanceReference() : Reference<Group, InstanceMap>() { } + ~GroupInstanceReference() { unlink(); } + GroupInstanceReference* next() { return (GroupInstanceReference*)Reference<Group, InstanceMap>::next(); } + GroupInstanceReference const* next() const { return (GroupInstanceReference const*)Reference<Group, InstanceMap>::next(); } + +protected: + void targetObjectBuildLink() override; + void targetObjectDestroyLink() override; + void sourceObjectDestroyLink() override; +}; + +#endif // GroupInstanceReference_h__ diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index a30e752f555..4c838cd7d09 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2958,6 +2958,12 @@ void InstanceMap::CreateInstanceData() i_data->Create(); } +void InstanceMap::TrySetOwningGroup(Group* group) +{ + if (!i_owningGroupRef.isValid()) + i_owningGroupRef.link(group, this); +} + /* Returns true if there are no players in the instance */ diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index e3d622f49b0..e1e70b4ab6f 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -25,6 +25,7 @@ #include "DynamicTree.h" #include "GridDefines.h" #include "GridRefManager.h" +#include "GroupInstanceReference.h" #include "MapDefines.h" #include "MapReference.h" #include "MapRefManager.h" @@ -831,6 +832,8 @@ class TC_GAME_API InstanceMap : public Map Team GetTeamInInstance() const { return GetTeamIdInInstance() == TEAM_ALLIANCE ? ALLIANCE : HORDE; } virtual void InitVisibilityDistance() override; + Group* GetOwningGroup() const { return i_owningGroupRef.getTarget(); } + void TrySetOwningGroup(Group* group); std::string GetDebugInfo() const override; private: @@ -840,6 +843,7 @@ class TC_GAME_API InstanceMap : public Map uint32 i_script_id; InstanceScenario* i_scenario; InstanceLock* i_instanceLock; + GroupInstanceReference i_owningGroupRef; }; class TC_GAME_API BattlegroundMap : public Map diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index a89324eb1a1..8a525d2b64e 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -103,6 +103,8 @@ InstanceMap* MapManager::CreateInstance(uint32 mapId, uint32 instanceId, Instanc map->LoadRespawnTimes(); map->LoadCorpseData(); + if (group) + map->TrySetOwningGroup(group); map->CreateInstanceData(); map->SetInstanceScenario(sScenarioMgr->CreateInstanceScenario(map, team)); |