Mercurial > wow > breuesk
view Comm.lua @ 95:5df2c9cdb8c8
A few notes
author | John@Yosemite-PC |
---|---|
date | Sun, 22 Apr 2012 23:18:35 -0400 |
parents | 2058d86778b4 |
children | 082ff877c443 |
line wrap: on
line source
local bsk=bsk local _G=_G local table=table local pairs=pairs local setmetatable=setmetatable local ipairs=ipairs local unpack=unpack local string=string local sformat=string.format local tostring=tostring local type=type local getn=getn local commlib = LibStub("AceComm-3.0") or _G.error("Couldn't load up AceComm") local s = LibStub("AceSerializer-3.0") or _G.error("Couldn't load up AceSerializer") setfenv(1,bsk) local function BuildPacket(handler,message) local p = {handler,message} local str = s:Serialize({handler,message}) print("sending",str) return p,str end local function SendMessage(str) --commlib:SendCommMessage("BSKADDON",str,"GUILD") commlib:SendCommMessage("BSKADDON"..commversion,str,"RAID") end local function Send(handler,message) local p,str = BuildPacket(handler,message) SendMessage(str) end -- todo: ActivateList and AddReserve -> state Comm = { ["SS"] = function(self,packet,sender,isloop) print("isloop",isloop) if not isloop then DispatchState(packet) end end, ["SendStateChange"] = function(self,...) local p,str = BuildPacket("SS",{...}) DispatchState(p[2]) SendMessage(str) end, ["AR"] = function(self,packet,sender,isloop) if isloop then return end PersonList:AddReserve(packet) changeListener:DataEvent() end, ["AddReserve"] = function(self,packet) if changeListener then changeListener:DataEvent(change) end Send("AR",packet) end, ["SendChange"] = function(self,change) if changeListener then changeListener:DataEvent(change) end Send("CC",change) end, ["CC"] = function(self,change,sender,isloop) if isloop then return end table.insert(db.profile.changes,change) ProcessChange(change) changeListener:DataEvent() end, ["Push"] = function(self) Send("PU",{db.profile.lists,db.profile.persons,db.profile.changes,db.profile.time}) end, ["PU"] = function(self,packet,sender,isloop) if isloop then return end db.profile.lists,db.profile.persons,db.profile.changes,db.profile.time = unpack(packet) CreateWorkingStateFromChanges(db.profile.changes) if changeListener then changeListener:DataEvent() end end, ["TS"] = function(self,packet,sender,isloop) if isloop then return end if masterLooterIsMe and admin then -- only non-admins will send this message, send them the present -- working state local t = packet local remoteBase = table.remove(t,1) -- if their base is older than ours, this is easy - send them our -- base and all the changes -- if their base is equal to ours, then diff their changes vs ours -- and send them the remainder - it's ok if they have changes we -- don't -- if their base is newer, then we have a problem - it means another -- admin rebased and we aren't aware of that. but the other admin -- wouldn't have done that if they didn't believe all the admins -- were synced up to the release point. So do we trust that and use -- this as a rebase opportunity? print an error? just reply that we -- don't have anything new to share with them? only send them -- if remoteBase == db.profile.time then local j = 1 -- index in foreign list local n = getn(t) local o = {} for i,v in pairs(db.profile.changes) do -- for each timestamp in our list if t and t[j] < v.time then table.insert(o,v) end while j<n and t[j] <= v.time do j = j+1 end -- advance the foreign pointer past our current entry end -- j>=n ? add because the remote hit end of road. lt? add because it's a missing stamp print("Received request at timebase",remoteBase,"and returning:") PrintTable(o) if getn(o) > 0 then Send("CU",o) -- todo: send privately to the requster end else print("Received request at differing timebase",remoteBase,db.profile.time," ... pushing") self:Push() -- todo: send privately to requester end end end, ["CU"] = function(self,packet,sender,isloop) -- blindly trust an admin loot master if isloop then return end local c = packet local old = db.profile.changes local new = {} local op = 1 local cp = 1 local no = getn(old) local nc = getn(c) if no == 0 then db.profile.changes = c else while op <= no or cp <= nc do -- lists are pre-sorted. insertion merge them if cp > nc then -- inelegant table.insert(new,old[op]) op = op + 1 elseif op > no then table.insert(new,c[cp]) cp = cp + 1 elseif c[cp].time < old[op].time then table.insert(new,c[cp]) cp = cp + 1 elseif c[cp].time > old[op].time then table.insert(new,old[op]) op = op + 1 else error("Bad update received from ",sender) end end print("Updating changes - ",getn(new), "entries") db.profile.changes = new end CreateWorkingStateFromChanges(db.profile.changes) if changeListener then changeListener:DataEvent() end end, ["RequestCatchup"] = function(self) if not admin then --local string = _g.tostring(timestamp) --for i,v in pairs(db.profile.changes) do -- append all change timestamps -- string = string .. "|" .. _g.tostring(v.time) --end local t = {db.profile.time} for i,v in pairs(db.profile.changes) do -- append all change timestamps table.insert(t,v.time) end Send("TS", t) -- todo: send privately to loot master else -- todo: admins talking to one another end end, } local function OnCommReceived(prefix, message, distribution, sender) print("Received on", distribution) local success,packet = s:Deserialize(message) local isloop = _G.UnitName("player") == sender print("received",message) Comm[packet[1]](Comm,packet[2],sender,isloop) end alertlist = {} local function OnOlderCommReceived(prefix, message, distribution, sender) if not alertlist[sender] then printf("Received communication from %s, who is using an older version of the addon; ignoring",sender) alertlist[sender]=true end end local function OnNewerCommReceived(prefix, message, distribution, sender) if not alertlist[sender] then printf("Received communication from %s, who is using a newer version of the addon; ignoring",sender) alertlist[sender]=true end end function InitializeComm() for i = 0,commversion-1 do commlib:RegisterComm("BSKADDON"..i,OnOlderCommReceived) end commlib:RegisterComm("BSKADDON"..commversion,OnCommReceived) for i = commversion+1,commversion+5 do -- some sensible number commlib:RegisterComm("BSKADDON"..i,OnNewerCommReceived) end end function DeinitializeComm() end