From 02930a0244c4d460544bcaddfccfed82ed5970cf Mon Sep 17 00:00:00 2001 From: prowley Date: Mon, 5 Oct 2020 16:59:44 -0700 Subject: [PATCH] net leader init fix, + internal stuff Fixed bug where the leader needing a waiting list would ignore a waiting list because it wasnt sent from the leader. Decoupled time updates from other visual updates and made visual responses to state changes faster but only happen when the state has changed. Should reduce load while also increasing visual response. Made offline and dead checks just in time. Added offline checks when something a net leader should do is about to happen. --- SteaSummon.toc | 2 +- events.lua | 1 + gossip.lua | 23 +++++-- main.lua | 10 ++- monitor.lua | 26 ++++++-- summon.lua | 175 +++++++++++++++++++++++++++---------------------- util.lua | 5 +- 7 files changed, 146 insertions(+), 96 deletions(-) diff --git a/SteaSummon.toc b/SteaSummon.toc index 75ed678..b084ecf 100755 --- a/SteaSummon.toc +++ b/SteaSummon.toc @@ -2,7 +2,7 @@ ## Title: SteaSummon ## Notes: One button summoning, shared summoning list... ## Author: Stea -## Version: 0.5 +## Version: 0.51 ## SavedVariablesPerCharacter: SteaSummonSave, SteaDEBUG Libs\embeds.xml diff --git a/events.lua b/events.lua index df4ffc5..cbe2348 100644 --- a/events.lua +++ b/events.lua @@ -90,6 +90,7 @@ function loaded(_, event, ...) -- otherwise the category or its children may not be registered for chat debug messages addonData.debug:chatCat("summon.waitlist") addonData.debug:chatCat("gossip") + addonData.debug:chatCat("buffs") addonData.debug:chatCatSwitch(true) -- strictly this is unnecessary, but I want to see the output cprint("loaded") diff --git a/gossip.lua b/gossip.lua index a850574..bcab662 100644 --- a/gossip.lua +++ b/gossip.lua @@ -189,6 +189,8 @@ local gossip = { return true end + self:offlineCheck() -- we may have become the leader + return self.netList[1] == self.me end, @@ -371,6 +373,7 @@ local gossip = { db ("gossip.event", "message", cmd, "from", sender, "payload:", subcmd) + --- arrive if cmd == "a" then db("gossip", "<< arrived <<", subcmd) @@ -380,12 +383,14 @@ local gossip = { addonData.summon:arrived(subcmd) end + --- add player elseif cmd == "ad" then db("gossip", "<< add <<", subcmd) if self:isLeader() then self:add(subcmd) end + --- add record elseif cmd == "adrec" then local i, rec = strsplit("_", subcmd) db("gossip", "<< add record <<", rec) @@ -393,6 +398,7 @@ local gossip = { addonData.summon.numwaiting = addonData.summon.numwaiting + 1 addonData.summon:showSummons() + --- initialize elseif cmd == "i" then -- initialize requestor, if deputy init leader when they /reload if self:isLeader() or (self.netList[1] == sender and self.netList[2] == self.me) then @@ -403,13 +409,14 @@ local gossip = { db("gossip", ">> initialize reply >>", data) -- first send the dest list self:SendCommMessage(self.channel, "dl " .. dl, "WHISPER", sender) - -- next waiting list - self:SendCommMessage(self.channel, "l " .. data, "WHISPER", sender) -- then set their destination self:destination(addonData.summon.zone, addonData.summon.location) + -- next waiting list + self:SendCommMessage(self.channel, "l " .. data, "WHISPER", sender) end end + --- leave netgroup (turned off comms) elseif cmd == "retire" then db("gossip", "<< retire <<", sender) local idx @@ -424,16 +431,16 @@ local gossip = { table.remove(self.netList, idx) end + --- destination list elseif cmd == "dl" then db("gossip", "<< at destination list <<") self.atDest = addonData.util:multiLineToMap(subcmd) elseif cmd == "l" then db("gossip", "<< waiting list <<", subcmd) - if sender == self.netList[1] then - addonData.util:unmarshalWaitingTable(subcmd) - end + addonData.util:unmarshalWaitingTable(subcmd) + --- destination change elseif cmd == "d" then local destination = string.gsub(subcmd, "_", " ") local zone, location = strsplit("+", destination) @@ -446,6 +453,7 @@ local gossip = { self:destination(zone, location, true) end + --- player at destination elseif cmd == "atD" then local player, at = strsplit("+", subcmd) at = at == "true" @@ -475,6 +483,7 @@ local gossip = { self:atDestination(at, player) end + --- status change elseif cmd == "s" then local player, status = strsplit("+", subcmd) db("gossip", "<< status <<", sender, player, status) @@ -484,6 +493,7 @@ local gossip = { addonData.summon:recStatus(addonData.summon.waiting[tonumber(player)], status) end + --- netgroup list elseif cmd == "netlist" then db("gossip", "<< netlist <<") self.netList = addonData.util:multiLineToTable(subcmd) @@ -494,6 +504,7 @@ local gossip = { self:initialize() end + --- request for netgroup list elseif cmd == "netreq" then db("gossip", "<< netreq <<") -- 4. if while waiting for network list, you receive a request for the network list, @@ -515,6 +526,7 @@ local gossip = { end end + --- notification of election, sender in init elseif cmd == "e" then db("gossip", "<< election <<") -- 5. if you ask for a network list and receive "election", wait 5 seconds for the network list to arrive @@ -531,6 +543,7 @@ local gossip = { db("gossip", "election in progress reported, but I am already out of the init phase, ignoring") end + --- election over, someone is leader elseif cmd == "edone" then db("gossip", "<< election over <<") self.inInit = false diff --git a/main.lua b/main.lua index ac1c3e3..83306a8 100644 --- a/main.lua +++ b/main.lua @@ -6,8 +6,12 @@ -- TODO: add type down search of list -- TODO: add fancy spell casting next button -- TODO: add sound when next button pops --- TODO: L10N **** Prio --- TODO: key bindings +-- TODO: offline on alt support +-- TODO: better offline, dead/ghost checks - dont need to enumerate raid for that, just the list +-- TODO: raid lead/assist function +-- TODO: nag for assist +-- TODO: auto life tap, maybe eat/drink too? +-- TODO: party/raid confirmation of add -- notes: -- @@ -16,7 +20,7 @@ -- gold ring (minimap frame button): ../COMMON/BlueMenuRing.png -- gold ring (minimap looks closer): ../COMMON/RingBorder -- gold ring: ../COMMON/GoldRing --- indicators (round): ../COMMON/inicator-(Red,Yellow,Gray,Green) +-- indicators (round): ../COMMON/idnicator-(Red,Yellow,Gray,Green) -- button fram UI-Quickslot /-Depress -- sound: RAID_WARNING = 8959, diff --git a/monitor.lua b/monitor.lua index 3db7212..ae01b9a 100644 --- a/monitor.lua +++ b/monitor.lua @@ -2,16 +2,22 @@ local _, addonData = ... +local LONG_TIME = 2 +local SHORT_TIME = 0.2 +local SECOND_TIME = 1 + local monitor = { - sec_t = {}, + second_t = {}, + short_t = {}, long_t = {}, init = function(self) addonData.debug:registerCategory("monitor") - self.sec_t = self:create(1, self.callback_sec) - self.long = self:create(2, self.callback_long) + self.short_t = self:create(SHORT_TIME, self.callback_short) + self.long_t = self:create(LONG_TIME, self.callback_long) + self.second_t = self:create(SECOND_TIME, self.callback_sec) self:start() - self.long:Play() + self.long_t:Play() end, create = function(_, i, callback, timerRepeat) @@ -39,17 +45,23 @@ local monitor = { end, start = function(self) - self.sec_t:Play() + self.short_t:Play() + self.second_t:Play() end, stop = function(self) - self.sec_t:Stop() + self.short_t:Stop() + self.second_t:Stop() end, - callback_sec = function() + callback_short = function() addonData.summon:tick() end, + callback_sec = function() + addonData.summon:timerSecondTick() + end, + callback_long = function() addonData.raid:fishArea() end, diff --git a/summon.lua b/summon.lua index b0b0717..554e3bb 100644 --- a/summon.lua +++ b/summon.lua @@ -16,6 +16,7 @@ local summon = { isWarlock = false, infoSend = false, me = "", + dirty = true, -- waiting list changed flag, to begin we want to show load list so default dirty --------------------------------- init = function(self) @@ -50,6 +51,14 @@ local summon = { self.numwaiting = #self.waiting end, + --------------------------------- + listDirty = function(self, dirty) + if dirty ~= nil then + self.dirty = dirty + end + return self.dirty + end, + --------------------------------- waitRecord = function(self, player, time, status, prioReason) local rec @@ -75,8 +84,9 @@ local summon = { end, --------------------------------- - recPlayer = function(_, rec, val) + recPlayer = function(self, rec, val) if val then + self:listDirty(true) db("summon.waitlist.record","setting record player value:", val) rec[1] = val end @@ -84,8 +94,9 @@ local summon = { end, --------------------------------- - recTime = function(_, rec, val) + recTime = function(self, rec, val) if val then + self:listDirty(true) db("summon.waitlist.record","setting record time value:", val) rec[2] = val end @@ -93,15 +104,17 @@ local summon = { end, --------------------------------- - recTimeIncr = function(_, rec) + recTimeIncr = function(self, rec) + self:listDirty(true) rec[2] = rec[2] + 1 db("summon.tick","setting record time value:", rec[2]) -- too verbose for summon.waitlist.record return rec[2] end, --------------------------------- - recStatus = function(_, rec, val) + recStatus = function(self, rec, val) if val then + self:listDirty(true) db("summon.waitlist.record","setting record status value:", val) rec[3] = val end @@ -109,8 +122,9 @@ local summon = { end, --------------------------------- - recPrio = function(_, rec, val) + recPrio = function(self, rec, val) if val then + self:listDirty(true) db("summon.waitlist.record","setting record priority reason value:", val) rec[4] = val end @@ -134,6 +148,7 @@ local summon = { idx = tonumber(string) end if idx and idx <= self.numwaiting then + self:listDirty(true) db("summon.waitlist.record", "removing", self:recPlayer(self.waiting[idx]), "from the waiting list") table.remove(self.waiting, idx) self.numwaiting = self.numwaiting - 1 @@ -145,6 +160,7 @@ local summon = { end, recAdd = function(self, rec, pos) + self:listDirty(true) if not pos or pos > self.numwaiting then db("summon.waitlist.record","appending record to waiting list for", self:recPlayer(rec)) table.insert(self.waiting, rec) @@ -260,25 +276,12 @@ local summon = { self:recAdd(self:waitRecord(player, 0, L["requested"], L["Normal"]), i) end - -- finally, this player may have come from an addon peer, so we need to check player status - db("summon.waitlist", player, "dead:", addonData.raid:isDead(player), "offline:", addonData.raid:isOffline(player)) - if addonData.raid:isDead(player) then - local wait = self:findWaitingPlayer(player) - self:recStatus(wait, L["dead"]) - end - - if addonData.raid:isOffline(player) then - local wait = self:findWaitingPlayer(player) - self:recStatus(wait, L["offline"]) - end - db("summon.waitlist", player .. " added to waiting list") self:showSummons() return index end, - --------------------------------- - tick = function(self) + timerSecondTick = function(self) --- update timers -- yea this is dumb, but time doesnt really work in wow -- so we count (rough) second ticks for how long someone has been waiting @@ -286,7 +289,10 @@ local summon = { for _, wait in pairs(self.waiting) do self:recTimeIncr(wait) end + end, + --------------------------------- + tick = function(self) --- detect arriving players local players = {} for _, wait in pairs(self.waiting) do @@ -307,7 +313,7 @@ local summon = { end --- maintain gossip list - addonData.gossip:offlineCheck() + addonData.gossip:offlineCheck() -- TODO: probably unnecessary --- update display self:showSummons() @@ -525,6 +531,9 @@ local summon = { db("summon.display","Screen Size (w/h):", GetScreenWidth(), GetScreenHeight() ) end + ------------------------------------------------------------ + --- Start of on tick visual updates + ------------------------------------------------------------ --- update buttons local next = false for i=1, 37 do @@ -538,12 +547,12 @@ local summon = { addonData.buttons[i].Button:SetText(player) addonData.buttons[i].Priority["FS"]:SetText(string.sub(self:recPrio(self.waiting[i]), 1, 1)) - if self:recStatus(self.waiting[i]) == L["offline"] or self:recStatus(self.waiting[i]) == L["dead"] then + if self:offline(player) or self:dead(player) then addonData.buttons[i].Button:SetEnabled(false) addonData.buttons[i].Status["FS"]:SetTextColor(0.5,0.5,0.5, 1) addonData.buttons[i].Button:SetAttribute("macrotext", "") addonData.buttons[i].Button:SetScript("OnMouseUp", nil) - else + elseif self:listDirty() then addonData.buttons[i].Button:SetEnabled(true) _, class = UnitClass(player) r,g,b,_ = GetClassColor(class) @@ -578,55 +587,63 @@ local summon = { self:enableButton(i, false) end - --- Cancel Button - -- Can cancel from own UI - -- Cancelling self sends msg to others - -- If summoning warlock, can cancel and send msg to others - cancelClick = function(_, button, worked) - if button == "LeftButton" and worked then - addonData.gossip:arrived(player) - db("summon.display","cancelling", player) + if self:listDirty() then + -- skip the rest of the visual updates + + --- Cancel Button + -- Can cancel from own UI + -- Cancelling self sends msg to others + -- If summoning warlock, can cancel and send msg to others + cancelClick = function(_, button, worked) + if button == "LeftButton" and worked then + addonData.gossip:arrived(player) + db("summon.display","cancelling", player) + end end - end - - addonData.buttons[i].Cancel:SetScript("OnMouseUp", cancelClick) - if self.waiting[i] then - --- Next Button - if not next and self:recStatus(self.waiting[i]) == L["requested"] and addonData.util:playerCanSummon() then - next = true - local spell = GetSpellInfo(698) -- Ritual of Summoning - addonData.buttons[38].Button:SetAttribute("macrotext", "/target " .. player .. "\n/cast " .. spell) - addonData.buttons[38].Button:SetScript("OnMouseUp", summonClick) - addonData.buttons[38].Button:Show() - end + addonData.buttons[i].Cancel:SetScript("OnMouseUp", cancelClick) - --- Time - addonData.buttons[i].Time["FS"]:SetText(string.format(SecondsToTime(self:recTime(self.waiting[i])))) - local strwd = addonData.buttons[i].Time["FS"]:GetStringWidth() - if strwd < 60 then - addonData.buttons[i].Time:SetWidth(80) - else - addonData.buttons[i].Time:SetWidth(strwd+20) - end + if self.waiting[i] then + --- Next Button + if not next and self:recStatus(self.waiting[i]) == L["requested"] and addonData.util:playerCanSummon() then + next = true + local spell = GetSpellInfo(698) -- Ritual of Summoning + addonData.buttons[38].Button:SetAttribute("macrotext", "/target " .. player .. "\n/cast " .. spell) + addonData.buttons[38].Button:SetScript("OnMouseUp", summonClick) + addonData.buttons[38].Button:Show() + end - --- Status - addonData.buttons[i].Status["FS"]:SetText(self:recStatus(self.waiting[i])) - end - end + --- Time + local noSecs = false + if tonumber(self:recTime(self.waiting[i])) > 59 then + noSecs = true + end + addonData.buttons[i].Time["FS"]:SetText(string.format(SecondsToTime(self:recTime(self.waiting[i]), noSecs))) + local strwd = addonData.buttons[i].Time["FS"]:GetStringWidth() + if strwd < 70 then + addonData.buttons[i].Time["FS"]:SetWidth(80) + else + addonData.buttons[i].Time:SetWidth(strwd+20) + addonData.buttons[i].Time["FS"]:SetWidth(strwd+10) + end - if not next then - -- all summons left are pending, disable the next button - addonData.buttons[38].Button:Hide() - end + --- Status + addonData.buttons[i].Status["FS"]:SetText(self:recStatus(self.waiting[i])) + end - -- summonTo + if not next then + -- all summons left are pending, disable the next button + addonData.buttons[38].Button:Hide() + end + end -- skip visual updates - if SummonToButton then - if IsInGroup(LE_PARTY_CATEGORY_HOME) then - SummonToButton:Show() - else - SummonToButton:Hide() + --- summonTo + if SummonToButton then + if IsInGroup(LE_PARTY_CATEGORY_HOME) then + SummonToButton:Show() + else + SummonToButton:Hide() + end end end @@ -653,6 +670,8 @@ local summon = { SummonFrame:Hide() addonData.monitor:stop() -- stop ui update tick end + + self:listDirty(false) end, --------------------------------- @@ -948,23 +967,23 @@ local summon = { addonData.gossip:status(self.summoningPlayer, L["summoned"]) end, - offline = function(self, player, offline) + offline = function(self, player) + local offline = not UnitIsConnected(player) local idx = self:findWaitingPlayerIdx(player) if idx then local state = "" - if offline then + if offline and not self:recStatus(self.waiting[idx]) == L["offline"] then db("summon.waitlist", "setting status of " .. player .. " to offline") state = L["offline"] - else - if self:recStatus(self.waiting[idx]) == L["offline"] then - db("summon.waitlist", "setting status of " .. player .. " from offline to requested") - state = L["requested"] - end + elseif not online and self:recStatus(self.waiting[idx]) == L["offline"] then + db("summon.waitlist", "setting status of " .. player .. " from offline to requested") + state = L["requested"] end if state ~= "" then self:recStatus(self.waiting[idx], state) end end + return offline end, remove = function(self, player) @@ -977,23 +996,23 @@ local summon = { return out end, - dead = function(self, player, dead) + dead = function(self, player) + local dead = UnitIsDeadOrGhost(player) local idx = self:findWaitingPlayerIdx(player) if idx then local state = "" - if dead then + if dead and not self.waiting[idx][3] == L["dead"] then state = L["dead"] db("summon.waitlist", "setting status of", player, "to dead") - else - if self.waiting[idx][3] == L["dead"] then - db("summon.waitlist", "setting status of", player, "from dead to requested") - state = L["requested"] - end + elseif not dead and self.waiting[idx][3] == L["dead"] then + db("summon.waitlist", "setting status of", player, "from dead to requested") + state = L["requested"] end if state ~= "" then self:recStatus(self.waiting[idx], state) end end + return dead end, --------------------------------- diff --git a/util.lua b/util.lua index e20d2c4..1725fc9 100644 --- a/util.lua +++ b/util.lua @@ -91,6 +91,7 @@ local util = { end addonData.summon.waiting = waiting addonData.summon.numwaiting = numwaiting + addonData.summon:listDirty(true) end, sortWaitingTableByTime = function() @@ -99,10 +100,10 @@ local util = { end) end, - isInTable = function(self, tbl, item) + isInTable = function(_, tbl, item) local inTable = false - for i,v in pairs(tbl) do + for _,v in pairs(tbl) do if v == item then inTable = true break