///// returns a new or existing Instance ///// in case of battlegrounds it will only return an existing map, those maps are created by bg-system Map* MapManager::CreateInstance(uint32 id, Player* player) { Map* map = NULL; Map* pNewMap = NULL; uint32 NewInstanceId = 0; // instanceId of the resulting map const MapEntry* entry = sMapStore.LookupEntry(id); if (entry->IsBattleGroundOrArena()) { // find existing bg map for player NewInstanceId = player->GetBattleGroundId(); MANGOS_ASSERT(NewInstanceId); map = FindMap(id, NewInstanceId); MANGOS_ASSERT(map); } else if (DungeonPersistentState* pSave = player->GetBoundInstanceSaveForSelfOrGroup(id)) { // solo/perm/group NewInstanceId = pSave->GetInstanceId(); map = FindMap(id, NewInstanceId); // it is possible that the save exists but the map doesn't if (!map) { pNewMap = CreateDungeonMap(id, NewInstanceId, pSave->GetDifficulty(), pSave); } } else { // if no instanceId via group members or instance saves is found // the instance will be created for the first time NewInstanceId = GenerateInstanceId(); Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty() : player->GetDifficulty(); pNewMap = CreateDungeonMap(id, NewInstanceId, diff); } // add a new map object into the registry if (pNewMap) { i_maps[MapID(id, NewInstanceId)] = pNewMap; map = pNewMap; } return map; }
BattleGroundMap* MapManager::CreateBattleGroundMap(uint32 id, uint32 InstanceId, BattleGround* bg) { DEBUG_LOG("MapInstanced::CreateBattleGroundMap: instance:%d for map:%d and bgType:%d created.", InstanceId, id, bg->GetTypeID()); PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), bg->GetMinLevel()); uint8 spawnMode = bracketEntry ? bracketEntry->difficulty : uint8(REGULAR_DIFFICULTY); BattleGroundMap* map = new BattleGroundMap(id, i_gridCleanUpDelay, InstanceId, spawnMode); MANGOS_ASSERT(map->IsBattleGroundOrArena()); map->SetBG(bg); bg->SetBgMap(map); // add map into map container i_maps[MapID(id, InstanceId)] = map; // BGs/Arenas not have saved instance data map->CreateInstanceData(false); return map; }
Map* MapManager::CreateMap(uint32 id, WorldObject const* obj) { MANGOS_ASSERT(obj); //if(!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId()); Guard _guard(*this); Map* m = NULL; MapEntry const* entry = sMapStore.LookupEntry(id); if(!entry) return NULL; if (entry->Instanceable()) { //create DungeonMap object if (obj->GetTypeId() == TYPEID_PLAYER) m = CreateInstance(id, (Player*)obj); else if (obj->IsInitialized() && obj->GetObjectGuid().IsMOTransport()) DEBUG_FILTER_LOG(LOG_FILTER_TRANSPORT_MOVES,"MapManager::CreateMap %s try create map %u (no instance given), currently not implemented.",obj->IsInitialized() ? obj->GetObjectGuid().GetString().c_str() : "<uninitialized>", id); else DETAIL_LOG("MapManager::CreateMap %s try create map %u (no instance given), BUG, wrong usage!",obj->IsInitialized() ? obj->GetObjectGuid().GetString().c_str() : "<uninitialized>", id); } else { //create regular non-instanceable map m = FindMap(id); if( m == NULL ) { m = new WorldMap(id, i_gridCleanUpDelay); //add map into container i_maps[MapID(id)] = m; // non-instanceable maps always expected have saved state m->CreateInstanceData(true); } } return m; }
Map* MapManager::CreateMap(uint32 id, const WorldObject* obj) { MANGOS_ASSERT(obj); //if(!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId()); Guard _guard(*this); Map * m = NULL; const MapEntry* entry = sMapStore.LookupEntry(id); if(!entry) return NULL; if(entry->Instanceable()) { MANGOS_ASSERT(obj->GetTypeId() == TYPEID_PLAYER); //create DungeonMap object if(obj->GetTypeId() == TYPEID_PLAYER) m = CreateInstance(id, (Player*)obj); } else { //create regular non-instanceable map m = FindMap(id); if( m == NULL ) { m = new WorldMap(id, i_gridCleanUpDelay); //add map into container i_maps[MapID(id)] = m; // non-instanceable maps always expected have saved state m->CreateInstanceData(true); } } return m; }
void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 resetTime) { // global reset for all instances of the given map MapEntry const *mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry->Instanceable()) return; time_t now = time(NULL); uint32 timeLeft = resetTime - now; if (!warn) { MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty); if (!mapDiff || !mapDiff->resetTime) { sLog.outError("InstanceSaveManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d", mapid); return; } // remove all binds to instances of the given map for(InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();) { if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty) _ResetSave(itr); else ++itr; } // delete them from the DB, even if not loaded CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM character_instance USING character_instance LEFT JOIN instance ON character_instance.instance = id WHERE map = '%u'", mapid); CharacterDatabase.PExecute("DELETE FROM group_instance USING group_instance LEFT JOIN instance ON group_instance.instance = id WHERE map = '%u'", mapid); CharacterDatabase.PExecute("DELETE FROM instance WHERE map = '%u'", mapid); CharacterDatabase.CommitTransaction(); // all needed values are already in resetTime uint32 next_reset = resetTime + InstanceResetScheduler::GetMaxResetTimeFor(mapDiff); // update it in the DB CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '%u' WHERE mapid = '%u' AND difficulty = '%u'", (uint64)next_reset, mapid, difficulty); m_Scheduler.SetResetTimeFor(mapid,difficulty,(time_t)next_reset); m_Scheduler.ScheduleReset(true, next_reset-3600, InstanceResetEvent(RESET_EVENT_INFORM_1, mapid, difficulty, 0)); } // note: this isn't fast but it's meant to be executed very rarely const MapManager::MapMapType& maps = sMapMgr.Maps(); MapManager::MapMapType::const_iterator iter_last = maps.lower_bound(MapID(mapid + 1)); for(MapManager::MapMapType::const_iterator mitr = maps.lower_bound(MapID(mapid)); mitr != iter_last; ++mitr) { Map *map2 = mitr->second; if(map2->GetId() != mapid) break; if (warn) ((InstanceMap*)map2)->SendResetWarnings(timeLeft); else ((InstanceMap*)map2)->Reset(INSTANCE_RESET_GLOBAL); } // TODO: delete creature/gameobject respawn times even if the maps are not loaded }
void MapPersistentStateManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime) { // global reset for all instances of the given map MapEntry const *mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry->Instanceable()) return; time_t now = time(NULL); if (!warn) { MapDifficultyEntry const* mapDiff = GetMapDifficultyData(mapid,difficulty); if (!mapDiff || !mapDiff->resetTime) { sLog.outError("MapPersistentStateManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d", mapid); return; } // remove all binds to instances of the given map for(PersistentStateMap::iterator itr = m_instanceSaveByInstanceId.begin(); itr != m_instanceSaveByInstanceId.end();) { if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty) { if (!((DungeonPersistentState*)itr->second)->IsExtended()) { _ResetSave(m_instanceSaveByInstanceId, itr); DeleteInstanceFromDB(itr->first, false); } else { DeleteInstanceFromDB(itr->first, true); ++itr; } } else ++itr; } // calculate the next reset time time_t next_reset = DungeonResetScheduler::CalculateNextResetTime(mapDiff, resetTime); // update it in the DB CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '%u' WHERE mapid = '%u' AND difficulty = '%u'", (uint64)next_reset, mapid, difficulty); m_Scheduler.SetResetTimeFor(mapid,difficulty,next_reset); m_Scheduler.ScheduleReset(true, next_reset-3600, DungeonResetEvent(RESET_EVENT_INFORM_1, mapid, difficulty, 0)); } // note: this isn't fast but it's meant to be executed very rarely const MapManager::MapMapType& maps = sMapMgr.Maps(); MapManager::MapMapType::const_iterator iter_last = maps.lower_bound(MapID(mapid + 1)); for(MapManager::MapMapType::const_iterator mitr = maps.lower_bound(MapID(mapid)); mitr != iter_last; ++mitr) { Map *map2 = mitr->second; if(map2->GetId() != mapid) break; if ((DungeonPersistentState*)map2->GetPersistentState() && ((DungeonPersistentState*)map2->GetPersistentState())->IsExtended()) break; if (warn) ((DungeonMap*)map2)->SendResetWarnings(resetTime - now); else ((DungeonMap*)map2)->Reset(INSTANCE_RESET_GLOBAL); } }