void ObjectUpdaterThread::Do() { uint32 last_time = getMSTime(); uint32 last_cTime = getMSTime(); uint32 last_gTime = getMSTime(); uint32 diff = 0; uint32 mstime = getMSTime(); uint32 cFlipper = 1; uint32 gFlipper = 3; uint32 mapid = m_MapMgr->GetMapId(); Creature * pCreature; GameObject * pGameObject; int result; int objectUpdate = 1; UpdateableCreaturesSet::iterator citr, citr_end, citr_last; UpdateableGameobjectsSet::iterator gitr, gitr_end, gitr_last; PlayerSet::iterator pitr, pitr_end; Player * pPlayer; SessionSet::iterator itr, it2; WorldSession *session; while(ThreadState != WOWD_THREADSTATE_TERMINATE) { // Provision for pausing this thread. if(ThreadState == WOWD_THREADSTATE_PAUSED) { while(ThreadState == WOWD_THREADSTATE_PAUSED) { Sleep(200); } } mstime = getMSTime(); last_time = mstime; if(cFlipper == 1) { citr_end = creatures.end(); // possible uint32 overflow ~50days if(last_cTime > mstime) diff = 100; else diff = mstime - last_cTime; citr_end = creatures.end(); for(citr = creatures.begin(); citr != citr_end;) { pCreature = (*citr); citr_last = citr; ++citr; if(!pCreature->IsInWorld() || !pCreature->GetMapCell()->IsActive()) { creatureLock.Acquire(); creatures.erase(citr_last); creatureLock.Release(); } else pCreature->Update(diff); } cFlipper = 0; // 2 loops away now. :) // update event holder eventholder->Update(diff); // update players pitr_end = m_MapMgr->_players.end(); pitr = m_MapMgr->_players.begin(); for(; pitr != pitr_end;) { pPlayer = (*pitr); ++pitr; pPlayer->Update(diff); } last_cTime = mstime; } else { cFlipper = 1; // Next loop we can have our cake. :) } if(gFlipper == 3) { if(last_gTime > mstime) diff = 300; else diff = mstime - last_gTime; gitr_end = gameobjects.end(); for(gitr = gameobjects.begin(); gitr != gitr_end;) { pGameObject = (*gitr); gitr_last = gitr; ++gitr; if(!pGameObject->IsInWorld() || !pGameObject->GetMapCell()->IsActive()) { gameobjectLock.Acquire(); gameobjects.erase(gitr_last); gameobjectLock.Release(); } else pGameObject->Update(diff); } gFlipper = 0; last_gTime = mstime; } else { ++gFlipper; } for(itr = m_MapMgr->Sessions.begin(); itr != m_MapMgr->Sessions.end();) { session = (*itr); it2 = itr; ++itr; if(result = session->Update(50, m_MapMgr->GetMapId())) { if(result == 1) { // complete deletion sWorld.DeleteSession(session); } m_MapMgr->Sessions.erase(it2); } } // instance thread object updates are done here if(mapid > 1 && mapid != 530) m_MapMgr->_UpdateObjects(); // Execution time compensation. :) mstime = getMSTime(); if(last_time > mstime) { Sleep(MAPMGR_SESSION_UPDATE_DELAY); // uint32 overflow } else { mstime = mstime - last_time; if(mstime < MAPMGR_SESSION_UPDATE_DELAY) { mstime = MAPMGR_SESSION_UPDATE_DELAY - mstime; if(mstime > 20) Sleep(mstime); } } } }
void MapMgr::_PerformObjectDuties() { ++mLoopCounter; uint32 mstime = getMSTime(); uint32 difftime = mstime - lastUnitUpdate; if(difftime > 500) difftime = 500; // Update creatures. { CreatureSet::iterator itr = activeCreatures.begin(); PetStorageMap::iterator it2 = m_PetStorage.begin(); Creature * ptr; Pet * ptr2; for(; itr != activeCreatures.end();) { ptr = *itr; ++itr; ptr->Update(difftime); } for(; it2 != m_PetStorage.end();) { ptr2 = it2->second; ++it2; ptr2->Update(difftime); } } // Update any events. eventHolder.Update(difftime); // Update players. { PlayerStorageMap::iterator itr = m_PlayerStorage.begin(); Player* ptr; for(; itr != m_PlayerStorage.end(); ) { ptr = static_cast< Player* >( (itr->second) ); ++itr; if( ptr != NULL ) ptr->Update( difftime ); } lastUnitUpdate = mstime; } // Update gameobjects (not on every loop, however) if( mLoopCounter % 2 ) { difftime = mstime - lastGameobjectUpdate; GameObjectSet::iterator itr = activeGameObjects.begin(); GameObject * ptr; for(; itr != activeGameObjects.end(); ) { ptr = *itr; ++itr; ptr->Update( difftime ); } lastGameobjectUpdate = mstime; } // Sessions are updated every loop. { int result; WorldSession * session; SessionSet::iterator itr = Sessions.begin(); SessionSet::iterator it2; for(; itr != Sessions.end();) { session = (*itr); it2 = itr; ++itr; if(session->GetInstance() != m_instanceID) { Sessions.erase(it2); continue; } // Don't update players not on our map. // If we abort in the handler, it means we will "lose" packets, or not process this. // .. and that could be diasterous to our client :P if(session->GetPlayer() && (session->GetPlayer()->GetMapMgr() != this && session->GetPlayer()->GetMapMgr() != 0)) { continue; } if((result = session->Update(m_instanceID))) { if(result == 1) { // complete deletion sWorld.DeleteSession(session); } Sessions.erase(it2); } } } // Finally, A9 Building/Distribution _UpdateObjects(); }
void MapMgr::_PerformObjectDuties() { ++mLoopCounter; uint32 mstime = getMSTime(); uint32 difftime = mstime - lastUnitUpdate; if(difftime > 500) difftime = 500; // Update any events. // we make update of events before objects so in case there are 0 timediff events they do not get deleted after update but on next server update loop eventHolder.Update(difftime); // Update creatures. { creature_iterator = activeCreatures.begin(); Creature* ptr; Pet* ptr2; for(; creature_iterator != activeCreatures.end();) { ptr = *creature_iterator; ++creature_iterator; ptr->Update(difftime); } pet_iterator = m_PetStorage.begin(); for(; pet_iterator != m_PetStorage.end();) { ptr2 = pet_iterator->second; ++pet_iterator; ptr2->Update(difftime); } } // Update players. { PlayerStorageMap::iterator itr = m_PlayerStorage.begin(); Player* ptr; for(; itr != m_PlayerStorage.end();) { ptr = itr->second; ++itr; ptr->Update(difftime); } lastUnitUpdate = mstime; } // Dynamic objects // // We take the pointer, increment, and update in this order because during the update the DynamicObject might get deleted, // rendering the iterator unincrementable. Which causes a crash! { for(DynamicObjectStorageMap::iterator itr = m_DynamicObjectStorage.begin(); itr != m_DynamicObjectStorage.end();) { DynamicObject* o = itr->second; ++itr; o->UpdateTargets(); } } // Update gameobjects (not on every loop, however) if(mLoopCounter % 2) { difftime = mstime - lastGameobjectUpdate; GameObjectSet::iterator itr = activeGameObjects.begin(); GameObject* ptr; for(; itr != activeGameObjects.end();) { ptr = *itr; ++itr; if(ptr != NULL) ptr->Update(difftime); } lastGameobjectUpdate = mstime; } // Sessions are updated every loop. { int result; WorldSession* session; SessionSet::iterator itr = Sessions.begin(); SessionSet::iterator it2; for(; itr != Sessions.end();) { session = (*itr); it2 = itr; ++itr; if(session->GetInstance() != m_instanceID) { Sessions.erase(it2); continue; } // Don't update players not on our map. // If we abort in the handler, it means we will "lose" packets, or not process this. // .. and that could be disastrous to our client :P if(session->GetPlayer() && (session->GetPlayer()->GetMapMgr() != this && session->GetPlayer()->GetMapMgr() != 0)) { continue; } if((result = session->Update(m_instanceID)) != 0) { if(result == 1) { // complete deletion sWorld.DeleteSession(session); } Sessions.erase(it2); } } } // Finally, A9 Building/Distribution _UpdateObjects(); }