[7487] Avoid attempt use InstanceSave data for non-dungeons.

Also check map existance and correctness at instance data loading.
Removed unused and totally bugged InstanceMap::GetResetTime.
This commit is contained in:
VladimirMangos 2009-03-18 15:57:13 +03:00
parent b3490d3b74
commit a7fd57cc74
6 changed files with 85 additions and 70 deletions

View file

@ -511,7 +511,7 @@ bool ChatHandler::HandleGonameCommand(const char* args)
// remember current position as entry point for return at bg end teleportation // remember current position as entry point for return at bg end teleportation
_player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());
} }
else if(cMap->IsDungeon() && cMap->Instanceable()) else if(cMap->IsDungeon())
{ {
// we have to go to instance, and can go to player only if: // we have to go to instance, and can go to player only if:
// 1) we are in his group (either as leader or as member) // 1) we are in his group (either as leader or as member)

View file

@ -2137,76 +2137,80 @@ bool InstanceMap::Add(Player *player)
if(!CanEnter(player)) if(!CanEnter(player))
return false; return false;
// get or create an instance save for the map // Dungeon only code
InstanceSave *mapSave = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); if(IsDungeon())
if(!mapSave)
{ {
sLog.outDetail("InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId()); // get or create an instance save for the map
mapSave = sInstanceSaveManager.AddInstanceSave(GetId(), GetInstanceId(), GetSpawnMode(), 0, true); InstanceSave *mapSave = sInstanceSaveManager.GetInstanceSave(GetInstanceId());
} if(!mapSave)
// check for existing instance binds
InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), GetSpawnMode());
if(playerBind && playerBind->perm)
{
// cannot enter other instances if bound permanently
if(playerBind->save != mapSave)
{ {
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.outDetail("InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId());
assert(false); mapSave = sInstanceSaveManager.AddInstanceSave(GetId(), GetInstanceId(), GetSpawnMode(), 0, true);
} }
}
else // check for existing instance binds
{ InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), GetSpawnMode());
Group *pGroup = player->GetGroup(); if(playerBind && playerBind->perm)
if(pGroup)
{ {
// solo saves should be reset when entering a group // cannot enter other instances if bound permanently
InstanceGroupBind *groupBind = pGroup->GetBoundInstance(GetId(), GetSpawnMode()); if(playerBind->save != mapSave)
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()); 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());
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); assert(false);
} }
// bind to the group or keep using the group save
if(!groupBind)
pGroup->BindToInstance(mapSave, false);
else
{
// cannot jump to a different instance without resetting it
if(groupBind->save != mapSave)
{
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());
else
sLog.outError("MapSave NULL");
if(groupBind->save)
sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount());
else
sLog.outError("GroupBind save NULL");
assert(false);
}
// if the group/leader is permanently bound to the instance
// players also become permanently bound when they enter
if(groupBind->perm)
{
WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4);
data << uint32(0);
player->GetSession()->SendPacket(&data);
player->BindToInstance(mapSave, true);
}
}
} }
else else
{ {
// set up a solo bind or continue using it Group *pGroup = player->GetGroup();
if(!playerBind) if(pGroup)
player->BindToInstance(mapSave, false); {
// solo saves should be reset when entering a group
InstanceGroupBind *groupBind = pGroup->GetBoundInstance(GetId(), GetSpawnMode());
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());
assert(false);
}
// bind to the group or keep using the group save
if(!groupBind)
pGroup->BindToInstance(mapSave, false);
else
{
// cannot jump to a different instance without resetting it
if(groupBind->save != mapSave)
{
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());
else
sLog.outError("MapSave NULL");
if(groupBind->save)
sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount());
else
sLog.outError("GroupBind save NULL");
assert(false);
}
// if the group/leader is permanently bound to the instance
// players also become permanently bound when they enter
if(groupBind->perm)
{
WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4);
data << uint32(0);
player->GetSession()->SendPacket(&data);
player->BindToInstance(mapSave, true);
}
}
}
else else
// cannot jump to a different instance without resetting it {
assert(playerBind->save == mapSave); // set up a solo bind or continue using it
if(!playerBind)
player->BindToInstance(mapSave, false);
else
// cannot jump to a different instance without resetting it
assert(playerBind->save == mapSave);
}
} }
} }
@ -2327,6 +2331,9 @@ bool InstanceMap::Reset(uint8 method)
void InstanceMap::PermBindAllPlayers(Player *player) void InstanceMap::PermBindAllPlayers(Player *player)
{ {
if(!IsDungeon())
return;
InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId());
if(!save) if(!save)
{ {
@ -2356,12 +2363,6 @@ void InstanceMap::PermBindAllPlayers(Player *player)
} }
} }
time_t InstanceMap::GetResetTime()
{
InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId());
return save ? save->GetDifficulty() : DIFFICULTY_NORMAL;
}
void InstanceMap::UnloadAll(bool pForce) void InstanceMap::UnloadAll(bool pForce)
{ {
if(HavePlayers()) if(HavePlayers())
@ -2391,7 +2392,7 @@ void InstanceMap::SetResetSchedule(bool on)
// only for normal instances // only for normal instances
// the reset time is only scheduled when there are no payers inside // 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 // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled
if(!HavePlayers() && !IsRaid() && !IsHeroic()) if(IsDungeon() && !HavePlayers() && !IsRaid() && !IsHeroic())
{ {
InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); InstanceSave *save = sInstanceSaveManager.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()); if(!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId());

View file

@ -530,7 +530,6 @@ class MANGOS_DLL_SPEC InstanceMap : public Map
uint32 GetScriptId() { return i_script_id; } uint32 GetScriptId() { return i_script_id; }
InstanceData* GetInstanceData() { return i_data; } InstanceData* GetInstanceData() { return i_data; }
void PermBindAllPlayers(Player *player); void PermBindAllPlayers(Player *player);
time_t GetResetTime();
void UnloadAll(bool pForce); void UnloadAll(bool pForce);
bool CanEnter(Player* player); bool CanEnter(Player* player);
void SendResetWarnings(uint32 timeLeft) const; void SendResetWarnings(uint32 timeLeft) const;

View file

@ -2709,7 +2709,14 @@ void ObjectMgr::LoadGroups()
} }
} }
InstanceSave *save = sInstanceSaveManager.AddInstanceSave(fields[1].GetUInt32(), fields[2].GetUInt32(), fields[4].GetUInt8(), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true); MapEntry const* mapEntry = sMapStore.LookupEntry(fields[1].GetUInt32());
if(!mapEntry || !mapEntry->IsDungeon())
{
sLog.outErrorDb("Incorrect entry in group_instance table : no dungeon map %d", fields[1].GetUInt32());
continue;
}
InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), fields[4].GetUInt8(), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true);
group->BindToInstance(save, fields[3].GetBool(), true); group->BindToInstance(save, fields[3].GetBool(), true);
}while( result->NextRow() ); }while( result->NextRow() );
delete result; delete result;

View file

@ -15469,6 +15469,14 @@ void Player::_LoadBoundInstances(QueryResult *result)
// so the value read from the DB may be wrong here but only if the InstanceSave is loaded // so the value read from the DB may be wrong here but only if the InstanceSave is loaded
// and in that case it is not used // and in that case it is not used
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
if(!mapEntry || !mapEntry->IsDungeon())
{
sLog.outError("_LoadBoundInstances: player %s(%d) has bind to not existed or not dungeon map %d", GetName(), GetGUIDLow(), mapId);
CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%d' AND instance = '%d'", GetGUIDLow(), instanceId);
continue;
}
if(!perm && group) if(!perm && group)
{ {
sLog.outError("_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d,%d,%d", GetName(), GetGUIDLow(), GUID_LOPART(group->GetLeaderGUID()), mapId, instanceId, difficulty); sLog.outError("_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d,%d,%d", GetName(), GetGUIDLow(), GUID_LOPART(group->GetLeaderGUID()), mapId, instanceId, difficulty);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7486" #define REVISION_NR "7487"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__