annotate Comm.lua @ 105:c6c748a5823b tip

Collaborative list trimming 80% functional Updates for the zone-in problem
author John@Yosemite-PC
date Sun, 06 May 2012 08:33:34 -0400
parents 21567b74fcc7
children
rev   line source
John@72 1 local bsk=bsk
John@72 2 local _G=_G
John@72 3 local table=table
John@72 4 local pairs=pairs
John@72 5 local setmetatable=setmetatable
John@72 6 local ipairs=ipairs
John@72 7 local unpack=unpack
John@72 8 local string=string
John@72 9 local sformat=string.format
John@72 10 local tostring=tostring
John@72 11 local type=type
John@72 12 local getn=getn
John@72 13
John@72 14 local commlib = LibStub("AceComm-3.0") or _G.error("Couldn't load up AceComm")
John@72 15 local s = LibStub("AceSerializer-3.0") or _G.error("Couldn't load up AceSerializer")
John@72 16
John@72 17 setfenv(1,bsk)
John@72 18
John@72 19 local function BuildPacket(handler,message)
John@72 20 local p = {handler,message}
John@72 21 local str = s:Serialize({handler,message})
John@72 22 print("sending",str)
John@72 23 return p,str
John@72 24 end
John@72 25
John@72 26 local function SendMessage(str)
John@97 27 --commlib:SendCommMessage("BSKADDON"..commversion,str,"GUILD")
John@86 28 commlib:SendCommMessage("BSKADDON"..commversion,str,"RAID")
John@72 29 end
John@99 30 local function SendAdminMessage(str)
John@99 31 --commlib:SendCommMessage("BSKADMIN"..commversion,str,"GUILD")
John@99 32 commlib:SendCommMessage("BSKADMIN"..commversion,str,"RAID")
John@99 33 end
John@72 34
John@72 35 local function Send(handler,message)
John@72 36 local p,str = BuildPacket(handler,message)
John@72 37 SendMessage(str)
John@72 38 end
John@72 39
John@99 40 local function SendAdmin(handler,message)
John@99 41 local p,str = BuildPacket(handler,message)
John@99 42 SendAdminMessage(str)
John@99 43 end
John@99 44
John@72 45 -- todo: ActivateList and AddReserve -> state
John@72 46 Comm =
John@72 47 {
John@72 48 ["SS"] = function(self,packet,sender,isloop)
John@72 49 print("isloop",isloop)
John@72 50 if not isloop then DispatchState(packet) end
John@72 51 end,
John@72 52 ["SendStateChange"] = function(self,...)
John@72 53 local p,str = BuildPacket("SS",{...})
John@72 54 DispatchState(p[2])
John@72 55 SendMessage(str)
John@72 56 end,
John@72 57 ["AR"] = function(self,packet,sender,isloop)
John@72 58 if isloop then return end
John@72 59 PersonList:AddReserve(packet)
John@72 60 changeListener:DataEvent()
John@72 61 end,
John@72 62 ["AddReserve"] = function(self,packet)
John@72 63 if changeListener then
John@72 64 changeListener:DataEvent(change)
John@72 65 end
John@72 66 Send("AR",packet)
John@72 67 end,
John@72 68 ["SendChange"] = function(self,change)
John@72 69 if changeListener then
John@72 70 changeListener:DataEvent(change)
John@72 71 end
John@72 72 Send("CC",change)
John@72 73 end,
John@72 74 ["CC"] = function(self,change,sender,isloop)
John@72 75 if isloop then return end
John@91 76 table.insert(db.profile.changes,change)
John@72 77 ProcessChange(change)
John@72 78 changeListener:DataEvent()
John@72 79 end,
John@72 80 ["Push"] = function(self)
John@91 81 Send("PU",{db.profile.lists,db.profile.persons,db.profile.changes,db.profile.time})
John@72 82 end,
John@72 83 ["PU"] = function(self,packet,sender,isloop)
John@72 84 if isloop then return end
John@91 85 db.profile.lists,db.profile.persons,db.profile.changes,db.profile.time = unpack(packet)
John@72 86 CreateWorkingStateFromChanges(db.profile.changes)
John@72 87 if changeListener then
John@72 88 changeListener:DataEvent()
John@72 89 end
John@72 90 end,
John@91 91
John@91 92 ["TS"] = function(self,packet,sender,isloop)
John@91 93 if isloop then return end
John@91 94 if masterLooterIsMe and admin then
John@96 95 -- only non-admins will send this message
John@92 96
John@92 97 local t = packet
John@92 98 local remoteBase = table.remove(t,1)
John@92 99
John@92 100 -- if their base is older than ours, this is easy - send them our
John@92 101 -- base and all the changes
John@92 102 -- if their base is equal to ours, then diff their changes vs ours
John@92 103 -- and send them the remainder - it's ok if they have changes we
John@92 104 -- don't
John@92 105 -- if their base is newer, then we have a problem - it means another
John@92 106 -- admin rebased and we aren't aware of that. but the other admin
John@92 107 -- wouldn't have done that if they didn't believe all the admins
John@92 108 -- were synced up to the release point. So do we trust that and use
John@92 109 -- this as a rebase opportunity? print an error? just reply that we
John@92 110 -- don't have anything new to share with them? only send them
John@92 111
John@96 112 local success, o = CreateChangeDiff(remoteBase,t)
John@96 113 if success and getn(o) > 0 then
John@105 114 Send("CU",{remoteBase,o})
John@96 115 end
John@96 116 if not success then -- push
John@93 117 print("Received request at differing timebase",remoteBase,db.profile.time," ... pushing")
John@93 118 self:Push() -- todo: send privately to requester
John@92 119 end
John@91 120 end
John@91 121 end,
John@91 122
John@91 123 ["CU"] = function(self,packet,sender,isloop) -- blindly trust an admin loot master
John@91 124 if isloop then return end
John@105 125 local base,changes = unpack(packet)
John@105 126 if base and base > 0 and changes and getn(changes) > 0 then
John@105 127 IntegrateChangeDiff(base,changes)
John@105 128 end
John@91 129 end,
John@91 130
John@102 131 ["RequestCatchup"] = function(self,from) -- todo: integrate from
John@91 132 if not admin then
John@92 133 --local string = _g.tostring(timestamp)
John@99 134 --for i,v in ipairs(db.profile.changes) do -- append all change timestamps
John@92 135 -- string = string .. "|" .. _g.tostring(v.time)
John@92 136 --end
John@92 137 local t = {db.profile.time}
John@99 138 for i,v in ipairs(db.profile.changes) do -- append all change timestamps
John@92 139 table.insert(t,v.time)
John@92 140 end
John@92 141 Send("TS", t) -- todo: send privately to loot master
John@91 142 else
John@91 143 -- todo: admins talking to one another
John@91 144 end
John@91 145
John@91 146 end,
John@99 147
John@99 148 ["SR"] = function(self,packet,sender,isloop)
John@99 149 if isloop then return end
John@99 150 if admin then
John@99 151 RemoteAdminUpdateReceived(sender,packet)
John@99 152 end
John@99 153 end,
John@99 154
John@99 155 ["SA"] = function(self,packet,sender,isloop)
John@99 156 print("SA")
John@99 157 if isloop then return end
John@99 158 if admin then
John@105 159 -- todo: only send back a diff. this is barbaric.
John@105 160 SendAdmin("SR",{onloadAdminStatus,db.profile.time,db.profile.changes}) -- SR ... prevent infinite loop please
John@99 161 RemoteAdminUpdateReceived(sender,packet)
John@99 162 end
John@99 163 end,
John@99 164
John@99 165 ["SendAdminStatusTable"] = function(self)
John@102 166 if admin then
John@105 167 SendAdmin("SA",{onloadAdminStatus,db.profile.time}) -- only send onload status, since that's the only data you're guaranteed to have safely saved
John@105 168 -- todo: see whether the above comment is correct, or the code
John@99 169 end
John@99 170 end,
John@72 171 }
John@72 172
John@72 173 local function OnCommReceived(prefix, message, distribution, sender)
John@72 174 print("Received on", distribution)
John@72 175 local success,packet = s:Deserialize(message)
John@72 176 local isloop = _G.UnitName("player") == sender
John@72 177
John@72 178 print("received",message)
John@72 179
John@72 180 Comm[packet[1]](Comm,packet[2],sender,isloop)
John@72 181 end
John@72 182
John@99 183 local function OnAdminCommReceived(prefix, message, distribution, sender)
John@99 184 print("Received (admin) on", distribution)
John@99 185 local success,packet = s:Deserialize(message)
John@99 186 local isloop = _G.UnitName("player") == sender
John@99 187
John@99 188 print("received",message)
John@99 189
John@99 190 Comm[packet[1]](Comm,packet[2],sender,isloop)
John@99 191 end
John@99 192
John@86 193 alertlist = {}
John@86 194 local function OnOlderCommReceived(prefix, message, distribution, sender)
John@86 195 if not alertlist[sender] then
John@86 196 printf("Received communication from %s, who is using an older version of the addon; ignoring",sender)
John@86 197 alertlist[sender]=true
John@86 198 end
John@86 199 end
John@86 200
John@86 201 local function OnNewerCommReceived(prefix, message, distribution, sender)
John@86 202 if not alertlist[sender] then
John@86 203 printf("Received communication from %s, who is using a newer version of the addon; ignoring",sender)
John@86 204 alertlist[sender]=true
John@86 205 end
John@86 206 end
John@86 207
John@72 208 function InitializeComm()
John@86 209 for i = 0,commversion-1 do
John@86 210 commlib:RegisterComm("BSKADDON"..i,OnOlderCommReceived)
John@86 211 end
John@86 212 commlib:RegisterComm("BSKADDON"..commversion,OnCommReceived)
John@86 213 for i = commversion+1,commversion+5 do -- some sensible number
John@86 214 commlib:RegisterComm("BSKADDON"..i,OnNewerCommReceived)
John@86 215 end
John@72 216 end
John@72 217
John@72 218 function DeinitializeComm()
John@99 219 -- todo
John@99 220 end
John@72 221
John@99 222 local adminregistered = false
John@99 223 function RegisterAdminChannels()
John@99 224 if not adminregistered then
John@99 225 for i = 0,commversion-1 do
John@99 226 commlib:RegisterComm("BSKADMIN"..i,OnOlderCommReceived)
John@99 227 end
John@99 228 commlib:RegisterComm("BSKADMIN"..commversion,OnAdminCommReceived)
John@99 229 for i = commversion+1,commversion+5 do -- some sensible number
John@99 230 commlib:RegisterComm("BSKADMIN"..i,OnNewerCommReceived)
John@99 231 end
John@99 232 adminregistered = true
John@99 233
John@99 234 -- now that we're set up, tell the other admins our status
John@99 235 Comm:SendAdminStatusTable()
John@99 236 end
John@72 237 end
John@99 238
John@99 239 function UnregisterAdminChannels()
John@99 240 -- todo
John@99 241 end
John@99 242