mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 10:37:03 +00:00
[10114] Store associated InstanceSave for dungeon map in Map object
This commit is contained in:
parent
6f4481a591
commit
67a7892075
9 changed files with 89 additions and 62 deletions
|
|
@ -1736,8 +1736,8 @@ void Group::_homebindIfInstance(Player *player)
|
|||
{
|
||||
// leaving the group in an instance, the homebind timer is started
|
||||
// unless the player is permanently saved to the instance
|
||||
InstanceSave *save = sInstanceSaveMgr.GetInstanceSave(player->GetInstanceId());
|
||||
InstancePlayerBind *playerBind = save ? player->GetBoundInstance(save->GetMapId(), save->GetDifficulty()) : NULL;
|
||||
Map* map = player->GetMap();
|
||||
InstancePlayerBind *playerBind = map->IsDungeon() ? player->GetBoundInstance(map->GetId(), map->GetDifficulty()) : NULL;
|
||||
if(!playerBind || !playerBind->perm)
|
||||
player->m_InstanceValid = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ INSTANTIATE_SINGLETON_1( InstanceSaveManager );
|
|||
|
||||
InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset)
|
||||
: m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId),
|
||||
m_difficulty(difficulty), m_canReset(canReset)
|
||||
m_difficulty(difficulty), m_canReset(canReset), m_usedByMap(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ void InstanceSave::DeleteFromDB()
|
|||
/* true if the instance save is still valid */
|
||||
bool InstanceSave::UnloadIfEmpty()
|
||||
{
|
||||
if(m_playerList.empty() && m_groupList.empty())
|
||||
if (m_playerList.empty() && m_groupList.empty() && !m_usedByMap)
|
||||
{
|
||||
sInstanceSaveMgr.RemoveInstanceSave(GetInstanceId());
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -95,9 +95,17 @@ class InstanceSave
|
|||
but that would depend on a lot of things that can easily change in future */
|
||||
Difficulty GetDifficulty() { return m_difficulty; }
|
||||
|
||||
void SetUsedByMapState(bool state)
|
||||
{
|
||||
m_usedByMap = state;
|
||||
if (!state)
|
||||
UnloadIfEmpty();
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::list<Player*> PlayerListType;
|
||||
typedef std::list<Group*> GroupListType;
|
||||
private:
|
||||
|
||||
bool UnloadIfEmpty();
|
||||
/* the only reason the instSave-object links are kept is because
|
||||
the object-instSave links need to be broken at reset time
|
||||
|
|
@ -109,6 +117,7 @@ class InstanceSave
|
|||
uint32 m_mapid;
|
||||
Difficulty m_difficulty;
|
||||
bool m_canReset;
|
||||
bool m_usedByMap; // true when instance map loaded
|
||||
};
|
||||
|
||||
/* resetTime is a global propery of each (raid/heroic) map
|
||||
|
|
@ -170,9 +179,6 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
|
|||
InstanceSaveManager();
|
||||
~InstanceSaveManager();
|
||||
|
||||
typedef UNORDERED_MAP<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap;
|
||||
typedef UNORDERED_MAP<uint32 /*mapId*/, InstanceSaveHashMap> InstanceSaveMapMap;
|
||||
|
||||
void CleanupInstances();
|
||||
void PackInstances();
|
||||
|
||||
|
|
@ -182,8 +188,6 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
|
|||
void RemoveInstanceSave(uint32 InstanceId);
|
||||
static void DeleteInstanceFromDB(uint32 instanceid);
|
||||
|
||||
InstanceSave *GetInstanceSave(uint32 InstanceId);
|
||||
|
||||
/* statistics */
|
||||
uint32 GetNumInstanceSaves() { return m_instanceSaveById.size(); }
|
||||
uint32 GetNumBoundPlayersTotal();
|
||||
|
|
@ -191,6 +195,11 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
|
|||
|
||||
void Update() { m_Scheduler.Update(); }
|
||||
private:
|
||||
typedef UNORDERED_MAP<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap;
|
||||
typedef UNORDERED_MAP<uint32 /*mapId*/, InstanceSaveHashMap> InstanceSaveMapMap;
|
||||
|
||||
InstanceSave *GetInstanceSave(uint32 InstanceId);
|
||||
|
||||
// called by scheduler
|
||||
void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeleft);
|
||||
void _ResetInstance(uint32 mapid, uint32 instanceId);
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ bool ChatHandler::HandleGonameCommand(const char* args)
|
|||
InstanceGroupBind *gBind = group ? group->GetBoundInstance(target) : NULL;
|
||||
// if no bind exists, create a solo bind
|
||||
if (!gBind)
|
||||
if (InstanceSave *save = sInstanceSaveMgr.GetInstanceSave(target->GetInstanceId()))
|
||||
if (InstanceSave *save = target->GetMap()->GetInstanceSave())
|
||||
_player->BindToInstance(save, !save->CanReset());
|
||||
}
|
||||
|
||||
|
|
|
|||
104
src/game/Map.cpp
104
src/game/Map.cpp
|
|
@ -54,6 +54,9 @@ Map::~Map()
|
|||
|
||||
if(!m_scriptSchedule.empty())
|
||||
sWorld.DecreaseScheduledScriptCount(m_scriptSchedule.size());
|
||||
|
||||
if (m_instanceSave)
|
||||
m_instanceSave->SetUsedByMapState(false); // field pointer can be deleted after this
|
||||
}
|
||||
|
||||
void Map::LoadVMap(int gx,int gy)
|
||||
|
|
@ -126,7 +129,7 @@ void Map::LoadMapAndVMap(int gx,int gy)
|
|||
Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent)
|
||||
: i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode),
|
||||
i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0),
|
||||
m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE),
|
||||
m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE), m_instanceSave(NULL),
|
||||
m_activeNonPlayersIter(m_activeNonPlayers.end()),
|
||||
i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this)
|
||||
{
|
||||
|
|
@ -1723,6 +1726,13 @@ InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 Spaw
|
|||
// the timer is started by default, and stopped when the first player joins
|
||||
// this make sure it gets unloaded if for some reason no player joins
|
||||
m_unloadTimer = std::max(sWorld.getConfig(CONFIG_UINT32_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY);
|
||||
|
||||
// Dungeon only code
|
||||
if(IsDungeon())
|
||||
{
|
||||
m_instanceSave = sInstanceSaveMgr.AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true);
|
||||
m_instanceSave->SetUsedByMapState(true);
|
||||
}
|
||||
}
|
||||
|
||||
InstanceMap::~InstanceMap()
|
||||
|
|
@ -1783,58 +1793,73 @@ bool InstanceMap::Add(Player *player)
|
|||
|
||||
{
|
||||
Guard guard(*this);
|
||||
if(!CanEnter(player))
|
||||
if (!CanEnter(player))
|
||||
return false;
|
||||
|
||||
// Dungeon only code
|
||||
if(IsDungeon())
|
||||
if (IsDungeon())
|
||||
{
|
||||
// get or create an instance save for the map
|
||||
InstanceSave *mapSave = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
|
||||
if(!mapSave)
|
||||
{
|
||||
DETAIL_LOG("InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId());
|
||||
mapSave = sInstanceSaveMgr.AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true);
|
||||
}
|
||||
|
||||
// check for existing instance binds
|
||||
InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), Difficulty(GetSpawnMode()));
|
||||
if(playerBind && playerBind->perm)
|
||||
if (playerBind && playerBind->perm)
|
||||
{
|
||||
// cannot enter other instances if bound permanently
|
||||
if(playerBind->save != mapSave)
|
||||
if (playerBind->save != GetInstanceSave())
|
||||
{
|
||||
sLog.outError("InstanceMap::Add: player %s(%d) is permanently bound to instance %d,%d,%d,%d,%d,%d but he is being put in instance %d,%d,%d,%d,%d,%d", player->GetName(), player->GetGUIDLow(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset());
|
||||
sLog.outError("InstanceMap::Add: player %s(%d) is permanently bound to instance %d,%d,%d,%d,%d,%d but he is being put in instance %d,%d,%d,%d,%d,%d",
|
||||
player->GetName(), player->GetGUIDLow(), playerBind->save->GetMapId(),
|
||||
playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(),
|
||||
playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(),
|
||||
playerBind->save->CanReset(),
|
||||
GetInstanceSave()->GetMapId(), GetInstanceSave()->GetInstanceId(),
|
||||
GetInstanceSave()->GetDifficulty(), GetInstanceSave()->GetPlayerCount(),
|
||||
GetInstanceSave()->GetGroupCount(), GetInstanceSave()->CanReset());
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Group *pGroup = player->GetGroup();
|
||||
if(pGroup)
|
||||
if (pGroup)
|
||||
{
|
||||
// solo saves should be reset when entering a group
|
||||
InstanceGroupBind *groupBind = pGroup->GetBoundInstance(this,GetDifficulty());
|
||||
if(playerBind)
|
||||
if (playerBind)
|
||||
{
|
||||
sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
|
||||
if(groupBind) sLog.outError("InstanceMap::Add: the group is bound to instance %d,%d,%d,%d,%d,%d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
|
||||
sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!",
|
||||
player->GetName(), player->GetGUIDLow(), GetInstanceSave()->GetMapId(), GetInstanceSave()->GetInstanceId(),
|
||||
GetInstanceSave()->GetDifficulty(), GetInstanceSave()->GetPlayerCount(), GetInstanceSave()->GetGroupCount(),
|
||||
GetInstanceSave()->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()),
|
||||
playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(),
|
||||
playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
|
||||
|
||||
if (groupBind)
|
||||
sLog.outError("InstanceMap::Add: the group is bound to instance %d,%d,%d,%d,%d,%d",
|
||||
groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(),
|
||||
groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
|
||||
ASSERT(false);
|
||||
}
|
||||
// bind to the group or keep using the group save
|
||||
if(!groupBind)
|
||||
pGroup->BindToInstance(mapSave, false);
|
||||
if (!groupBind)
|
||||
pGroup->BindToInstance(GetInstanceSave(), false);
|
||||
else
|
||||
{
|
||||
// cannot jump to a different instance without resetting it
|
||||
if(groupBind->save != mapSave)
|
||||
if (groupBind->save != GetInstanceSave())
|
||||
{
|
||||
sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d but he is in group %d which is bound to instance %d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), GUID_LOPART(pGroup->GetLeaderGUID()), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty());
|
||||
if(mapSave)
|
||||
sLog.outError("MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount());
|
||||
sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d but he is in group %d which is bound to instance %d,%d,%d!",
|
||||
player->GetName(), player->GetGUIDLow(), GetInstanceSave()->GetMapId(),
|
||||
GetInstanceSave()->GetInstanceId(), GetInstanceSave()->GetDifficulty(),
|
||||
GUID_LOPART(pGroup->GetLeaderGUID()), groupBind->save->GetMapId(),
|
||||
groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty());
|
||||
|
||||
if (GetInstanceSave())
|
||||
sLog.outError("MapSave players: %d, group count: %d",
|
||||
GetInstanceSave()->GetPlayerCount(), GetInstanceSave()->GetGroupCount());
|
||||
else
|
||||
sLog.outError("MapSave NULL");
|
||||
if(groupBind->save)
|
||||
|
||||
if (groupBind->save)
|
||||
sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount());
|
||||
else
|
||||
sLog.outError("GroupBind save NULL");
|
||||
|
|
@ -1842,12 +1867,12 @@ bool InstanceMap::Add(Player *player)
|
|||
}
|
||||
// if the group/leader is permanently bound to the instance
|
||||
// players also become permanently bound when they enter
|
||||
if(groupBind->perm)
|
||||
if (groupBind->perm)
|
||||
{
|
||||
WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4);
|
||||
data << uint32(0);
|
||||
player->GetSession()->SendPacket(&data);
|
||||
player->BindToInstance(mapSave, true);
|
||||
player->BindToInstance(GetInstanceSave(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1855,10 +1880,10 @@ bool InstanceMap::Add(Player *player)
|
|||
{
|
||||
// set up a solo bind or continue using it
|
||||
if(!playerBind)
|
||||
player->BindToInstance(mapSave, false);
|
||||
player->BindToInstance(GetInstanceSave(), false);
|
||||
else
|
||||
// cannot jump to a different instance without resetting it
|
||||
ASSERT(playerBind->save == mapSave);
|
||||
ASSERT(playerBind->save == GetInstanceSave());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1993,13 +2018,6 @@ void InstanceMap::PermBindAllPlayers(Player *player)
|
|||
if(!IsDungeon())
|
||||
return;
|
||||
|
||||
InstanceSave *save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
|
||||
if(!save)
|
||||
{
|
||||
sLog.outError("Cannot bind players, no instance save available for map!");
|
||||
return;
|
||||
}
|
||||
|
||||
Group *group = player->GetGroup();
|
||||
// group members outside the instance group don't get bound
|
||||
for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
|
||||
|
|
@ -2007,10 +2025,10 @@ void InstanceMap::PermBindAllPlayers(Player *player)
|
|||
Player* plr = itr->getSource();
|
||||
// players inside an instance cannot be bound to other instances
|
||||
// some players may already be permanently bound, in this case nothing happens
|
||||
InstancePlayerBind *bind = plr->GetBoundInstance(save->GetMapId(), save->GetDifficulty());
|
||||
InstancePlayerBind *bind = plr->GetBoundInstance(GetId(), GetDifficulty());
|
||||
if(!bind || !bind->perm)
|
||||
{
|
||||
plr->BindToInstance(save, true);
|
||||
plr->BindToInstance(GetInstanceSave(), true);
|
||||
WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4);
|
||||
data << uint32(0);
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
|
|
@ -2018,7 +2036,7 @@ void InstanceMap::PermBindAllPlayers(Player *player)
|
|||
|
||||
// if the leader is not in the instance the group will not get a perm bind
|
||||
if(group && group->GetLeaderGUID() == plr->GetGUID())
|
||||
group->BindToInstance(save, true);
|
||||
group->BindToInstance(GetInstanceSave(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2052,13 +2070,7 @@ void InstanceMap::SetResetSchedule(bool on)
|
|||
// the reset time is only scheduled when there are no payers inside
|
||||
// it is assumed that the reset time will rarely (if ever) change while the reset is scheduled
|
||||
if(IsDungeon() && !HavePlayers() && !IsRaidOrHeroicDungeon())
|
||||
{
|
||||
InstanceSave *save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
|
||||
if (!save)
|
||||
sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId());
|
||||
else
|
||||
sInstanceSaveMgr.GetScheduler().ScheduleReset(on, save->GetResetTime(), InstanceResetEvent(0, GetId(), Difficulty(GetSpawnMode()), GetInstanceId()));
|
||||
}
|
||||
sInstanceSaveMgr.GetScheduler().ScheduleReset(on, GetInstanceSave()->GetResetTime(), InstanceResetEvent(0, GetId(), Difficulty(GetSpawnMode()), GetInstanceId()));
|
||||
}
|
||||
|
||||
/* ******* Battleground Instance Maps ******* */
|
||||
|
|
|
|||
|
|
@ -210,6 +210,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
|
|||
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
|
||||
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
|
||||
|
||||
InstanceSave* GetInstanceSave() const { return m_instanceSave; }
|
||||
|
||||
void AddObjectToRemoveList(WorldObject *obj);
|
||||
|
||||
void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
|
||||
|
|
@ -312,6 +314,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
|
|||
uint32 i_InstanceId;
|
||||
uint32 m_unloadTimer;
|
||||
float m_VisibleDistance;
|
||||
InstanceSave* m_instanceSave; // can be NULL for non dungeons...
|
||||
|
||||
MapRefManager m_mapRefManager;
|
||||
MapRefManager::iterator m_mapRefIter;
|
||||
|
|
|
|||
|
|
@ -15213,12 +15213,14 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
|||
}
|
||||
}
|
||||
|
||||
// NOW player must have valid map
|
||||
// player bounded instance saves loaded in _LoadBoundInstances, group versions at group loading
|
||||
InstanceSave* instanceSave = GetBoundInstanceSaveForSelfOrGroup(GetMapId());
|
||||
|
||||
// load the player's map here if it's not already loaded
|
||||
SetMap(sMapMgr.CreateMap(GetMapId(), this));
|
||||
|
||||
// if the player is in an instance and it has been reset in the meantime teleport him to the entrance
|
||||
if(GetInstanceId() && !sInstanceSaveMgr.GetInstanceSave(GetInstanceId()))
|
||||
if(GetInstanceId() && !instanceSave)
|
||||
{
|
||||
AreaTrigger const* at = sObjectMgr.GetMapEntranceTrigger(GetMapId());
|
||||
if(at)
|
||||
|
|
|
|||
|
|
@ -841,8 +841,9 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
|
|||
// the reset time is set but not added to the scheduler
|
||||
// until the players leave the instance
|
||||
time_t resettime = cVictim->GetRespawnTimeEx() + 2 * HOUR;
|
||||
if(InstanceSave *save = sInstanceSaveMgr.GetInstanceSave(cVictim->GetInstanceId()))
|
||||
if(save->GetResetTime() < resettime) save->SetResetTime(resettime);
|
||||
if (InstanceSave *save = m->GetInstanceSave())
|
||||
if (save->GetResetTime() < resettime)
|
||||
save->SetResetTime(resettime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "10113"
|
||||
#define REVISION_NR "10114"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue