John@72: local bsk=bsk John@72: local _G=_G John@72: local table=table John@72: local pairs=pairs John@72: local setmetatable=setmetatable John@72: local ipairs=ipairs John@72: local unpack=unpack John@72: local string=string John@72: local sformat=string.format John@72: local tostring=tostring John@72: local type=type John@72: local getn=getn John@72: John@72: local commlib = LibStub("AceComm-3.0") or _G.error("Couldn't load up AceComm") John@72: local s = LibStub("AceSerializer-3.0") or _G.error("Couldn't load up AceSerializer") John@72: John@72: setfenv(1,bsk) John@72: John@72: local function BuildPacket(handler,message) John@72: local p = {handler,message} John@72: local str = s:Serialize({handler,message}) John@72: print("sending",str) John@72: return p,str John@72: end John@72: John@72: local function SendMessage(str) John@97: --commlib:SendCommMessage("BSKADDON"..commversion,str,"GUILD") John@86: commlib:SendCommMessage("BSKADDON"..commversion,str,"RAID") John@72: end John@99: local function SendAdminMessage(str) John@99: --commlib:SendCommMessage("BSKADMIN"..commversion,str,"GUILD") John@99: commlib:SendCommMessage("BSKADMIN"..commversion,str,"RAID") John@99: end John@72: John@72: local function Send(handler,message) John@72: local p,str = BuildPacket(handler,message) John@72: SendMessage(str) John@72: end John@72: John@99: local function SendAdmin(handler,message) John@99: local p,str = BuildPacket(handler,message) John@99: SendAdminMessage(str) John@99: end John@99: John@72: -- todo: ActivateList and AddReserve -> state John@72: Comm = John@72: { John@72: ["SS"] = function(self,packet,sender,isloop) John@72: print("isloop",isloop) John@72: if not isloop then DispatchState(packet) end John@72: end, John@72: ["SendStateChange"] = function(self,...) John@72: local p,str = BuildPacket("SS",{...}) John@72: DispatchState(p[2]) John@72: SendMessage(str) John@72: end, John@72: ["AR"] = function(self,packet,sender,isloop) John@72: if isloop then return end John@72: PersonList:AddReserve(packet) John@72: changeListener:DataEvent() John@72: end, John@72: ["AddReserve"] = function(self,packet) John@72: if changeListener then John@72: changeListener:DataEvent(change) John@72: end John@72: Send("AR",packet) John@72: end, John@72: ["SendChange"] = function(self,change) John@72: if changeListener then John@72: changeListener:DataEvent(change) John@72: end John@72: Send("CC",change) John@72: end, John@72: ["CC"] = function(self,change,sender,isloop) John@72: if isloop then return end John@91: table.insert(db.profile.changes,change) John@72: ProcessChange(change) John@72: changeListener:DataEvent() John@72: end, John@72: ["Push"] = function(self) John@91: Send("PU",{db.profile.lists,db.profile.persons,db.profile.changes,db.profile.time}) John@72: end, John@72: ["PU"] = function(self,packet,sender,isloop) John@72: if isloop then return end John@91: db.profile.lists,db.profile.persons,db.profile.changes,db.profile.time = unpack(packet) John@72: CreateWorkingStateFromChanges(db.profile.changes) John@72: if changeListener then John@72: changeListener:DataEvent() John@72: end John@72: end, John@91: John@91: ["TS"] = function(self,packet,sender,isloop) John@91: if isloop then return end John@91: if masterLooterIsMe and admin then John@96: -- only non-admins will send this message John@92: John@92: local t = packet John@92: local remoteBase = table.remove(t,1) John@92: John@92: -- if their base is older than ours, this is easy - send them our John@92: -- base and all the changes John@92: -- if their base is equal to ours, then diff their changes vs ours John@92: -- and send them the remainder - it's ok if they have changes we John@92: -- don't John@92: -- if their base is newer, then we have a problem - it means another John@92: -- admin rebased and we aren't aware of that. but the other admin John@92: -- wouldn't have done that if they didn't believe all the admins John@92: -- were synced up to the release point. So do we trust that and use John@92: -- this as a rebase opportunity? print an error? just reply that we John@92: -- don't have anything new to share with them? only send them John@92: John@96: local success, o = CreateChangeDiff(remoteBase,t) John@96: if success and getn(o) > 0 then John@96: Send("CU",o) John@96: end John@96: if not success then -- push John@93: print("Received request at differing timebase",remoteBase,db.profile.time," ... pushing") John@93: self:Push() -- todo: send privately to requester John@92: end John@91: end John@91: end, John@91: John@91: ["CU"] = function(self,packet,sender,isloop) -- blindly trust an admin loot master John@91: if isloop then return end John@96: IntegrateChangeDiff(packet) John@91: end, John@91: John@91: ["RequestCatchup"] = function(self) John@91: if not admin then John@92: --local string = _g.tostring(timestamp) John@99: --for i,v in ipairs(db.profile.changes) do -- append all change timestamps John@92: -- string = string .. "|" .. _g.tostring(v.time) John@92: --end John@92: local t = {db.profile.time} John@99: for i,v in ipairs(db.profile.changes) do -- append all change timestamps John@92: table.insert(t,v.time) John@92: end John@92: Send("TS", t) -- todo: send privately to loot master John@91: else John@91: -- todo: admins talking to one another John@91: end John@91: John@91: end, John@99: John@99: ["SR"] = function(self,packet,sender,isloop) John@99: if isloop then return end John@99: if admin then John@99: RemoteAdminUpdateReceived(sender,packet) John@99: end John@99: end, John@99: John@99: ["SA"] = function(self,packet,sender,isloop) John@99: print("SA") John@99: if isloop then return end John@99: if admin then John@99: SendAdmin("SR",onloadAdminStatus) -- SR ... prevent infinite loop please John@99: RemoteAdminUpdateReceived(sender,packet) John@99: end John@99: end, John@99: John@99: ["SendAdminStatusTable"] = function(self) John@99: if admin and onloadAdminStatus and _G.next(onloadAdminStatus) then John@99: SendAdmin("SA",onloadAdminStatus) -- only send onload status, since that's the only data you're guaranteed to have safely safed John@99: end John@99: end, John@72: } John@72: John@72: local function OnCommReceived(prefix, message, distribution, sender) John@72: print("Received on", distribution) John@72: local success,packet = s:Deserialize(message) John@72: local isloop = _G.UnitName("player") == sender John@72: John@72: print("received",message) John@72: John@72: Comm[packet[1]](Comm,packet[2],sender,isloop) John@72: end John@72: John@99: local function OnAdminCommReceived(prefix, message, distribution, sender) John@99: print("Received (admin) on", distribution) John@99: local success,packet = s:Deserialize(message) John@99: local isloop = _G.UnitName("player") == sender John@99: John@99: print("received",message) John@99: John@99: Comm[packet[1]](Comm,packet[2],sender,isloop) John@99: end John@99: John@86: alertlist = {} John@86: local function OnOlderCommReceived(prefix, message, distribution, sender) John@86: if not alertlist[sender] then John@86: printf("Received communication from %s, who is using an older version of the addon; ignoring",sender) John@86: alertlist[sender]=true John@86: end John@86: end John@86: John@86: local function OnNewerCommReceived(prefix, message, distribution, sender) John@86: if not alertlist[sender] then John@86: printf("Received communication from %s, who is using a newer version of the addon; ignoring",sender) John@86: alertlist[sender]=true John@86: end John@86: end John@86: John@72: function InitializeComm() John@86: for i = 0,commversion-1 do John@86: commlib:RegisterComm("BSKADDON"..i,OnOlderCommReceived) John@86: end John@86: commlib:RegisterComm("BSKADDON"..commversion,OnCommReceived) John@86: for i = commversion+1,commversion+5 do -- some sensible number John@86: commlib:RegisterComm("BSKADDON"..i,OnNewerCommReceived) John@86: end John@72: end John@72: John@72: function DeinitializeComm() John@99: -- todo John@99: end John@72: John@99: local adminregistered = false John@99: function RegisterAdminChannels() John@99: if not adminregistered then John@99: for i = 0,commversion-1 do John@99: commlib:RegisterComm("BSKADMIN"..i,OnOlderCommReceived) John@99: end John@99: commlib:RegisterComm("BSKADMIN"..commversion,OnAdminCommReceived) John@99: for i = commversion+1,commversion+5 do -- some sensible number John@99: commlib:RegisterComm("BSKADMIN"..i,OnNewerCommReceived) John@99: end John@99: adminregistered = true John@99: John@99: -- now that we're set up, tell the other admins our status John@99: Comm:SendAdminStatusTable() John@99: end John@72: end John@99: John@99: function UnregisterAdminChannels() John@99: -- todo John@99: end John@99: