diff options
author | megamage <none@none> | 2009-05-16 14:52:41 -0500 |
---|---|---|
committer | megamage <none@none> | 2009-05-16 14:52:41 -0500 |
commit | e4456ae9f8347a32c39fdfc3fd6cef2279996cd0 (patch) | |
tree | 86eab427c03b95dfa30e863a8dc42840d4ccb396 /src | |
parent | 14edc1e5eb0712a486ed43518d9a140900072431 (diff) |
*Fix an exploit that instance can be reset when there are logged-out players in it.
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/game/CharacterHandler.cpp | 2 | ||||
-rw-r--r-- | src/game/MapInstanced.cpp | 120 | ||||
-rw-r--r-- | src/game/Player.cpp | 7 |
3 files changed, 45 insertions, 84 deletions
diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 29a54da5d06..1fa8665364e 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -63,7 +63,7 @@ bool LoginQueryHolder::Initialize() // NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure. // !!! NOTE: including unused `zone`,`online` - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,bgid,bgteam,bgmap,bgx,bgy,bgz,bgo FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,bgid,bgteam,bgmap,bgx,bgy,bgz,bgo,instance_id FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_mask,stackcount,amount0, amount1, amount2 ,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index 2494a07e20c..137c325ff88 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.cpp @@ -112,93 +112,51 @@ void MapInstanced::UnloadAll() */ Map* MapInstanced::GetInstance(const WorldObject* obj) { - uint32 CurInstanceId = obj->GetInstanceId(); - Map* map = NULL; - - if (obj->GetMapId() == GetId() && CurInstanceId != 0) + if(obj->GetTypeId() == TYPEID_UNIT) { - // the object wants to be put in a certain instance of this map - map = _FindMap(CurInstanceId); - if(!map) - { - // For players if the instanceId is set, it's assumed they are already in a map, - // hence the map must be loaded. For Creatures, GameObjects etc the map must exist - // prior to calling GetMap, they are not allowed to create maps for themselves. - sLog.outError("GetInstance: object %s(%d), typeId %d, in world %d, should be in map %d,%d but that's not loaded yet.", obj->GetName(), obj->GetGUIDLow(), obj->GetTypeId(), obj->IsInWorld(), obj->GetMapId(), obj->GetInstanceId()); - assert(false); - } - return(map); + assert(obj->GetMapId() == GetId() && obj->GetInstanceId()); + return _FindMap(obj->GetInstanceId()); } - else + + Player* player = (Player*)obj; + uint32 instanceId = player->GetInstanceId(); + + if(IsBattleGroundOrArena()) { - // instance not specified, find an existing or create a new one - if(obj->GetTypeId() != TYPEID_PLAYER) - { - sLog.outError("MAPINSTANCED: WorldObject '%u' (Entry: %u TypeID: %u) is in map %d,%d and requested base map instance of map %d, this must not happen", obj->GetGUIDLow(), obj->GetEntry(), obj->GetTypeId(), obj->GetMapId(), obj->GetInstanceId(), GetId()); - assert(false); + if(!instanceId) + instanceId = player->GetBattleGroundId(); + + if(instanceId) + return _FindMap(instanceId); + else return NULL; - } + } + + if(instanceId) + if(Map *map = _FindMap(instanceId)) + return map; + + InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty()); + InstanceSave *pSave = pBind ? pBind->save : NULL; + if(!pBind || !pBind->perm) + { + if(Group *group = player->GetGroup()) + if(InstanceGroupBind *groupBind = group->GetBoundInstance(GetId(), player->GetDifficulty())) + pSave = groupBind->save; + } + + if(instanceId && pSave && instanceId != pSave->GetInstanceId()) + return NULL; + + if(!player->GetSession()->PlayerLoading()) // enter a new map + { + if(pSave) + return CreateInstance(pSave->GetInstanceId(), pSave, pSave->GetDifficulty()); else - { - uint32 NewInstanceId = 0; // instanceId of the resulting map - Player* player = (Player*)obj; - - if(IsBattleGroundOrArena()) - { - // instantiate or find existing bg map for player - // the instance id is set in battlegroundid - NewInstanceId = player->GetBattleGroundId(); - if(!NewInstanceId) - { - if(player->GetSession()->PlayerLoading()) - return NULL; - else - assert(NewInstanceId); - } - map = _FindMap(NewInstanceId); - if(!map) - map = CreateBattleGround(NewInstanceId); - return map; - } - - InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty()); - InstanceSave *pSave = pBind ? pBind->save : NULL; - - // the player's permanet player bind is taken into consideration first - // then the player's group bind and finally the solo bind. - if(!pBind || !pBind->perm) - { - InstanceGroupBind *groupBind = NULL; - Group *group = player->GetGroup(); - // use the player's difficulty setting (it may not be the same as the group's) - if(group && (groupBind = group->GetBoundInstance(GetId(), player->GetDifficulty()))) - pSave = groupBind->save; - } - - if(pSave) - { - // solo/perm/group - NewInstanceId = pSave->GetInstanceId(); - map = _FindMap(NewInstanceId); - // it is possible that the save exists but the map doesn't - if(!map) - map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty()); - return map; - } - else if(!player->GetSession()->PlayerLoading()) - { - // if no instanceId via group members or instance saves is found - // the instance will be created for the first time - NewInstanceId = MapManager::Instance().GenerateInstanceId(); - return CreateInstance(NewInstanceId, NULL, player->GetDifficulty()); - } - else - { - sLog.outError("MAPINSTANCED: Player %s is trying to create instance (MapId %u) when login.", player->GetName(), player->GetMapId()); - return NULL; - } - } + return CreateInstance(MapManager::Instance().GenerateInstanceId(), NULL, player->GetDifficulty()); } + + return NULL; } InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 349a1947c79..74a2558e699 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -14262,6 +14262,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) uint32 transGUID = fields[24].GetUInt32(); Relocate(fields[6].GetFloat(),fields[7].GetFloat(),fields[8].GetFloat(),fields[10].GetFloat()); SetMapId(fields[9].GetUInt32()); + SetInstanceId(fields[41].GetFloat()); SetDifficulty(fields[32].GetUInt32()); // may be changed in _LoadGroup _LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP)); @@ -14473,7 +14474,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) // since the player may not be bound to the map yet, make sure subsequent // getmap calls won't create new maps - SetInstanceId(map->GetInstanceId()); + //SetInstanceId(map->GetInstanceId()); // if the player is in an instance and it has been reset in the meantime teleport him to the entrance if(GetInstanceId() && !sInstanceSaveManager.GetInstanceSave(GetInstanceId())) @@ -15782,7 +15783,7 @@ void Player::SaveToDB() std::ostringstream ss; ss << "INSERT INTO characters (guid,account,name,race,class," - "map, dungeon_difficulty, position_x, position_y, position_z, orientation, data, " + "map, instance_id, dungeon_difficulty, position_x, position_y, position_z, orientation, data, " "taximask, online, cinematic, " "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " "trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, " @@ -15796,6 +15797,7 @@ void Player::SaveToDB() if(!IsBeingTeleported()) { ss << GetMapId() << ", " + << (uint32)GetInstanceId() << ", " << (uint32)GetDifficulty() << ", " << finiteAlways(GetPositionX()) << ", " << finiteAlways(GetPositionY()) << ", " @@ -15805,6 +15807,7 @@ void Player::SaveToDB() else { ss << GetTeleportDest().mapid << ", " + << (uint32)0 << ", " << (uint32)GetDifficulty() << ", " << finiteAlways(GetTeleportDest().x) << ", " << finiteAlways(GetTeleportDest().y) << ", " |