From 626c35ec48c04b7990572cb0b187df7513e7670e Mon Sep 17 00:00:00 2001 From: "Johnny C. Lam" Date: Sat, 10 Aug 2013 18:40:11 +0000 Subject: [PATCH] Refactor latency calculation into a separate OvaleLatency module. git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@1003 d5049fe3-3747-40f7-a4b5-f36d6801af5f --- Ovale.toc | 7 +++-- OvaleCondition.lua | 6 ++-- OvaleDamageTaken.lua | 4 +-- OvaleFuture.lua | 25 ---------------- OvaleLatency.lua | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 33 deletions(-) create mode 100644 OvaleLatency.lua diff --git a/Ovale.toc b/Ovale.toc index f5975d5..264835d 100644 --- a/Ovale.toc +++ b/Ovale.toc @@ -34,6 +34,7 @@ OvaleActionBar.lua OvaleEnemies.lua OvaleEquipement.lua OvaleGUID.lua +OvaleLatency.lua OvalePool.lua OvalePoolGC.lua OvaleQueue.lua @@ -41,21 +42,22 @@ OvaleRecount.lua OvaleSkada.lua OvaleStance.lua # +OvaleDamageTaken.lua OvalePaperDoll.lua # OvaleData.lua OvaleScripts.lua defaut\Chaman.lua defaut\Chasseur.lua +defaut\Chevalier.lua defaut\Demoniste.lua defaut\Druide.lua defaut\Guerrier.lua defaut\Mage.lua +defaut\Moine.lua defaut\Paladin.lua defaut\Pretre.lua defaut\Voleur.lua -defaut\Moine.lua -defaut\Chevalier.lua OvaleSpellDamage.lua OvaleSwing.lua # @@ -65,7 +67,6 @@ OvaleOptions.lua # OvaleFuture.lua # -OvaleDamageTaken.lua OvaleState.lua # OvaleCondition.lua diff --git a/OvaleCondition.lua b/OvaleCondition.lua index bb617f1..5553053 100644 --- a/OvaleCondition.lua +++ b/OvaleCondition.lua @@ -24,6 +24,7 @@ local OvaleEnemies = Ovale.OvaleEnemies local OvaleEquipement = Ovale.OvaleEquipement local OvaleFuture = Ovale.OvaleFuture local OvaleGUID = Ovale.OvaleGUID +local OvaleLatency = Ovale.OvaleLatency local OvalePaperDoll = Ovale.OvalePaperDoll local OvaleSpellDamage = Ovale.OvaleSpellDamage local OvaleStance = Ovale.OvaleStance @@ -2297,8 +2298,7 @@ OvaleCondition.conditions.lastswing = function(condition) return 0, nil, 0, OvaleSwing:GetLast(condition[1]), 1 end ---- Get the most recent estimate of latency in milliseconds. --- This condition is experimental and may not yield correct results. +--- Get the most recent estimate of roundtrip latency in milliseconds. -- @name Latency -- @paramsig number or boolean -- @param operator Optional. Comparison operator: equal, less, more. @@ -2310,7 +2310,7 @@ end -- if Latency(more 1000) Spell(sinister_strike) OvaleCondition.conditions.latency = function(condition) - return 0, nil, OvaleFuture.latency * 1000, 0, 0 + return 0, nil, OvaleLatency:GetLatency() * 1000, 0, 0 end --- Get the level of the target. diff --git a/OvaleDamageTaken.lua b/OvaleDamageTaken.lua index e160ef9..652dde4 100644 --- a/OvaleDamageTaken.lua +++ b/OvaleDamageTaken.lua @@ -15,7 +15,7 @@ Ovale.OvaleDamageTaken = OvaleDamageTaken -- local OvaleGUID = Ovale.OvaleGUID -local OvaleFuture = Ovale.OvaleFuture +local OvaleLatency = Ovale.OvaleLatency local OvalePool = Ovale.OvalePool local OvaleQueue = Ovale.OvaleQueue @@ -80,7 +80,7 @@ end function OvaleDamageTaken:GetRecentDamage(interval, lagCorrection) local lowerBound = Ovale.now - interval if lagCorrection then - lowerBound = lowerBound - OvaleFuture.latency + lowerBound = lowerBound - OvaleLatency:GetLatency() end self:RemoveExpiredEvents() diff --git a/OvaleFuture.lua b/OvaleFuture.lua index c03415c..aca9565 100644 --- a/OvaleFuture.lua +++ b/OvaleFuture.lua @@ -49,10 +49,6 @@ local self_lastTarget = nil -- Time at which a player aura was last added. local self_timeAuraAdded = nil --- The spell requests that have been sent to the server and are awaiting a reply. --- self_sentSpellcast[lineId] = timestamp -local self_sentSpellcast = {} - local OVALE_UNKNOWN_GUID = 0 -- These CLEU events are eventually received after a successful spellcast. @@ -69,8 +65,6 @@ local OVALE_CLEU_SPELLCAST_RESULTS = { -- --spell counter (see Counter function) OvaleFuture.counter = {} --- Most recent latency (time between UNIT_SPELLCAST_SENT and UNIT_SPELLCAST_SUCCEEDED events). -OvaleFuture.latency = 0 -- Debugging: spells to trace OvaleFuture.traceSpellList = nil -- @@ -167,24 +161,8 @@ local function AddSpellToQueue(spellId, lineId, startTime, endTime, channeled, a else spellcast.removeOnSuccess = true end - tinsert(self_activeSpellcast, spellcast) - -- Update latency measurement. API_GetTime() only updates on frame refresh (OnUpdate) so - -- this latency measurement has a lower bound of the 1/FPS, where FPS is the current frame - -- rate. - if self_sentSpellcast[lineId] then - local latency = Ovale.now - self_sentSpellcast[lineId] - local castTime = endTime - startTime - if castTime > 0 and latency > castTime then - latency = castTime - end - if latency > 0 then - self.latency = latency - end - self_sentSpellcast[lineId] = nil - end - ScoreSpell(spellId) Ovale.refreshNeeded["player"] = true end @@ -347,9 +325,6 @@ function OvaleFuture:UNIT_SPELLCAST_SENT(event, unit, spell, rank, target, lineI self_lastTarget = OVALE_UNKNOWN_GUID end TracePrintf(spell, "%s: %f %s on %s, lineId=%d", event, Ovale.now, spell, self_lastTarget, lineId) - - -- Note starting time for latency calculation. - self_sentSpellcast[lineId] = Ovale.now end end diff --git a/OvaleLatency.lua b/OvaleLatency.lua new file mode 100644 index 0000000..fdb30c2 --- /dev/null +++ b/OvaleLatency.lua @@ -0,0 +1,77 @@ +--[[-------------------------------------------------------------------- + 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 + +-- +local select = select +local API_GetNetStats = GetNetStats + +-- The spell requests that have been sent to the server and are awaiting a reply. +-- self_sentSpellcast[lineId] = GetTime() timestamp +local self_sentSpellcast = {} + +local self_lastUpdateTime = nil +local self_latency = nil +-- + +-- +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_sentSpellcast[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 latency = Ovale.now - self_sentSpellcast[lineId] + if latency > 0 then + self_latency = latency + self_lastUpdateTime = Ovale.now + end + self_sentSpellcast[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_sentSpellcast[lineId] = Ovale.now + end +end + +function OvaleLatency:GetLatency() + -- If we haven't cast a spell in a while, then get the average world roundtrip latency + -- using GetNetStats(). + if not self_latency or not self_lastUpdateTime or Ovale.now - self_lastUpdateTime > 10 then + self_latency = select(4, API_GetNetStats()) / 1000 + end + return self_latency +end +-- -- 1.7.9.5