--[[-------------------------------------------------------------------- Ovale Spell Priority Copyright (C) 2013 Johnny C. Lam This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License in the LICENSE file accompanying this program. --]]-------------------------------------------------------------------- local _, Ovale = ... local OvaleLatency = Ovale:NewModule("OvaleLatency", "AceEvent-3.0") Ovale.OvaleLatency = OvaleLatency --<private-static-properties> local API_GetNetStats = GetNetStats local API_GetTime = GetTime --</private-static-properties> --<public-static-properties> -- The spell requests that have been sent to the server and are awaiting a reply. -- spellcast[lineId] = GetTime() timestamp OvaleLatency.spellcast = {} OvaleLatency.lastUpdateTime = nil OvaleLatency.latency = nil --</public-static-properties> --<public-static-methods> function OvaleLatency:OnEnable() self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START", "UpdateLatency") self:RegisterEvent("UNIT_SPELLCAST_SENT") self:RegisterEvent("UNIT_SPELLCAST_START", "UpdateLatency") self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED", "UpdateLatency") end function OvaleLatency:OnDisable() self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START") self:UnregisterEvent("UNIT_SPELLCAST_SENT") self:UnregisterEvent("UNIT_SPELLCAST_START") self:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED") end -- Event handler for UNIT_SPELLCAST_* events that updates the current roundtrip latency. function OvaleLatency:UpdateLatency(event, unit, name, rank, lineId, spellId) if unit == "player" and self.spellcast[lineId] then --[[ Assume an event loop looks like: client --SENT--> server (processing) --CHANNEL_START/START/SUCCEEDED--> client By taking the difference between the SENT and CHANNEL_START/START/SUCCEEDED events, we are assuming that the processing time on the server is negligible compared to the network latency. As a result, this will always over-estimate the true latency. ]]-- local now = API_GetTime() local latency = now - self.spellcast[lineId] if latency > 0 then self.latency = latency self.lastUpdateTime = now end self.spellcast[lineId] = nil end end function OvaleLatency:UNIT_SPELLCAST_SENT(event, unit, spell, rank, target, lineId) if unit == "player" then -- Note starting time for latency calculation. self.spellcast[lineId] = API_GetTime() end end function OvaleLatency:GetLatency() -- If we haven't cast a spell in a while, then get the average world roundtrip latency -- using GetNetStats(). local now = API_GetTime() if not self.latency or not self.lastUpdateTime or now - self.lastUpdateTime > 10 then local _, _, _, latency = API_GetNetStats() self.latency = latency / 1000 end return self.latency end --</public-static-methods>