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
|