Instance * InstanceMgr::GetSavedInstance(uint32 map_id, uint32 guid) { InstanceMap::iterator itr; InstanceMap * instancemap; m_mapLock.Acquire(); instancemap = m_instances[map_id]; if(instancemap) { for(itr = instancemap->begin(); itr != instancemap->end();) { if(itr != instancemap->end()) { if( itr->second->m_SavedPlayers.find(guid) != itr->second->m_SavedPlayers.end() ) { m_mapLock.Release(); return itr->second; } ++itr; } } } // instance is non-existant (shouldn't really happen for units...) m_mapLock.Release(); return 0; }
Instance * InstanceMgr::GetSavedInstance(uint32 map_id, uint32 guid, uint32 difficulty) { InstanceMap::iterator itr; InstanceMap * instancemap; m_mapLock.Acquire(); instancemap = m_instances[map_id]; if(instancemap) { for(itr = instancemap->begin(); itr != instancemap->end();) { if(itr != instancemap->end()) { itr->second->m_SavedLock.Acquire(); if(itr->second->m_difficulty == difficulty) { if( itr->second->m_SavedPlayers.find(guid) != itr->second->m_SavedPlayers.end() ) { itr->second->m_SavedLock.Release(); m_mapLock.Release(); return itr->second; } } itr->second->m_SavedLock.Release(); ++itr; } } } m_mapLock.Release(); return NULL; }
MapMgr* InstanceMgr::GetInstance(uint32 MapId, uint32 InstanceId) { Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; MapInfo * inf = WorldMapInfoStorage.LookupEntry(MapId); // we can *never* teleport to maps without a mapinfo. if( inf == NULL || MapId >= NUM_MAPS ) return NULLMAPMGR; // single-instance maps never go into the instance set. if( inf->type == INSTANCE_NULL ) return m_singleMaps[MapId]; m_mapLock.Acquire(); instancemap = m_instances[MapId]; if(instancemap != NULL) { // check our saved instance id. see if its valid, and if we can join before trying to find one. itr = instancemap->find(InstanceId); if(itr != instancemap->end()) { if(itr->second->m_mapMgr) { m_mapLock.Release(); return itr->second->m_mapMgr; } } // iterate over our instances, and see if any of them are owned/joinable by him. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; // this is our instance. if(in->m_mapMgr == NULL) { // create the actual instance. in->m_mapMgr = _CreateInstance(in); m_mapLock.Release(); return in->m_mapMgr; } else { // instance is already created. m_mapLock.Release(); return in->m_mapMgr; } } } // if we're here, it means there are no instances on that map, or none of the instances on that map are joinable // by this player. m_mapLock.Release(); return NULLMAPMGR; }
void InstanceMgr::OnGroupDestruction(Group * pGroup) { // this means a group has been deleted, so lets clear out all instances that they owned. // (instances don't transfer to the group leader, or anything) Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; ++i) { instancemap = m_instances[i]; if(instancemap) { for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(in->m_creatorGroup && in->m_creatorGroup == pGroup->GetID()) _DeleteInstance(in, false); } } } m_mapLock.Release(); }
void InstanceMgr::CheckForExpiredInstances() { // checking for any expired instances. Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; i++) { instancemap = m_instances[i]; if(instancemap) { for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; // use a "soft" delete here. if(HasInstanceExpired(in)) _DeleteInstance(in, false); } } } m_mapLock.Release(); }
void InstanceMgr::ResetHeroicInstances() { // checking for any expired instances. Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; i++) { instancemap = m_instances[i]; if(instancemap) { for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(!in->m_dbcMap->israid()) { // use a "soft" delete here. if(in->m_difficulty == MODE_5PLAYER_HEROIC) _DeleteInstance(in, false); } } } } m_mapLock.Release(); }
void InstanceMgr::CheckForExpiredInstances() { // checking for any expired instances. Instance* in; InstanceMap::iterator itr; InstanceMap* instancemap; uint32 i; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; ++i) { instancemap = m_instances[i]; if(instancemap) { for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; // use a "soft" delete here. if(in->m_mapInfo->type != INSTANCE_NONRAID && !(in->m_mapInfo->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL) && HasInstanceExpired(in)) _DeleteInstance(in, false); } } } m_mapLock.Release(); }
void InstanceMgr::BuildXMLStats(char* m_file) { uint32 i; InstanceMap::iterator itr; InstanceMap* instancemap; Instance* in; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; ++i) { if(m_singleMaps[i] != NULL) BuildStats(m_singleMaps[i], m_file, NULL, m_singleMaps[i]->GetMapInfo()); else { instancemap = m_instances[i]; if(instancemap != NULL) { for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(in->m_mapMgr == NULL) continue; BuildStats(in->m_mapMgr, m_file, in, in->m_mapInfo); } } } } m_mapLock.Release(); }
void InstanceMgr::ResetSavedInstances(Player* plr) { WorldPacket data(SMSG_INSTANCE_RESET, 4); Instance * in; InstanceMap::iterator itr; InstanceMap* instancemap; MapEntry* map; uint32 i; if(plr == NULL || !plr->IsInWorld() || plr->GetMapMgr()->GetMapInfo()->type != INSTANCE_NULL) return; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; i++) { if(m_instances[i] != NULL) { instancemap = m_instances[i]; map = dbcMap.LookupEntry(i); for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if((!map->israid()) && in->m_mapInfo->type == INSTANCE_MULTIMODE && plr->GetGroupID() == in->m_creatorGroup) { if( in->m_difficulty == MODE_5PLAYER_HEROIC && in->m_SavedPlayers.size() )//heroic instances can't be reset once they are saved. { plr->GetSession()->SystemMessage("Heroic instances are reset daily at 08:00 CET!"); continue; } if(plr->GetGroup() != NULL && plr->GetGroup()->GetLeader() != plr->m_playerInfo) { plr->GetSession()->SystemMessage("Can't reset instance %u (%s), you are not the group leader!", in->m_instanceId, in->m_mapMgr->GetMapInfo()->name); continue; } if(in->m_mapMgr && in->m_mapMgr->HasPlayers()) { plr->GetSession()->SystemMessage("Can't reset instance %u (%s) when there are still players inside!", in->m_instanceId, in->m_mapMgr->GetMapInfo()->name); continue; } // destroy the instance bool destroyed = _DeleteInstance(in, true); if(destroyed) { // <mapid> has been reset. data << uint32(in->m_mapId); plr->GetSession()->SendPacket(&data); } } } } } m_mapLock.Release(); }
void InstanceMgr::PlayerLeftGroup(Group * pGroup, Player* pPlayer) { // does this group own any instances? we have to kick the player out of those instances. Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; WorldPacket data(SMSG_RAID_GROUP_ONLY, 8); uint32 i; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; i++) { instancemap = m_instances[i]; if(instancemap) { for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; bool eject = false; if(pPlayer->GetGUID() == in->m_creatorGuid) eject = true; else if(pPlayer->GetGroupID() == in->m_creatorGroup) eject = true; else { // Are we on the saved list? in->m_SavedLock.Acquire(); if( in->m_SavedPlayers.find(pPlayer->GetLowGUID()) != in->m_SavedPlayers.end() ) eject = true; in->m_SavedLock.Release(); } if(eject) { // better make sure we're actually in that instance.. :P if(!pPlayer->raidgrouponlysent && pPlayer->GetInstanceID() == (int32)in->m_instanceId) { data << uint32(60000) << uint32(1); pPlayer->GetSession()->SendPacket(&data); pPlayer->raidgrouponlysent=true; sEventMgr.AddEvent(pPlayer, &Player::EjectFromInstance, EVENT_PLAYER_EJECT_FROM_INSTANCE, 60000, 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT); m_mapLock.Release(); return; } } } } } m_mapLock.Release(); }
void InstanceMgr::BuildRaidSavedInstancesForPlayer(Player* plr) { #if VERSION_STRING != Cata WorldPacket data(SMSG_RAID_INSTANCE_INFO, 200); #else WorldPacket data(SMSG_RAID_INSTANCE_INFO, 4); #endif Instance* in; InstanceMap::iterator itr; InstanceMap* instancemap; uint32 i; uint32 counter = 0; data << counter; m_mapLock.Acquire(); for (i = 0; i < NUM_MAPS; ++i) { if (m_instances[i] != NULL) { instancemap = m_instances[i]; for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (in->m_persistent && PlayerOwnsInstance(in, plr)) { data << uint32(in->m_mapId); // obviously the mapid data << uint32(in->m_difficulty); // instance difficulty data << uint64(in->m_instanceId); // self-explanatory data << uint8(1); // expired = 0 data << uint8(0); // extended = 1 if (in->m_expiration > UNIXTIME) data << uint32(in->m_expiration - UNIXTIME); else data << uint32(0); #if VERSION_STRING == Cata data << uint32(0); #endif ++counter; } } } } m_mapLock.Release(); *(uint32*)&data.contents()[0] = counter; plr->GetSession()->SendPacket(&data); }
void InstanceMgr::OnGroupDestruction(Group* pGroup) { // this means a group has been deleted, so lets clear out all instances that they owned. // (instances don't transfer to the group leader, or anything) Instance* in; InstanceMap::iterator itr; InstanceMap* instancemap; uint32 i; m_mapLock.Acquire(); for (i = 0; i < NUM_MAPS; ++i) { instancemap = m_instances[i]; if (instancemap) { for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (in->m_mapMgr && in->m_creatorGroup && in->m_creatorGroup == pGroup->GetID()) { if (IS_RESETABLE_INSTANCE(in)) { _DeleteInstance(in, false); } else if (in->m_mapMgr->HasPlayers()) { WorldPacket data(SMSG_RAID_GROUP_ONLY, 8); data << uint32(60000); data << uint32(1); for (PlayerStorageMap::iterator mitr = in->m_mapMgr->m_PlayerStorage.begin(); mitr != in->m_mapMgr->m_PlayerStorage.end(); ++mitr) { if ((*mitr).second->IsInWorld() && !(*mitr).second->raidgrouponlysent && (*mitr).second->GetInstanceID() == (int32)in->m_instanceId) { (*mitr).second->GetSession()->SendPacket(&data); (*mitr).second->raidgrouponlysent = true; sEventMgr.AddEvent((*mitr).second, &Player::EjectFromInstance, EVENT_PLAYER_EJECT_FROM_INSTANCE, 60000, 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT); } } } } } } } m_mapLock.Release(); }
void InstanceMgr::ResetSavedInstances(PlayerPointer plr) { WorldPacket data(SMSG_INSTANCE_RESET, 4); Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; if(!plr->IsInWorld() || plr->GetMapMgr()->GetMapInfo()->type != INSTANCE_NULL) return; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; ++i) { if(m_instances[i] != NULL) { instancemap = m_instances[i]; for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if ( in->m_mapInfo->type == INSTANCE_NONRAID && ( plr->GetLowGUID() == in->m_creatorGuid || ( plr->GetGroup() && plr->GetGroup()->GetID() == in->m_creatorGroup ))) { if(in->m_mapMgr && in->m_mapMgr->HasPlayers()) { plr->GetSession()->SystemMessage("Can't reset instance %u (%s) when there are still players inside!", in->m_instanceId, in->m_mapMgr->GetMapInfo()->name); continue; } // <mapid> has been reset. data << uint32(in->m_mapId); plr->GetSession()->SendPacket(&data); // reset groupinstanceid if(plr->GetGroup()) plr->GetGroup()->SetGroupInstanceID(0); // destroy the instance _DeleteInstance(in, true); } } } } m_mapLock.Release(); }
void InstanceMgr::BuildSavedInstancesForPlayer(Player* plr) { #if VERSION_STRING != Cata WorldPacket data(4); Instance* in; InstanceMap::iterator itr; InstanceMap* instancemap; uint32 i; if (!plr->IsInWorld() || plr->GetMapMgr()->GetMapInfo()->type != INSTANCE_NULL) { m_mapLock.Acquire(); for (i = 0; i < NUM_MAPS; ++i) { if (m_instances[i] != NULL) { instancemap = m_instances[i]; for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (PlayerOwnsInstance(in, plr) && in->m_mapInfo->type == INSTANCE_NONRAID) { m_mapLock.Release(); data.SetOpcode(SMSG_UPDATE_LAST_INSTANCE); data << uint32(in->m_mapId); plr->GetSession()->SendPacket(&data); data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP); data << uint32(0x01); plr->GetSession()->SendPacket(&data); return; } } } } m_mapLock.Release(); } data.SetOpcode(SMSG_UPDATE_INSTANCE_OWNERSHIP); data << uint32(0x00); plr->GetSession()->SendPacket(&data); #endif }
bool InstanceMgr::_DeleteInstance(Instance * in, bool ForcePlayersOut) { m_mapLock.Acquire(); InstanceMap * instancemap; InstanceMap::iterator itr; if(in->m_mapMgr) { // "ForcePlayersOut" will teleport the players in this instance to their entry point/hearthstone. // otherwise, they will get a 60 second timeout telling them they are not in this instance's group. if(in->m_mapMgr->HasPlayers()) { if(ForcePlayersOut) in->m_mapMgr->InstanceShutdown(); else { in->m_mapMgr->BeginInstanceExpireCountdown(); in->m_mapMgr->pInstance = NULL; } } else in->m_mapMgr->InstanceShutdown(); } // remove the instance from the large map. instancemap = m_instances[in->m_mapId]; if(instancemap) { itr = instancemap->find(in->m_instanceId); if(itr != instancemap->end()) instancemap->erase(itr); } // cleanup corpses, database references in->DeleteFromDB(); // delete the instance pointer. delete in; m_mapLock.Release(); return true; }
void InstanceMgr::BuildSavedInstancesForPlayer(Player* plr) { WorldPacket data(4); Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; if(!plr->IsInWorld() || plr->GetMapMgr()->GetMapInfo()->type != INSTANCE_NULL) { m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; i++) { if(m_instances[i] != NULL) { instancemap = m_instances[i]; for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if( !in->m_dbcMap->israid() && (PlayerOwnsInstance(in, plr) >= OWNER_CHECK_OK) ) { m_mapLock.Release(); data.SetOpcode(SMSG_UPDATE_LAST_INSTANCE); data << uint32(in->m_mapId); plr->GetSession()->SendPacket(&data); data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP); data << uint32(0x01); plr->GetSession()->SendPacket(&data); break; //next mapid } } } } m_mapLock.Release(); } data.SetOpcode(SMSG_UPDATE_INSTANCE_OWNERSHIP); data << uint32(0x00); plr->GetSession()->SendPacket(&data); }
void InstanceMgr::ResetSavedInstances(Player* plr) { WorldPacket data(SMSG_INSTANCE_RESET, 4); Instance* in; InstanceMap::iterator itr; InstanceMap* instancemap; uint32 i; if(!plr->IsInWorld() || plr->GetMapMgr()->GetMapInfo()->type != INSTANCE_NULL) return; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; ++i) { if(m_instances[i] != NULL) { instancemap = m_instances[i]; for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(IS_RESETABLE_INSTANCE(in) && (CHECK_INSTANCE_GROUP(in, plr->GetGroup()) || plr->GetLowGUID() == in->m_creatorGuid)) { if(in->m_mapMgr && in->m_mapMgr->HasPlayers()) { plr->GetSession()->SystemMessage("Failed to reset instance %u (%s), due to players still inside.", in->m_instanceId, in->m_mapMgr->GetMapInfo()->name); continue; } // <mapid> has been reset. data << uint32(in->m_mapId); plr->GetSession()->SendPacket(&data); // destroy the instance _DeleteInstance(in, true); } } } } m_mapLock.Release(); }
void InstanceMgr::BuildRaidSavedInstancesForPlayer(Player * plr) { WorldPacket data(SMSG_RAID_INSTANCE_INFO, 200); Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; uint32 counter = 0; data << counter; m_mapLock.Acquire(); for (i = 0; i < NUM_MAPS; ++i) { if (m_instances[i] != NULL) { instancemap = m_instances[i]; for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (in->m_persistent && PlayerOwnsInstance(in, plr)) { data << in->m_mapId; data << uint32(in->m_expiration - UNIXTIME); data << in->m_instanceId; data << ++counter; } } } } m_mapLock.Release(); #ifdef USING_BIG_ENDIAN *(uint32*)&data.contents()[0] = swap32(counter); #else *(uint32*)&data.contents()[0] = counter; #endif plr->GetSession()->SendPacket(&data); }
void InstanceMgr::BuildXMLStats(char * m_file) { uint32 i; InstanceMap::iterator itr; InstanceMap * instancemap; Instance * in; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; i++) { if(m_singleMaps[i] != NULL) BuildStats(m_singleMaps[i], m_file, NULL, m_singleMaps[i]->GetMapInfo()); } // Crow: WE CAN MAKE THIS BETTER, FASTER, STRONGER!!! for(i = 0; i < NUM_MAPS; i++) { if(m_singleMaps[i] == NULL) { instancemap = m_instances[i]; if(instancemap != NULL) { for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(in->m_mapMgr == NULL) continue; BuildStats(in->m_mapMgr, m_file, in, in->m_mapInfo); } } } } m_mapLock.Release(); Log.Debug("InstanceMgr", "Dumping XML stats..."); }
void InstanceMgr::BuildRaidSavedInstancesForPlayer(PlayerPointer plr) { WorldPacket data(SMSG_RAID_INSTANCE_INFO, 200); Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; uint32 counter = 0; data << counter; m_mapLock.Acquire(); for(i = 0; i < NUM_MAPS; ++i) { if(m_instances[i] != NULL) { instancemap = m_instances[i]; for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; uint8 poinst = PlayerOwnsInstance(in, plr); if( poinst >= OWNER_CHECK_OK ) { data << in->m_mapId; data << uint32(in->m_expiration - UNIXTIME); data << in->m_instanceId; data << in->m_difficulty; ++counter; } } } } m_mapLock.Release(); *(uint32*)&data.contents()[0] = counter; plr->GetSession()->SendPacket(&data); }
MapMgr* InstanceMgr::GetInstance(Object* obj) { Player* plr = NULL; InstanceMap::iterator itr; InstanceMap * instancemap = NULL; MapInfo * inf = NULL; inf = WorldMapInfoStorage.LookupEntry(obj->GetMapId()); // we can *never* teleport to maps without a mapinfo. if( inf == NULL || obj->GetMapId() >= NUM_MAPS ) return NULLMAPMGR; if( obj->IsPlayer() ) { // players can join instances based on their groups/solo status. plr = TO_PLAYER( obj ); // single-instance maps never go into the instance set. if( inf->type == INSTANCE_NULL ) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap != NULL) { // check our saved instance id. see if its valid, and if we can join before trying to find one. itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { if(itr->second) { //we have an instance,but can we enter it? uint8 owns = PlayerOwnsInstance( itr->second, plr ); if( owns >= OWNER_CHECK_OK ) { //wakeup call for saved instances if(itr->second->m_mapMgr == NULL) itr->second->m_mapMgr = _CreateInstance(itr->second); if(owns == OWNER_CHECK_SAVED_OK && !itr->second->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) itr->second->m_creatorGroup = plr->GetGroupID(); } m_mapLock.Release(); return itr->second->m_mapMgr; } } } // iterate over our instances, and see if any of them are owned/joinable by him. for(itr = instancemap->begin(); itr != instancemap->end(); itr++) { // Is this our instance? uint8 owns = PlayerOwnsInstance(itr->second, plr); if(owns >= OWNER_CHECK_OK ) { //wakeup call for saved instances if(itr->second->m_mapMgr == NULL) itr->second->m_mapMgr = _CreateInstance(itr->second); if(owns == OWNER_CHECK_SAVED_OK && !itr->second->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) itr->second->m_creatorGroup = plr->GetGroupID(); } m_mapLock.Release(); return itr->second->m_mapMgr; } else DEBUG_LOG("InstanceMgr","Check failed %s", plr->GetName()); } } // if we're here, it means there are no instances on that map, or none of the instances on that map are joinable // by this player. m_mapLock.Release(); return NULLMAPMGR; } else { // units are *always* limited to their set instance ids. if(inf->type == INSTANCE_NULL) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap != NULL) { itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { // we never create instances just for units. m_mapLock.Release(); return itr->second->m_mapMgr; } } // instance is non-existant (shouldn't really happen for units...) m_mapLock.Release(); return NULLMAPMGR; } }
void InstanceMgr::ResetSavedInstances(Player * plr) { WorldPacket *pData; Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; if (!plr->IsInWorld() || plr->GetMapMgr()->GetMapInfo()->type != INSTANCE_NULL) return; m_mapLock.Acquire(); Group *group = plr->GetGroup(); for (i = 0; i < NUM_MAPS; ++i) { if (m_instances[i] != NULL) { instancemap = m_instances[i]; for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (IS_RESETABLE_INSTANCE(in) && ((group && group->GetID() == in->m_creatorGroup) || plr->GetLowGUID() == in->m_creatorGuid)) { if (in->m_mapMgr && in->m_mapMgr->HasPlayers()) { pData = new WorldPacket(SMSG_INSTANCE_RESET_FAILED, 8); *pData << uint32(INSTANCE_RESET_ERROR_PLAYERS_INSIDE); *pData << uint32(in->m_mapId); plr->GetSession()->SendPacket(pData); delete pData; continue; } if (group) { group->m_instanceIds[in->m_mapId][in->m_difficulty] = 0; } // <mapid> has been reset. pData = new WorldPacket(SMSG_INSTANCE_RESET, 4); *pData << uint32(in->m_mapId); plr->GetSession()->SendPacket(pData); delete pData; // destroy the instance _DeleteInstance(in, true); } } } } m_mapLock.Release(); /* plr->m_playerInfo->savedInstanceIdsLock.Acquire(); for(int difficulty=0; difficulty<NUM_INSTANCE_MODES; difficulty++) { PlayerInstanceMap::iterator itr,itr2=plr->m_playerInfo->savedInstanceIds[difficulty].begin(); for(; itr2 != plr->m_playerInfo->savedInstanceIds[difficulty].end();) { itr = itr2; itr2++; in = sInstanceMgr.GetInstanceByIds((*itr).first, (*itr).second); if( !in ) continue; if(((group && group->GetID() == in->m_creatorGroup) || plr->GetLowGUID() == in->m_creatorGuid)) { if(in->m_mapMgr && in->m_mapMgr->HasPlayers()) { pData = new WorldPacket(SMSG_RESET_INSTANCE_FAILED, 8); *pData << uint32(INSTANCE_RESET_ERROR_PLAYERS_INSIDE); *pData << uint32(in->m_mapId); plr->GetSession()->SendPacket(pData); delete pData; continue; } if(group) { group->m_instanceIds[in->m_mapId][in->m_difficulty] = 0; } // <mapid> has been reset. pData = new WorldPacket(SMSG_RESET_INSTANCE, 4); *pData << uint32(in->m_mapId); plr->GetSession()->SendPacket(pData); delete pData; //remove instance from player plr->SetPersistentInstanceId(in->m_mapId, difficulty, 0); // destroy the instance _DeleteInstance(in, true); } } } plr->m_playerInfo->savedInstanceIdsLock.Release();*/ }
MapMgr* InstanceMgr::GetInstance(Object* obj) { Player* plr; Instance* in; InstanceMap::iterator itr; InstanceMap* instancemap; MapInfo* inf = WorldMapInfoStorage.LookupEntry(obj->GetMapId()); // we can *never* teleport to maps without a mapinfo. if(inf == NULL || obj->GetMapId() >= NUM_MAPS) return NULL; if(obj->IsPlayer()) { // players can join instances based on their groups/solo status. plr = TO< Player* >(obj); // single-instance maps never go into the instance set. if(inf->type == INSTANCE_NULL) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap != NULL) { // check our saved instance id. see if its valid, and if we can join before trying to find one. itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { if(itr->second->m_mapMgr == NULL) { itr->second->m_mapMgr = _CreateInstance(itr->second); } if(itr->second->m_mapMgr) { m_mapLock.Release(); return itr->second->m_mapMgr; } } // iterate over our instances, and see if any of them are owned/joinable by him. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; uint32 difficulty; if(in->m_mapInfo->type == INSTANCE_RAID) difficulty = plr->GetRaidDifficulty(); else difficulty = plr->GetDungeonDifficulty(); if(in->m_difficulty == difficulty && PlayerOwnsInstance(in, plr)) { // this is our instance. if(in->m_mapMgr == NULL) { /*if(plr->m_TeleportState == 1) { // the player is loading. boot him out to the entry point, we don't want to spam useless instances on startup. m_mapLock.Release(); return NULL; }*/ // create the actual instance. in->m_mapMgr = _CreateInstance(in); m_mapLock.Release(); return in->m_mapMgr; } else { // instance is already created. m_mapLock.Release(); return in->m_mapMgr; } } } } // if we're here, it means there are no instances on that map, or none of the instances on that map are joinable // by this player. m_mapLock.Release(); return NULL; } else { // units are *always* limited to their set instance ids. if(inf->type == INSTANCE_NULL) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap) { itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { // we never create instances just for units. m_mapLock.Release(); return itr->second->m_mapMgr; } } // instance is non-existent (shouldn't really happen for units...) m_mapLock.Release(); return NULL; } }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player* plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo* inf = WorldMapInfoStorage.LookupEntry(mapid); Group* pGroup; InstanceMap* instancemap; Instance* in; if(inf == NULL || mapid >= NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if(inf->type == INSTANCE_BATTLEGROUND) return INSTANCE_ABORT_NOT_FOUND; pGroup = plr->GetGroup(); // players without groups cannot enter raids and heroic instances if(pGroup == NULL && inf->type == INSTANCE_RAID && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; if(pGroup == NULL && (inf->type == INSTANCE_NONRAID && plr->iInstanceType == MODE_HEROIC) && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // players without raid groups cannot enter raid instances if(pGroup != NULL && pGroup->GetGroupType() != GROUP_TYPE_RAID && inf->type == INSTANCE_RAID && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // We deny transfer if we requested a heroic instance of a map that has no heroic mode // We are trying to enter into a non-multi instance with a heroic group, downscaling if(inf->type == INSTANCE_NONRAID && plr->GetDungeonDifficulty() == MODE_HEROIC) { plr->SetDungeonDifficulty(MODE_NORMAL); plr->SendDungeonDifficulty(); Group* grp = plr->GetGroup(); if(grp != NULL) grp->SetDungeonDifficulty(MODE_NORMAL); } // if it's not a normal / 10men normal then check if we even have this mode if(inf->type == INSTANCE_RAID && plr->GetRaidDifficulty() != MODE_NORMAL_10MEN) { uint32 newtype = 0; if(!inf->HasDifficulty(plr->GetRaidDifficulty())) { // no it doesn't so we will downscale it /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This part is totally speculative, if you know how this is done actually then do change it // switch(plr->GetRaidDifficulty()) { case MODE_NORMAL_25MEN: case MODE_HEROIC_10MEN: { newtype = MODE_NORMAL_10MEN; break; } case MODE_HEROIC_25MEN: { newtype = MODE_NORMAL_25MEN; break; } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // check if we have this mode if(!inf->HasDifficulty(newtype)) { //appearantly we don't so we set to 10men normal, which is the default for old raids too //regardless of their playerlimit newtype = MODE_NORMAL_10MEN; } // Setting the new mode on us and our group if(plr->GetRaidDifficulty() != newtype) { plr->SetRaidDifficulty(newtype); plr->SendRaidDifficulty(); Group* grp = plr->GetGroup(); if(grp != NULL) grp->SetRaidDifficulty(newtype); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // If we are here, it means: // 1.) We're a simple non-raid and non-heroic dungeon // 2.) We're a multi-dungeon set to heroic and we are in a group // 3.) We're a raid, and we are in a raid group // 4.) We're a raid, we are in a raid group, and we have the right mode set // // So, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // Otherwise, we will try to create them a new one. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// m_mapLock.Acquire(); instancemap = m_instances[mapid]; // If there are no instances of this map yet, we need to create the map if(instancemap == NULL) { if(instanceid != 0) { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } else { InstanceMap::iterator itr; // this is the case when we enter an already existing instance ( with summons for example ) if(instanceid != 0) { itr = instancemap->find(instanceid); if(itr != instancemap->end()) { in = itr->second; if(!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... m_mapLock.Release(); sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if(pGroup) in->m_creatorGroup = pGroup->GetID(); m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } } else // this is the case when we enter the normal way (e.g. we enter thru the portal ) { in = NULL; if(pGroup != NULL) // we are in a group { uint32 grpdiff; // We want to use the raid difficulty for raids, and dungeon difficulty for dungeons if(inf->type == INSTANCE_RAID) grpdiff = pGroup->m_raiddifficulty; else grpdiff = pGroup->m_difficulty; if((inf->type == INSTANCE_MULTIMODE && grpdiff == MODE_HEROIC) || inf->type == INSTANCE_RAID) { // This is the case when we don't have this map on this difficulty saved yet for the player entering if(plr->GetPersistentInstanceId(mapid, grpdiff) == 0) { // The group has this instance saved already so we will use it if(pGroup->m_instanceIds[mapid][ grpdiff ] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][ grpdiff ]); } else if(sWorld.instance_TakeGroupLeaderID) { PlayerInfo* pLeaderInfo = pGroup->GetLeader(); if(pLeaderInfo) { pLeaderInfo->savedInstanceIdsLock.Acquire(); PlayerInstanceMap::iterator itrLeader = pLeaderInfo->savedInstanceIds[ grpdiff ].find(mapid); if(itrLeader != pLeaderInfo->savedInstanceIds[ grpdiff ].end()) { in = sInstanceMgr.GetInstanceByIds(mapid, (*itrLeader).second); } pLeaderInfo->savedInstanceIdsLock.Release(); } } } // If we have it saved to the player then use that if(in == NULL && plr->GetPersistentInstanceId(mapid, grpdiff) != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, plr->GetPersistentInstanceId(mapid, grpdiff)); } } else { if(pGroup->m_instanceIds[mapid][ grpdiff ] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][ grpdiff ]); } } } if(in == NULL) { // We are not in a group, so we will look for an instance that we own and has the right difficulty uint32 diff; if(inf->type == INSTANCE_RAID) diff = plr->GetRaidDifficulty(); else diff = plr->GetDungeonDifficulty(); for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(in->m_difficulty == diff && PlayerOwnsInstance(in, plr)) break; in = NULL; } } // We've found an instance! if(in != NULL) { m_mapLock.Release(); // check the player count and in combat status. if(in->m_mapMgr) { if(in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; if(in->m_mapMgr->GetPlayerCount() >= inf->playerlimit) return INSTANCE_ABORT_FULL; } if(!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if(pGroup) in->m_creatorGroup = pGroup->GetID(); plr->SetInstanceID(in->m_instanceId); // found our instance, allow him in. return INSTANCE_OK; } } } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; switch(inf->type) { case INSTANCE_NONRAID: case INSTANCE_MULTIMODE: in->m_difficulty = plr->GetDungeonDifficulty(); break; case INSTANCE_RAID: in->m_difficulty = plr->GetRaidDifficulty(); break; } in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapInfo = inf; in->m_mapMgr = NULL; // always start off without a map manager, it is created in GetInstance() in->m_isBattleground = false; in->m_persistent = IS_PERSISTENT_INSTANCE(in) && objmgr.m_InstanceBossInfoMap[mapid] == NULL; in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; if(sWorld.instance_SlidingExpiration) { if(inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_HEROIC) in->m_expiration = UNIXTIME + TIME_DAY; else in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } else { if(inf->type == INSTANCE_MULTIMODE && in->m_difficulty >= MODE_HEROIC) { in->m_expiration = UNIXTIME - (UNIXTIME % TIME_DAY) + ((UNIXTIME % TIME_DAY) > (sWorld.instance_DailyHeroicInstanceResetHour * TIME_HOUR) ? 82800 : -3600) + ((sWorld.instance_DailyHeroicInstanceResetHour - sWorld.GMTTimeZone) * TIME_HOUR); } else if(IS_PERSISTENT_INSTANCE(in)) { if(m_nextInstanceReset[in->m_mapId] == 0) { m_nextInstanceReset[in->m_mapId] = UNIXTIME - (UNIXTIME % TIME_DAY) - ((sWorld.GMTTimeZone + 1) * TIME_HOUR) + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); CharacterDatabase.Execute("DELETE FROM server_settings WHERE setting_id LIKE 'next_instance_reset_%u';", in->m_mapId); CharacterDatabase.Execute("INSERT INTO server_settings VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } if(m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME) { do { time_t tmp = m_nextInstanceReset[in->m_mapId]; if(tmp + (TIME_MINUTE * 15) < UNIXTIME) m_nextInstanceReset[in->m_mapId] = tmp + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); } while(m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME); CharacterDatabase.Execute("DELETE FROM server_settings WHERE setting_id LIKE 'next_instance_reset_%u';", in->m_mapId); CharacterDatabase.Execute("INSERT INTO server_settings VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } in->m_expiration = m_nextInstanceReset[in->m_mapId]; } else { in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } } plr->SetInstanceID(in->m_instanceId); Log.Debug("InstanceMgr", "Creating instance for player %u and group %u on map %u. (%u)", in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // save our new instance to the database. in->SaveToDB(); // apply it in the instance map instancemap->insert(InstanceMap::value_type(in->m_instanceId, in)); // Try to add instance ID to player plr->SetPersistentInstanceId(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
uint32 InstanceMgr::PreTeleport(uint32 mapid, PlayerPointer plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = WorldMapInfoStorage.LookupEntry(mapid); Group * pGroup = plr->GetGroup() ; InstanceMap * instancemap; Instance * in; if(inf == NULL || mapid>=NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if(inf->type==INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; if( !plr->triggerpass_cheat ) { // players without groups cannot enter raid instances (no soloing them:P) if( pGroup == NULL && (inf->type == INSTANCE_RAID || inf->type == INSTANCE_MULTIMODE)) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // check that heroic mode is available if the player has requested it. if(plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // otherwise, we can create them a new one. m_mapLock.Acquire(); instancemap = m_instances[mapid]; if(instancemap) { InstanceMap::iterator itr; if(instanceid != 0) { //try to find our instance in ones active now. itr = instancemap->find(instanceid); if(itr != instancemap->end()) { Instance *inn = itr->second; if( PlayerOwnsInstance( inn, plr ) >= OWNER_CHECK_OK ) { m_mapLock.Release(); return INSTANCE_OK; } } //There are no active maps, re-check if this concerns a saved instance. Instance * saved_in = sInstanceMgr.GetSavedInstance( mapid, plr->GetLowGUID() ); if( saved_in && saved_in->m_instanceId == instanceid ) { if ( PlayerOwnsInstance( saved_in, plr ) >= OWNER_CHECK_OK ) { m_mapLock.Release(); return INSTANCE_OK; } } m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } else { // search all active instances and see if we have one here. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(PlayerOwnsInstance(in, plr) >= OWNER_CHECK_OK ) { m_mapLock.Release(); // check the player count and in combat status. if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat) { if( in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; // check if we are full if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit ) return INSTANCE_ABORT_FULL; } // found our instance, allow him in. return INSTANCE_OK; } else DEBUG_LOG("InstanceMgr","Check failed %s",plr->GetName()); } } } else { if(instanceid != 0) { return INSTANCE_ABORT_NOT_FOUND; } // gotta create the hashmap. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; in->m_expiration = (inf->type == INSTANCE_NONRAID) ? 0 : UNIXTIME + inf->cooldown; // expire time 0 is 10 minutes after last player leaves in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; in->m_difficulty = plr->iInstanceType; in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapMgr = NULLMAPMGR; // always start off without a map manager, it is created in GetInstance() //crash fix; GM's without group will start up raid instances as if they where nonraids //this to avoid exipring check, this is mainly for developers purpose; GM's should NOT invite any players here! if( plr->triggerpass_cheat && !plr->GetGroup() && inf->type == INSTANCE_RAID) { inf->type = INSTANCE_NONRAID; sGMLog.writefromsession(plr->GetSession(), "Started a raid instance %d [%s] as non_raid instance.", mapid, inf->name); DEBUG_LOG("InstanceMgr","Started a raid instance %d [%s] as non_raid instance.", mapid, inf->name); } in->m_mapInfo = inf; in->m_isBattleground=false; plr->SetInstanceID(in->m_instanceId); if( plr->GetGroup() && !plr->GetSession()->HasGMPermissions())//GM should not set the instanceID pGroup->SetGroupInstanceID(in->m_instanceId); DEBUG_LOG("InstanceMgr", "Prepared new instance %u for player %u and group %u on map %u. (%u)",in->m_instanceId, in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // apply it in the instance map instancemap->insert( InstanceMap::value_type( in->m_instanceId, in ) ); // create the actual instance (if we don't GetInstance() won't be able to access it). in->m_mapMgr = _CreateInstance(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
MapMgrPointer InstanceMgr::GetInstance(ObjectPointer obj) { PlayerPointer plr; Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; MapInfo * inf = WorldMapInfoStorage.LookupEntry(obj->GetMapId()); // we can *never* teleport to maps without a mapinfo. if( inf == NULL || obj->GetMapId() >= NUM_MAPS ) return NULLMAPMGR; if( obj->IsPlayer() ) { // players can join instances based on their groups/solo status. plr = TO_PLAYER( obj ); // single-instance maps never go into the instance set. if( inf->type == INSTANCE_NULL ) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap != NULL) { // check our instance_id, which we saved before in Player::_Relocate uint32 plr_instanceID = obj->GetInstanceID(); itr = instancemap->find(plr_instanceID); if(itr != instancemap->end()) { in = itr->second; if(in && in->m_mapMgr) { m_mapLock.Release(); return in->m_mapMgr; } } // iterate over our instances, and see if any of them are owned/joinable by him. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; // Is this our instance? uint8 poinst = PlayerOwnsInstance(in, plr); if(poinst >= OWNER_CHECK_OK ) { //Has it been created yet? if(in->m_mapMgr == NULL) { // create the actual instance. in->m_mapMgr = _CreateInstance(in); m_mapLock.Release(); // first one to enter, set the group instance ID if( plr->GetGroup() && !plr->GetSession()->HasGMPermissions() ) plr->GetGroup()->SetGroupInstanceID(in->m_instanceId); return in->m_mapMgr; } else // instance has found and verfied; us it. { if( poinst != OWNER_CHECK_GM_INSIDE && in->m_mapMgr->HasPlayers() && plr->GetGroup() && plr->GetGroup()->GetGroupInstanceID() != in->m_instanceId ) { Log.Warning("InstanceMgr","Reset GroupInstanceID for existing instance %u [%s] , old_ID = %u, new_ID = %u", in->m_mapId, in->m_mapInfo->name, plr->GetGroup()->GetGroupInstanceID(), in->m_instanceId ); plr->GetGroup()->SetGroupInstanceID(in->m_instanceId); } else if(in->m_mapMgr->HasPlayers() && plr->GetGroup() && plr->GetGroup()->GetGroupInstanceID() != in->m_instanceId) { Log.Warning("InstanceMgr","Forced GroupInstanceID for instance %u [%s] started by GM, old_ID = %u, new_ID = %u", in->m_mapId, in->m_mapInfo->name, plr->GetGroup()->GetGroupInstanceID(), in->m_instanceId ); plr->GetGroup()->SetGroupInstanceID(in->m_instanceId); } m_mapLock.Release(); return in->m_mapMgr; } } else DEBUG_LOG("InstanceMgr","Check failed %s",plr->GetName()); } } // if we're here, it means there are no instances on that map, or none of the instances on that map are joinable // by this player. m_mapLock.Release(); return NULLMAPMGR; } else { // units are *always* limited to their set instance ids. if(inf->type == INSTANCE_NULL) return m_singleMaps[obj->GetMapId()]; m_mapLock.Acquire(); instancemap = m_instances[obj->GetMapId()]; if(instancemap) { itr = instancemap->find(obj->GetInstanceID()); if(itr != instancemap->end()) { // we never create instances just for units. m_mapLock.Release(); return itr->second->m_mapMgr; } } // instance is non-existant (shouldn't really happen for units...) m_mapLock.Release(); return NULLMAPMGR; } }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player * plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = WorldMapInfoStorage.LookupEntry(mapid); Group * pGroup; InstanceMap * instancemap; Instance * in; if(inf == NULL || mapid>=NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if(inf->type==INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; // players without groups cannot enter raid instances (no soloing them:P) if(plr->GetGroup() == NULL && (inf->type == INSTANCE_RAID || inf->type == INSTANCE_MULTIMODE) && !plr->triggerpass_cheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // check that heroic mode is available if the player has requested it. if(plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // otherwise, we can create them a new one. m_mapLock.Acquire(); instancemap = m_instances[mapid]; // set up our pointers (cleaner code is always good) pGroup = plr->GetGroup(); if(instancemap == NULL) { if(instanceid != 0) { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } // gotta create the hashmap. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } else { InstanceMap::iterator itr; if(instanceid != 0) { itr = instancemap->find(instanceid); if(itr != instancemap->end()) { m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } } else { // search the instance and see if we have one here. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(PlayerOwnsInstance(in, plr)) { m_mapLock.Release(); // check the player count and in combat status. if(in->m_mapMgr) { if(in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; if(in->m_mapMgr->GetPlayerCount() >= inf->playerlimit) return INSTANCE_ABORT_FULL; } // found our instance, allow him in. return INSTANCE_OK; } } } } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; in->m_expiration =UNIXTIME + inf->cooldown; // expire time 0 is 10 minutes after last player leaves in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; in->m_difficulty = plr->iInstanceType; in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapMgr = NULL; // always start off without a map manager, it is created in GetInstance() in->m_mapInfo = inf; in->m_isBattleground=false; plr->SetInstanceID(in->m_instanceId); Log.Debug("InstanceMgr", "Creating instance for player %u and group %u on map %u. (%u)", in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // save our new instance to the database. in->SaveToDB(); // apply it in the instance map instancemap->insert( InstanceMap::value_type( in->m_instanceId, in ) ); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player* plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = LimitedMapInfoStorage.LookupEntry(mapid); MapEntry* map = dbcMap.LookupEntry(mapid); InstanceMap * instancemap; Instance * in = NULL; //is the map vaild? if(inf == NULL || mapid >= NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; // shouldn't happen if(inf->type == INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; if(map->israid()) // check that heroic mode is available if the player has requested it. { if(plr->iRaidType > 1 && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } else if(plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; //do we need addition raid/heroic checks? Group * pGroup = plr->GetGroup() ; if( !plr->triggerpass_cheat ) { // players without groups cannot enter raid instances (no soloing them:P) if( pGroup == NULL && (map->israid() || inf->type == INSTANCE_MULTIMODE)) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; //and has the required level if( plr->getLevel() < 80) { if(!map->israid()) { //otherwise we still need to be lvl 70/80 for heroic. if( plr->iInstanceType && plr->getLevel() < uint32(inf->HasFlag(WMI_INSTANCE_XPACK_02) ? 80 : 70)) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } else //otherwise we still need to be lvl 70/80 for heroic. if( plr->iRaidType > 1 && plr->getLevel() < uint32(inf->HasFlag(WMI_INSTANCE_XPACK_02) ? 80 : 70)) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; //and we might need a key too. bool reqkey = (inf->heroic_key[0] || inf->heroic_key[1])? true : false; bool haskey = (plr->GetItemInterface()->GetItemCount(inf->heroic_key[0], false) || plr->GetItemInterface()->GetItemCount(inf->heroic_key[1], false))? true : false; if(reqkey && !haskey) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } } // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // next we check if there is a saved instance belonging to him. // otherwise, we can create them a new one. m_mapLock.Acquire(); //find all instances for our map instancemap = m_instances[mapid]; if(instancemap) { InstanceMap::iterator itr; // do we have a specific instance id we should enter (saved or active). // don't bother looking for saved instances, if we had one we found it in areatrigger.cpp if(instanceid != 0) { itr = instancemap->find(instanceid); if(itr != instancemap->end()) { in = itr->second; //we have an instance,but can we enter it? uint8 owns = PlayerOwnsInstance( in, plr ); if( owns >= OWNER_CHECK_OK ) { // If the map is active and has players if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat) { //check if combat is in progress if( in->m_mapMgr->IsCombatInProgress()) { m_mapLock.Release(); return INSTANCE_ABORT_ENCOUNTER; } // check if we are full if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit ) { m_mapLock.Release(); return INSTANCE_ABORT_FULL; } } uint32 plrdiff = map->israid() ? plr->iRaidType : plr->iInstanceType; if(in->m_difficulty == plrdiff) { //wakeup call for saved instances if(!in->m_mapMgr) in->m_mapMgr = _CreateInstance(in); if(owns == OWNER_CHECK_SAVED_OK && !in->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) in->m_creatorGroup = plr->GetGroupID(); } m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_TOO_MANY; } } else DEBUG_LOG("InstanceMgr","Check failed %s, return code %u",plr->GetName(), owns); } m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } else { // search all active instances and see if we have one here. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; //we have an instance,but do we own it? uint8 owns = PlayerOwnsInstance(in, plr); if( owns >= OWNER_CHECK_OK ) { // check the player count and in combat status. if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat) { if( in->m_mapMgr->IsCombatInProgress()) { m_mapLock.Release(); return INSTANCE_ABORT_ENCOUNTER; } // check if we are full if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit ) { m_mapLock.Release(); return INSTANCE_ABORT_FULL; } } uint32 plrdiff = map->israid() ? plr->iRaidType : plr->iInstanceType; if(in->m_difficulty == plrdiff) { //wakeup call for saved instances if(!in->m_mapMgr) in->m_mapMgr = _CreateInstance(in); if(owns == OWNER_CHECK_SAVED_OK && !in->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) in->m_creatorGroup = plr->GetGroupID(); } // found our instance, allow him in. m_mapLock.Release(); return INSTANCE_OK; } } else DEBUG_LOG("InstanceMgr","Check failed %s, return code %u",plr->GetName(), owns); } } } else { if(instanceid != 0) { // wtf, how can we have an instance_id for a mapid which doesn't even exist? m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } // this mapid hasn't been added yet, so we gotta create the hashmap now. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } // if we're here, it means we need to create a new instance. bool raid = map->israid(); in = new Instance; in->m_creation = UNIXTIME; in->m_expiration = (raid ? UNIXTIME + inf->cooldown : 0); // expire time 0 is 10 minutes after last player leaves in->m_creatorGuid = plr->GetLowGUID(); in->m_creatorGroup = (pGroup ? pGroup->GetID() : 0); in->m_difficulty = (raid ? plr->iRaidType : plr->iInstanceType); in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapMgr = NULLMAPMGR; // always start off without a map manager, it is created in _CreateInstance(in) //crash fix; GM's without group will start up raid instances as if they where nonraids //this to avoid exipring check, this is mainly for developers purpose; GM's should NOT invite any players here! if( plr->triggerpass_cheat && !plr->GetGroup() && raid) { const char * message = "Started this instance for development purposes only, do not invite players!!"; sEventMgr.AddEvent( plr, &Player::_Warn, message, EVENT_UNIT_SENDMESSAGE, 5000, 1, 0); } in->m_mapInfo = inf; in->m_dbcMap = map; in->m_isBattleground = false; plr->SetInstanceID(in->m_instanceId); DEBUG_LOG("InstanceMgr", "Prepared new %s %u for player %u and group %u on map %u with difficulty %u. (%u)", raid ? "Raid" : "Instance" ,in->m_instanceId, in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_difficulty, in->m_instanceId); // apply it in the instance map instancemap->insert( InstanceMap::value_type( in->m_instanceId, in ) ); // create the actual instance (if we don't GetInstance() won't be able to access it). in->m_mapMgr = _CreateInstance(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player * plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = WorldMapInfoStorage.LookupEntry(mapid); Group * pGroup; InstanceMap * instancemap; Instance * in; if (inf == NULL || mapid >= NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if (inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if (inf->type == INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; pGroup = plr->GetGroup(); // players without groups cannot enter raids and heroic instances if (pGroup == NULL && (inf->type == INSTANCE_RAID || (inf->type == INSTANCE_MULTIMODE && plr->iInstanceType >= MODE_HEROIC)) && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // players without raid groups cannot enter raid instances if (pGroup != NULL && pGroup->GetGroupType() != GROUP_TYPE_RAID && inf->type == INSTANCE_RAID && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // check that heroic mode is available if the player has requested it. if (plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // otherwise, we can create them a new one. m_mapLock.Acquire(); instancemap = m_instances[mapid]; if (instancemap == NULL) { if (instanceid != 0) { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } // gotta create the hashmap. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } else { InstanceMap::iterator itr; if (instanceid != 0) { itr = instancemap->find(instanceid); if (itr != instancemap->end()) { in = itr->second; if (!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... m_mapLock.Release(); sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if (pGroup) in->m_creatorGroup = pGroup->GetID(); m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } } else { in = NULL; if (pGroup != NULL) { if ((inf->type == INSTANCE_MULTIMODE && pGroup->m_difficulty >= MODE_HEROIC) || inf->type == INSTANCE_RAID) { if (plr->GetPersistentInstanceId(mapid, pGroup->m_difficulty) == 0) { if (pGroup->m_instanceIds[mapid][pGroup->m_difficulty] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][pGroup->m_difficulty]); } else if (sWorld.instance_TakeGroupLeaderID) { PlayerInfo *pLeaderInfo = pGroup->GetLeader(); if (pLeaderInfo) { pLeaderInfo->savedInstanceIdsLock.Acquire(); PlayerInstanceMap::iterator itrLeader = pLeaderInfo->savedInstanceIds[pGroup->m_difficulty].find(mapid); if (itrLeader != pLeaderInfo->savedInstanceIds[pGroup->m_difficulty].end()) { in = sInstanceMgr.GetInstanceByIds(mapid, (*itrLeader).second); } pLeaderInfo->savedInstanceIdsLock.Release(); } } } if (in == NULL && plr->GetPersistentInstanceId(mapid, pGroup->m_difficulty) != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, plr->GetPersistentInstanceId(mapid, pGroup->m_difficulty)); } } else { if (pGroup->m_instanceIds[mapid][pGroup->m_difficulty] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][pGroup->m_difficulty]); } } } if (in == NULL) { // search the instance and see if we have one here. for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (in->m_difficulty == plr->iInstanceType && PlayerOwnsInstance(in, plr)) break; in = NULL; } } if (in != NULL) { m_mapLock.Release(); // check the player count and in combat status. if (in->m_mapMgr) { if (in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; if (in->m_mapMgr->GetPlayerCount() >= inf->playerlimit) return INSTANCE_ABORT_FULL; } if (!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if (pGroup) in->m_creatorGroup = pGroup->GetID(); plr->SetInstanceID(in->m_instanceId); // found our instance, allow him in. return INSTANCE_OK; } } } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; in->m_difficulty = pGroup ? pGroup->m_difficulty : plr->iInstanceType; in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapInfo = inf; in->m_mapMgr = NULL; // always start off without a map manager, it is created in GetInstance() in->m_isBattleground = false; in->m_persistent = IS_PERSISTENT_INSTANCE(in) && objmgr.m_InstanceBossInfoMap[mapid] == NULL; in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; if (sWorld.instance_SlidingExpiration) { if (inf->type == INSTANCE_MULTIMODE && in->m_difficulty >= MODE_HEROIC) in->m_expiration = UNIXTIME + TIME_DAY; else in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } else { if (inf->type == INSTANCE_MULTIMODE && in->m_difficulty >= MODE_HEROIC) { in->m_expiration = UNIXTIME - (UNIXTIME % TIME_DAY) + ((UNIXTIME % TIME_DAY) > (sWorld.instance_DailyHeroicInstanceResetHour * TIME_HOUR) ? 82800 : -3600) + ((sWorld.instance_DailyHeroicInstanceResetHour - sWorld.GMTTimeZone) * TIME_HOUR); } else if (IS_PERSISTENT_INSTANCE(in)) { if (m_nextInstanceReset[in->m_mapId] == 0) { m_nextInstanceReset[in->m_mapId] = UNIXTIME - (UNIXTIME % TIME_DAY) - ((sWorld.GMTTimeZone + 1) * TIME_HOUR) + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); CharacterDatabase.Execute("REPLACE INTO `server_settings` (`setting_id`, `setting_value`) VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } if (m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME) { do { time_t tmp = m_nextInstanceReset[in->m_mapId]; if (tmp + (TIME_MINUTE * 15) < UNIXTIME) m_nextInstanceReset[in->m_mapId] = tmp + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); } while (m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME); CharacterDatabase.Execute("REPLACE INTO `server_settings` (`setting_id`, `setting_value`) VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } in->m_expiration = m_nextInstanceReset[in->m_mapId]; } else { in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } } plr->SetInstanceID(in->m_instanceId); Log.Debug("InstanceMgr", "Creating instance for player %u and group %u on map %u. (%u)", in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // save our new instance to the database. in->SaveToDB(); // apply it in the instance map instancemap->insert(InstanceMap::value_type(in->m_instanceId, in)); // Try to add instance ID to player plr->SetPersistentInstanceId(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }