Event & Update Buffering

From ESOUI Wiki

Jump to: navigation, search

Events in this game can trigger really, really... really fast. If you want to know how fast you can easily dump a counter to your chat window when that event triggers and watch as it fliiieeeeesssss by. This can cause issues when your update script has to parse something or do any heavy lifting. In fact, it can cause a problem at times when your update script isn't really doing much.

The safe way to handle this is to buffer your event handling so that you're only processing updates at set intervals, instead of nearly instantaneously. And yes, some things are fine at lightening speed but I've found that most work just fine between 0.33 and 3 seconds.

In the case of my War Tools addon I parse Cyrodiil rather extensively. When I first drafted the addon I walked into Cyrodiil, the events registered and I instantly entered stutter-frame, stop-motion TESO. It... was... bad... The simple fact was that events were triggering too quickly for the Cyrodiil parser to constantly run the way it was. In fact, it was running in layers on top of itself because the events fired so fast.

I also use this trick in Gear Tools to build a queuing system to handle gear moves because items can't all be unequipped all at once. You have to trigger those moves one at a time. So, I pile the "these things need to happen" gear moves into a table and I execute anything pending in the table, 1 item per iteration, as the OnUpdate event triggers in the addon... at a 0.33 buffer. Because anything faster than 1/3rd of a second doesn't allow time for gear to move properly and register with your UI.

This is the basic buffer I use, modified for "generic and global" application:

    local BufferTable = {}
    function BufferReached(key, buffer)
        if key == nil then return end
        if BufferTable[key] == nil then BufferTable[key] = {} end
        BufferTable[key].buffer = buffer or 3
        BufferTable[key].now = GetFrameTimeSeconds()
        if BufferTable[key].last == nil then BufferTable[key].last = BufferTable[key].now end
        BufferTable[key].diff = BufferTable[key].now - BufferTable[key].last
        BufferTable[key].eval = BufferTable[key].diff >= BufferTable[key].buffer
        if BufferTable[key].eval then BufferTable[key].last = BufferTable[key].now end
        return BufferTable[key].eval

This is how you would consume that buffer in an event/update handler:

    function OnUpdateHandler()
        if not BufferReached("myaddonupdatebuffer", 1) then return; end
        -- process your update here

--Wykkyd 20:37, 21 February 2014 (CST)

Personal tools