Exemple #1
0
/*
- adding instance into manager
- called from InstanceMap::Add, _LoadBoundInstances, LoadGroups
*/
InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load)
{
    InstanceSave *save = GetInstanceSave(instanceId);
    if(save) return save;

    const MapEntry* entry = sMapStore.LookupEntry(mapId);
    if(!entry || instanceId == 0)
    {
        sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d!", mapId, instanceId);
        return NULL;
    }

    if(!resetTime)
    {
        // initialize reset time
        // for normal instances if no creatures are killed the instance will reset in two hours
        if(entry->map_type == MAP_RAID || difficulty == DIFFICULTY_HEROIC)
            resetTime = GetResetTimeFor(mapId);
        else
        {
            resetTime = time(NULL) + 2 * HOUR;
            // normally this will be removed soon after in InstanceMap::Add, prevent error
            ScheduleReset(true, resetTime, InstResetEvent(0, mapId, instanceId));
        }
    }

    sLog.outDebug("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId);

    save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset);
    if(!load) save->SaveToDB();

    m_instanceSaveById[instanceId] = save;
    return save;
}
Exemple #2
0
void InstanceSaveManager::UnloadInstanceSave(uint32 InstanceId)
{
    if (InstanceSave* save = GetInstanceSave(InstanceId))
    {
        save->UnloadIfEmpty();
        if (save->m_toDelete)
            delete save;
    }
}
/*
 - adding instance into manager
 - called from InstanceMap::Add, _LoadBoundInstances, LoadGroups
 */
InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId,
		uint32 instanceId, Difficulty difficulty, time_t resetTime,
		bool canReset, bool load) {
	if (InstanceSave *old_save = GetInstanceSave(instanceId))
		return old_save;

	const MapEntry* entry = sMapStore.LookupEntry(mapId);
	if (!entry) {
		sLog->outError(
				"InstanceSaveManager::AddInstanceSave: wrong mapid = %d, instanceid = %d!",
				mapId, instanceId);
		return NULL;
	}

	if (instanceId == 0) {
		sLog->outError(
				"InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d!",
				mapId, instanceId);
		return NULL;
	}

	if (difficulty
			>= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) {
		sLog->outError(
				"InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong dificalty %u!",
				mapId, instanceId, difficulty);
		return NULL;
	}

	if (!resetTime) {
		// initialize reset time
		// for normal instances if no creatures are killed the instance will reset in two hours
		if (entry->map_type == MAP_RAID
				|| difficulty > DUNGEON_DIFFICULTY_NORMAL)
			resetTime = GetResetTimeFor(mapId, difficulty);
		else {
			resetTime = time(NULL) + 2 * HOUR;
			// normally this will be removed soon after in InstanceMap::Add, prevent error
			ScheduleReset(true, resetTime,
					InstResetEvent(0, mapId, difficulty, instanceId));
		}
	}

	sLog->outDebug(LOG_FILTER_MAPS,
			"InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d",
			mapId, instanceId);

	InstanceSave *save = new InstanceSave(mapId, instanceId, difficulty,
			resetTime, canReset);
	if (!load)
		save->SaveToDB();

	m_instanceSaveById[instanceId] = save;
	return save;
}
/*
- adding instance into manager
- called from InstanceMap::Add, _LoadBoundInstances, LoadGroups
*/
InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, uint32 entranceId, bool canReset, bool load)
{
    if (InstanceSave* old_save = GetInstanceSave(instanceId))
        return old_save;

    const MapEntry* entry = sMapStore.LookupEntry(mapId);
    if (!entry)
    {
        TC_LOG_ERROR("misc", "InstanceSaveManager::AddInstanceSave: wrong mapid = %d, instanceid = %d!", mapId, instanceId);
        return NULL;
    }

    if (instanceId == 0)
    {
        TC_LOG_ERROR("misc", "InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d!", mapId, instanceId);
        return NULL;
    }

    DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty);
    if (!difficultyEntry || difficultyEntry->InstanceType != entry->InstanceType)
    {
        TC_LOG_ERROR("misc", "InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong dificalty %u!", mapId, instanceId, difficulty);
        return NULL;
    }

    if (entranceId && !sWorldSafeLocsStore.LookupEntry(entranceId))
    {
        TC_LOG_WARN("misc", "InstanceSaveManager::AddInstanceSave: invalid entranceId = %d defined for instance save with mapid = %d, instanceid = %d!", entranceId, mapId, instanceId);
        entranceId = 0;
    }

    if (!resetTime)
    {
        // initialize reset time
        // for normal instances if no creatures are killed the instance will reset in two hours
        if (entry->IsRaid() || difficulty > DIFFICULTY_NORMAL)
            resetTime = GetResetTimeFor(mapId, difficulty);
        else
        {
            resetTime = time(NULL) + 2 * HOUR;
            // normally this will be removed soon after in InstanceMap::Add, prevent error
            ScheduleReset(true, resetTime, InstResetEvent(0, mapId, difficulty, instanceId));
        }
    }

    TC_LOG_DEBUG("maps", "InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId);

    InstanceSave* save = new InstanceSave(mapId, instanceId, difficulty, entranceId, resetTime, canReset);
    if (!load)
        save->SaveToDB();

    m_instanceSaveById[instanceId] = save;
    return save;
}
void InstanceSaveManager::LoadCharacterBinds()
{
    lock_instLists = true;

    QueryResult result = CharacterDatabase.Query("SELECT guid, instance, permanent, extended FROM character_instance");
    if (result)
    {
        do
        {
            Field* fields = result->Fetch();

            uint32 guid = fields[0].GetUInt32();
            uint32 instanceId = fields[1].GetUInt32();
            bool perm = fields[2].GetBool();
            bool extended = fields[3].GetBool();

            if (InstanceSave* save = GetInstanceSave(instanceId))
            {
                PlayerCreateBoundInstancesMaps(guid);
                InstancePlayerBind& bind = playerBindStorage[guid]->m[save->GetDifficulty()][save->GetMapId()];
                if (bind.save) // pussywizard: another bind for the same map and difficulty! may happen because of mysql thread races
                {
                    if (bind.perm) // already loaded perm -> delete currently checked one from db
                    {
                        PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID);
                        stmt->setUInt32(0, guid);
                        stmt->setUInt32(1, instanceId);
                        CharacterDatabase.Execute(stmt);
                        continue;
                    }
                    else // override temp bind by newest one
                    {
                        PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID);
                        stmt->setUInt32(0, guid);
                        stmt->setUInt32(1, bind.save->GetInstanceId());
                        CharacterDatabase.Execute(stmt);
                        bind.save->RemovePlayer(guid, this);
                    }
                }
                bind.save = save;
                bind.perm = perm;
                bind.extended = extended;
                save->AddPlayer(guid);
                if (perm)
                    save->SetCanReset(false);
            }
        }
        while (result->NextRow());
    }

    lock_instLists = false;
}
void InstanceSaveManager::Update()
{
    time_t now = time(NULL);
    time_t t, t2;

    while (!m_resetTimeQueue.empty())
    {
        t = m_resetTimeQueue.begin()->first;
        if (t >= now)
            break;

        // if m_resetTime has new resetTime, then write it to Queue, not delete the active instance.. 
        InstResetEvent &event = m_resetTimeQueue.begin()->second;
        time_t resetTime = GetResetTimeFor(event.mapid, event.difficulty);
        if (InstanceSave* save = GetInstanceSave(event.instanceId))
        {
            if (t2 = save->GetResetTime())
                if (t2 >= t)
                {
                    m_resetTimeQueue.erase(m_resetTimeQueue.begin());
                    m_resetTimeQueue.insert(std::pair<time_t, InstResetEvent>(t2, event));
                    break;
                }
        }
       
        if (event.type == 0)
        {
            // for individual normal instances, max creature respawn + X hours
            _ResetInstance(event.mapid, event.instanceId);
            m_resetTimeQueue.erase(m_resetTimeQueue.begin());
        }
        else
        {
            // global reset/warning for a certain map
            _ResetOrWarnAll(event.mapid, event.difficulty, event.type != 4, resetTime);
            if (event.type != 4)
            {
                // schedule the next warning/reset
                ++event.type;
                ScheduleReset(true, resetTime - ResetTimeDelay[event.type - 1], event);
            }
            m_resetTimeQueue.erase(m_resetTimeQueue.begin());
        }
    }
}
/*
- adding instance into manager
*/
InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, bool startup /*=false*/)
{
    ASSERT(!GetInstanceSave(instanceId));

    const MapEntry* entry = sMapStore.LookupEntry(mapId);
    if (!entry)
    {
        sLog->outError("InstanceSaveManager::AddInstanceSave: wrong mapid = %d, instanceid = %d!", mapId, instanceId);
        return NULL;
    }

    if (instanceId == 0)
    {
        sLog->outError("InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d!", mapId, instanceId);
        return NULL;
    }

    if (difficulty >= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY))
    {
        sLog->outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong dificalty %u!", mapId, instanceId, difficulty);
        return NULL;
    }

    time_t resetTime, extendedResetTime;
    if (entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL)
    {
        resetTime = GetResetTimeFor(mapId, difficulty);
        extendedResetTime = GetExtendedResetTimeFor(mapId, difficulty);
    }
    else
    {
        resetTime = time(NULL) + 3*DAY; // normals expire after 3 days even if someone is still bound to them, cleared on startup
        extendedResetTime = 0;
    }
    InstanceSave* save = new InstanceSave(mapId, instanceId, difficulty, resetTime, extendedResetTime);
    if (!startup)
        save->InsertToDB();

    m_instanceSaveById[instanceId] = save;
    return save;
}
bool InstanceSaveManager::DeleteInstanceSaveIfNeeded(uint32 InstanceId, bool skipMapCheck)
{
    return DeleteInstanceSaveIfNeeded(GetInstanceSave(InstanceId), skipMapCheck);
}
void InstanceSaveManager::_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)
    {
        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;
        }

        // calculate the next reset time
        uint32 diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;

        uint32 period = uint32(((mapDiff->resetTime * sWorld->getRate(RATE_INSTANCE_RESET_TIME))/DAY) * DAY);
        if (period < DAY)
            period = DAY;

        uint32 next_reset = uint32(((resetTime + MINUTE) / DAY * DAY) + period + diff);
        SetResetTimeFor(mapid, difficulty, next_reset);
        SetExtendedResetTimeFor(mapid, difficulty, next_reset + period);
        ScheduleReset(time_t(next_reset-3600), InstResetEvent(1, mapid, difficulty));

        // update it in the DB
        PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GLOBAL_INSTANCE_RESETTIME);
        stmt->setUInt32(0, next_reset);
        stmt->setUInt16(1, uint16(mapid));
        stmt->setUInt8(2, uint8(difficulty));
        CharacterDatabase.Execute(stmt);

        // remove all binds to instances of the given map and delete from db (delete per instance id, no mass deletion!)
        // do this after new reset time is calculated
        for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(), itr2; itr != m_instanceSaveById.end(); )
        {
            itr2 = itr++;
            if (itr2->second->GetMapId() == mapid && itr2->second->GetDifficulty() == difficulty)
                _ResetSave(itr2);
        }
    }

    // now loop all existing maps to warn / reset
    Map const* map = sMapMgr->CreateBaseMap(mapid);
    MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps();
    MapInstanced::InstancedMaps::iterator mitr;
    uint32 timeLeft;

    for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
    {
        Map* map2 = mitr->second;
        if (!map2->IsDungeon() || map2->GetDifficulty() != difficulty)
            continue;

        if (warn)
        {
            if (now >= resetTime)
                timeLeft = 0;
            else
                timeLeft = uint32(resetTime - now);

            map2->ToInstanceMap()->SendResetWarnings(timeLeft);
        }
        else
        {
            InstanceSave* save = GetInstanceSave(map2->GetInstanceId());
            map2->ToInstanceMap()->Reset(INSTANCE_RESET_GLOBAL, (save ? &(save->m_playerList) : NULL));
        }
    }
}
void InstanceSaveManager::UnloadInstanceSave(uint32 InstanceId)
{
    if (InstanceSave* save = GetInstanceSave(InstanceId))
        save->UnloadIfEmpty();
}