world-of-warcraftazerothcore

How does the update diff work in AzerothCore?


The worldserver source code is full of Update methods that take as input a diff integer value:

AzerothCore Update(uint32 diff)

How does it work?

And how is this linked to the "Update time diff" from the .server info command?

AzerothCore .server info command


Solution

  • To fully understand how this works, it's necessary to have a look at the main World run process.

    WorldRunnable::run()

    File: src/server/worldserver/WorldThread/WorldRunnable.cpp

    The method void WorldRunnable::run() is the "Main heartbeat for the World". This method runs the whole world process.

    Inside it, there is a while loop that runs as long as the world is supposed to keep running:

    void WorldRunnable::run()
    {
        uint32 realCurrTime = 0;
        uint32 realPrevTime = getMSTime();
    
        ///- While we have not World::m_stopEvent, update the world
        while (!World::IsStopped())
        {
            ++World::m_worldLoopCounter;
            realCurrTime = getMSTime();
    
            uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime);
    
            sWorld->Update( diff );
            realPrevTime = realCurrTime;
    
            uint32 executionTimeDiff = getMSTimeDiff(realCurrTime, getMSTime());
            devDiffTracker.Update(executionTimeDiff);
            avgDiffTracker.Update(executionTimeDiff > WORLD_SLEEP_CONST ? executionTimeDiff : WORLD_SLEEP_CONST);
    
            // ... some more code here
        }
        // at this point the world process is terminating
    
        // ... some more code here
    
    

    What this loop really does is basically:

    1) calculate the elapsed time (in milliseconds) since the previous iteration, this will be the diff

    2) call the sWorld->Update( diff ); function, that contains all the world process logic (see below) and passing the diff to it

    3) calculate how much time it took to run sWorld->Update( diff ); and update the devDiffTracker and its average avgDiffTracker. These values will be displayed by the .server info command.

    World::Update(uint32 diff)

    File: src/server/game/World/World.cpp

    The World::Update(uint32 diff) function gets constantly called by the main worldserver loop process and every time it takes in input the amount diff of elapsed time since the last call.

    This function is responsible for constantly updating the world, this is where all the magic happens.

    Timers

    There are a set of timers (defined in World.h that are being updated within the World::Update function:

    /// Timers for different object refresh rates
    enum WorldTimers
    {
        WUPDATE_AUCTIONS,
        WUPDATE_WEATHERS,
        WUPDATE_UPTIME,
        WUPDATE_CORPSES,
        WUPDATE_EVENTS,
        WUPDATE_CLEANDB,
        WUPDATE_AUTOBROADCAST,
        WUPDATE_MAILBOXQUEUE,
        WUPDATE_PINGDB,
        WUPDATE_5_SECS,
        WUPDATE_COUNT
    };
    

    For example, WUPDATE_AUTOBROADCAST is responsible for the period global messages defined in the acore_auth.autobroadcast table.

    Tasks

    The World::Update function also takes care of many timed-tasks, for example:

    /// Handle daily quests reset time
    if (m_gameTime > m_NextDailyQuestReset)
        ResetDailyQuests();
    

    Calling Update(diff) functions of Managers

    In AzerothCore there are singleton classes called Managers (Mgr) that handle specific parts of the game. For example BattlegroundMgr handles the Battlegrounds (BGs).

    Those classes have their own Update(uint32 diff) functions and they are called by World::Update that passes down the diff to them, for example:

    sBattlegroundMgr->Update(diff);
    sOutdoorPvPMgr->Update(diff);
    sBattlefieldMgr->Update(diff);
    /// ... there are more!
    

    OnWorldUpdate hook

    Last but not least, it calls sScriptMgr->OnWorldUpdate(diff);.

    This is part of the AzerothCore Module System, and defines a hook that can be used by third-part modules to attach custom logic to the World::Update function.