If I add AceSerializer-3.0, then I might as well go for AceComm-3.0, AceEvent-3.0, etc, and embed Ace3 in favour of ChatThrottleLib. Not a big issue, as I started the project with Ace3, but got advised not to go that route.
Man, I am getting confused! Should of taken the blue pill....
you're sending the entire guildbank on each bank close? is that right?
wouldn't it make more sense to just send the slots that have changed?
when you open the frame/change tabs, compare each slot to your internal record of the guild bank info. record any changes in a table (something like bankDelta[#bankDelta+1] = { slotNum = #, tabNum = #, itemString = string, etc }).
when you close the frame, broadcast that data and apply it to your internal bank data.
i would think the only time you need to transmit the entire contents of the bank is when somebody first logs in. form there, it's just a matter of sending the changes.
if you're concerned about going out of sync, you could come up with some kind of checksum that you send as well that would be a way to fall back to a retransmit if somebody loses sync.
Yeah, sending only changed slots does not work. I attempted using that method in a communications module for MobileVault. There was no way to maintain consistency for all the users involved. There are too many opportunities for people to miss changes and then never have them fully propagate through the user base.
Xinhuan and Starinnia, since you responded earlier that this lib could be useful when complete for your own addons, I would like to ask if the data format I am using is standardized enough, or do I need to tweak it, or will you adjust code on your end?
etc... The final variable names may change depending on how I code the scan, but you get the idea. I have purposely used GetGuildBankMoney() to get the funds in raw copper, and left the conversion into higher coins up to authors for localization reasons.
** EDIT **
I realize that GUILDBANK_UPDATE_MONEY() fires even when someone isn't actually at the bank; guild repairs, the possible tithing system Blizzard talked about for Cataclysm.. What I did not want to do is fire off a comm and a callback for that, as those could be updated incredibly frequently. Therefore, I chose to fire the callback and comm on GUILDBANKFRAME_CLOSED() which means lib.guildBank[guildName].money may not be accurate in a timely fashion. Thoughts?
it gives you more flexibility in adding data to the tables without running into conflicts and using the minimal amount of tables to hold it.
it also means that when you transmit you can just serialise the page table and send it in one go.
btw, if a tab is hidden from everyone but a specific rank does it still get transmitted to everyone? (if logged on as someone in the rank to read it)
I will try those changes, thank you Arkayenro. And no, I do not intend to send data to those who should not be able to see the bank frame or page; I just haven't solved that riddle yet.
I think I have the sending to appropriate people licked; at least I hope.
function lib:GUILDBANKFRAME_CLOSED()
local commString:Serialize("UPDATE", lib.guildBank)
local _, numGuildOnline = GetNumGuildMembers()
for i = 1, numGuildOnline do
local rankIndex = Select(3, GetRosterInfo(i))
local name = GetRosterInfo(i)
local function GuildPermissions(...)
local k == 16 -- can withdraw gold from the guild bank
if rankIndex.._G.("GUILDCONTROL_OPTION"..k) == 1 then
commSend(string.format("gBankComm", commString), "WHISPER", name..i)
end
end
end
local pName = UnitName("player")
local bankData = lib.guildBank
lib.CallBacks:Fire("GuildBankComm_ContentsChanged", pName, bankData)
end
myrroddin: You should load the lib in game. Make sure there's no errors on login before uploading the lib.
Anyway. I don't think it's a good idea to whisper everyone in the guild the entire contents of your table when you close the guild bank.
A small bank with 1 page and 20 items would look like this. http://paste.wowace.com/2872/
Serializing that table would be 707 characters long and be split into 3 messages.
A bank with 6 tabs and 480 items would be near 2676 characters long split into 11 messages.
I would instead send 1 message to guild comm saying I've updated my data and for others to whisper me for updates.
I would also look into making a hash string of each tab and sending that first before sending the whole table. If their hash matches yours then there's no need for them to request updates. Allara's CRC-32 example
So serialize table > hash function.
So once you close your bank you'd send to guild comm
"HASHUPDATE 11111111,22222222,33333333,44444444,55555555,66666666"
and others would request just the pages that don't match their own. Then when they whisper you, you confirm their rank matches the tab rank and reply with the tab's contents.
does just announcing you've changed things really help? you might end up with 30 or 40 people whispering you about what you changed and then you'd have to whisper them back with, theoretically, the same identical message since they presumably all have the same data (since they're running a mod specifically designed to make sure they all have the same data).
it seems to me you should trust your system to be functional and then just broadcast changes (slot#1 is now empty, slot#5 now contains 6x[item], slot #15 now has 15 in the stack, etc). you'd need to have a means to sync when a new client logs in and maybe some way to detect/correct out-of-sync data. perhaps the crc example above would serve this purpose.
You can't broadcast only changes. I've tried this method and it does not work. People never have the same base, which means you can't apply a change set uniformly. In order to ensure valid data the entire tab needs to be serialized and sent to users.
Plus to be honest, it's simpler to handle. I'd rather have more bandwidth and an addon that works reliably than an addon trying to be super super efficient. I've got an addon that tries to be efficient about syncing up during initial logins and it's a pain in the rear.
Maybe you can revisit this if it ends up becoming a real issue.
You can't broadcast only changes. I've tried this method and it does not work. People never have the same base, which means you can't apply a change set uniformly. In order to ensure valid data the entire tab needs to be serialized and sent to users.
where did things go south?
edit: if the fear is missing an update, perhaps there could be a serial number associated per update and maybe the most recent 3 updates could be sent just in case something was missed. or if a client gets an out-of-sync update, it asks for the missing update packets (which would be condensed to a single update).
Man, I am getting confused! Should of taken the blue pill....
http://paste.wowace.com/2052/
Much thanks to Cyprias for the help. Not finished, but a lot closer.
wouldn't it make more sense to just send the slots that have changed?
when you open the frame/change tabs, compare each slot to your internal record of the guild bank info. record any changes in a table (something like bankDelta[#bankDelta+1] = { slotNum = #, tabNum = #, itemString = string, etc }).
when you close the frame, broadcast that data and apply it to your internal bank data.
i would think the only time you need to transmit the entire contents of the bank is when somebody first logs in. form there, it's just a matter of sending the changes.
if you're concerned about going out of sync, you could come up with some kind of checksum that you send as well that would be a way to fall back to a retransmit if somebody loses sync.
$.02
etc... The final variable names may change depending on how I code the scan, but you get the idea. I have purposely used GetGuildBankMoney() to get the funds in raw copper, and left the conversion into higher coins up to authors for localization reasons.
** EDIT **
I realize that GUILDBANK_UPDATE_MONEY() fires even when someone isn't actually at the bank; guild repairs, the possible tithing system Blizzard talked about for Cataclysm.. What I did not want to do is fire off a comm and a callback for that, as those could be updated incredibly frequently. Therefore, I chose to fire the callback and comm on GUILDBANKFRAME_CLOSED() which means lib.guildBank[guildName].money may not be accurate in a timely fashion. Thoughts?
lib.guildBank[guildName].links[page][slot] = "empty"
lib.guildBank[guildName].info[page][slot] = "empty"
you could use
lib.guildBank[guildName].gold = amount
lib.guildBank[guildName].page[page].owned = boolean
lib.guildBank[guildName].page[page].icon = texture
lib.guildBank[guildName].page[page].name = name
lib.guildBank[guildName].page[page].view = view
lib.guildBank[guildName].page[page].slot[slot].link = link
lib.guildBank[guildName].page[page].slot[slot].count = count
it gives you more flexibility in adding data to the tables without running into conflicts and using the minimal amount of tables to hold it.
it also means that when you transmit you can just serialise the page table and send it in one go.
btw, if a tab is hidden from everyone but a specific rank does it still get transmitted to everyone? (if logged on as someone in the rank to read it)
I will try those changes, thank you Arkayenro. And no, I do not intend to send data to those who should not be able to see the bank frame or page; I just haven't solved that riddle yet.
Any thoughts?
I'm guessing it should be:
Anyway. I don't think it's a good idea to whisper everyone in the guild the entire contents of your table when you close the guild bank.
A small bank with 1 page and 20 items would look like this.
http://paste.wowace.com/2872/
Serializing that table would be 707 characters long and be split into 3 messages.
A bank with 6 tabs and 480 items would be near 2676 characters long split into 11 messages.
I would instead send 1 message to guild comm saying I've updated my data and for others to whisper me for updates.
I would also look into making a hash string of each tab and sending that first before sending the whole table. If their hash matches yours then there's no need for them to request updates.
Allara's CRC-32 example
So serialize table > hash function.
So once you close your bank you'd send to guild comm
"HASHUPDATE 11111111,22222222,33333333,44444444,55555555,66666666"
and others would request just the pages that don't match their own. Then when they whisper you, you confirm their rank matches the tab rank and reply with the tab's contents.
it seems to me you should trust your system to be functional and then just broadcast changes (slot#1 is now empty, slot#5 now contains 6x[item], slot #15 now has 15 in the stack, etc). you'd need to have a means to sync when a new client logs in and maybe some way to detect/correct out-of-sync data. perhaps the crc example above would serve this purpose.
Maybe you can revisit this if it ends up becoming a real issue.
where did things go south?
edit: if the fear is missing an update, perhaps there could be a serial number associated per update and maybe the most recent 3 updates could be sent just in case something was missed. or if a client gets an out-of-sync update, it asks for the missing update packets (which would be condensed to a single update).