On the EU-Mekkatorque Cata beta realm, I was interested in the Player IDs
So I wrote a quick and messy test addon to get some Player ID data into an array and im a noob btw.
In the picture below:
The upper part is: /dump KethoDatabase.db.profile.test4
The lower part is: /run for key, val in orderedPairs(KethoDatabase.db.profile.test4) do print(key.." = "..val); end
btw thanks sylvanaar for updating prat for cata already
http://www.wowwiki.com/API_UnitGUID Player GUIDs are local on a per-server basis, making the "global" scope to be bound to the specific server. Every time a character is created, a new GUID is assigned from a simple +1 counter and then given to that character.
Question 01: Is it normal there were created over 3.1 million characters on that server?
Even though ppl might make a lot of alts and/or even delete them again, racechanges, and taking into consideration how long that beta server has been up already(4-6 month?)
Question 02: About sorting lua tables/arrays:
I tried table.sort(KethoDatabase.db.profile.test4), but I guess I'm doing that wrong.
So I copied the example function at http://lua-users.org/wiki/SortedIteration and use the following code/macro to call the sorting function which I copied to the test addon: /run for key, val in orderedPairs(KethoDatabase.db.profile.test4) do print(key.." = "..val); end
So Question 02 is: Can a lua array be sorted numerically or can it only be printed out sorted with this "orderedPairs()" function?
Question 01: Is it normal there were created over 3.1 million characters on that server?
Even though ppl might make a lot of alts and/or even delete them again, racechanges, and taking into consideration how long that beta server has been up already(4-6 month?)
They don't necessarily start at 0000.....00001 for the first toon, do they?
So Question 02 is: Can a lua array be sorted numerically or can it only be printed out sorted with this "orderedPairs()" function?
Not if you're using non-numerical keys. It's a hash table, after all. (Or "dictionary" or whatever the cool kids are calling them now.) Rearranging the keys would defeat the whole point of the hash.
What you're doing -- an ancillary table with the numerical keys in whatever order you want, and the values as keys of the original table -- is pretty much the only approach, although there are many variants on the implementation.
2. You can't iterate through a table by keys in such a way that the keys are in sorted order. However, you can use a second array indexed from 1 to N with the values of this table as the keys of the first, sort this one, then access the first table using the sorted keys.
The orderedPairs() essentially does exactly what I described internally, and then gives you back each iteration one by one using the temporary array. Note that the example given that you linked has performance issues.
Specifically, issue number 1 is that if the loop was terminated halfway with a break or return statement, there will be a "memory leak" because t.__orderedIndex = nil was never called to release the memory.
Issue number 2 would be that because a new table is made on every orderedPairs() call, calling it a lot of times very frequently will produce a lot of garbage (if the table is large) to be collected. However, because a new table is made, the function is re-entrant and you can use an orderedPairs() within an orderedPairs().
They don't necessarily start at 0000.....00001 for the first toon, do they?
Not if you're using non-numerical keys. It's a hash table, after all. (Or "dictionary" or whatever the cool kids are calling them now.) Rearranging the keys would defeat the whole point of the hash.
What you're doing -- an ancillary table with the numerical keys in whatever order you want, and the values as keys of the original table -- is pretty much the only approach, although there are many variants on the implementation.
Well, the lowest Player ID I saw was [49361] = "Erniecool", so I kinda believe they start at 1 ...
For the rest, I didn't really understand all that programming terminology since im just noob. But you are saying rearranging it is not how it works and there are variations on how to implement it and this is how it should kinda work right.
Edit: This gonna take me some time to understand your posts (=.=)
Edit2: So I should make another table "with the values of this table as the keys of the first" then sort it, then use the original table with the sorted keys. (so ehm keys are the things on the left, right)
So the function I copied has performance issues ok .. but I didn't really understand that part of Xinhuan's post. I don't know enough yet to comprehend that :(
You can't use pairs(t1) because it would iterate through the 4 entries in a random order.
What you do is create a temporary table, say t2, and fill it up like this
t2[1] = 300
t2[2] = 100
t2[3] = 200
t2[4] = 1000
Then you sort t2 to get:
t2[1] = 100
t2[2] = 200
t2[3] = 300
t2[4] = 1000
Then you loop over t2 from t2[1] to t2[4] and use the value stored to access the values stored in t1 in order. So, the whole code looks like this
local t1 = {}
t1[300] = "ghi"
t1[100] = "xyz"
t1[200] = "abc"
t1[1000] = "def"
-- Create/use a temporary table
local t2 = {}
local i = 1
for k, v in pairs(t1) do
-- Take all the keys of t1[] and put them in t2 as values
t2[i] = k
i = i + 1
end
table.sort(t2)
-- Now print out key = value in sorted order
for i = 1, #t2 do
print("[" .. t2[i] .. "] = " .. t1[t2[i]])
end
The fancy orderedPairs() function you see in the link you provided, is just a much fancier way of doing the exact same thing, and requires you to understand what iterators are.
For the rest, I didn't really understand all that programming terminology since im just noob. But you are saying rearranging it is not how it works and there are variations on how to implement it and this is how it should kinda work right.
Pretty much! For some of the variations, have a look at
I think the code you're already using is based on the "sorted iteration" link on that page, but some of the more popular variations are also there.
Here's a simple example. If I have a table with three string keys, "foo", "bar", and "baz", there's no telling what order they're in behind the scenes. I might write the table like this:
but that doesn't have anything to do with how they're arranged in memory. Lua will sort them internally however Lua feels like sorting them.
If I want to arrange them in some order, I create a second table like this:
T2 = {
1 = "foo",
2 = "bar",
3 = "baz",
}
Now I can rearrange that table however I feel like. In particular, I can use the table.sort() routine, which does an in-place sort according to whatever comparison function I pass in. By default it's just alphabetical:
T2_sorted = {
1 = "bar",
2 = "baz",
3 = "foo",
}
Now if I loop over that table in standard key order (using ipairs or the usual numerical for loop), the values from T2_sorted become the indexes to use into T1, and the result is plucking out entries from T1 in alphabetical order of its keys.
So my understanding of the logic is to make another "temporary" table, that can be sorted (in contrary to table 1), and then use the keys of table 1 as values in table 2.
Thank you very much for your dummy proof explanation :p
(I only learned some Lua by trial and error, going to try learn something from this)
In the end, I only copied Xinhuan's perfectly working code and learned about the "for in loop", "key" and "value"...
I tried to save the sorted table/array again to the AceDB, so I can e.g. see the AceDB in the SavedVariables folder with notepad++ easily without having to sort it in notepad++ manually.
But without much success(keys in the table/array in random order again), so my way of thinking doesn't really work
Codesnip of my _failed_ attempt:
if not self.db.profile.test6 then self.db.profile.test6 = {}; end
for i = 1, #t2 do
print("["..t2[i].."] = ".. KethoDatabase.db.profile.test4[t2[i]])
self.db.profile.test6[t2[i]] = KethoDatabase.db.profile.test4[t2[i]]
end
Anyways concerning the Player ID / UnitGUID:
I made 3 characters in quick succession, without loading them, just creating. Then afterwards loading them. (You can see I reused 1 name "testguida")
I still think the Player ID starts at 1~, but that however the Player ID increases over time.
I think the reasons are that Blizzard assigns UnitGUIDs to players according to time or there are just a lot of characters being created/transferred/racechanged or even a combination of them.
I estimate that almost every second the Player ID increases by 2 to 4 in value. So maybe the idea that 3.1 million characters were created really seems implausible ...
That's over 10 million seconds since the start of F&F alpha. Is 3.1 million characters really that unrealistic? They probably have a lot of internal testing as well done on character copying/transferring from live servers.
That's over 10 million seconds since the start of F&F alpha. Is 3.1 million characters really that unrealistic? They probably have a lot of internal testing as well done on character copying/transferring from live servers.
I had no idea how long the beta realms were up, but neglected to do the math though
That means the GUID really has nothing to do with time then (><)
Of course it doesn't have anything to do with time lol.. What would happen if 100 people created a character at the same time otherwise (say on launch day)?
local t = { --[[ random indices ]] }
for i = 1, table.maxn(t) do
local v = t[i]
if v then
print(i, v)
end
end
Is this very bad in comparison?
I tested your code and it works, but ehh the game freezes for like 3 sec when I call the function.
I think maybe its because it runs 3.2 million iterations(?) before it gets to the end of the array/table because of the for do loop ...
- the UnitGUID in WoW is a 64-bit hexadecimal string. do not use tonumber(). you will get trouble if you do this.
- a WoW UnitGUID looks like: 0x040000000A182FE0
- 0x040 = battlegroup identification (globally unique)
- 000000A182FE0 = character identification (globally unique because of battlegroup identification)
- do not use excessive code execution in COMBAT_LOG*EVENT(s). minimalism rules.
- disable guid scanning/digging/catching in combat!
- simply save the whole UnitGUID and you can sort it easily.
- digging for UnitGUIDs on a test/beta realm is really useless. nearly all characters are created in a very small period of time. if you try to test code for testing purpose, okay, but ptr/beta servers are slow, really very very slow compared to live servers.
- the UnitGUID is definitly date/time based!!! (date/time of character creation! but there is no way to get this info. there is only an estimated date/time based on very large data and (server-based/WoW) experience).
- it's not possible to get a creation date unless you link the UnitGUID with the information someone can see in the account management side (this is the only place where you can see _when_ an account! (not a char!) was created (date only, no time). nobody with brain would allow some external code dig data from the WoW account management side --- or you have a SendAddonMessage() addonbot that sends played time data to you (but played time is not creation date)...).
- UnitGUIDs are incremented exactly by 1. i have catched hundreds of such UnitGUIDs on live servers.
- UnitGUID != BN/RealID. there is currently no way to link these two IDentifiers with the Lua API (which is good and VERY VERY IMPORTANT!!!, and for the sake of privacy concerns hopefully Blizzard will never change this!!!)
- check out GT100GCX aka 'Gnomish Top100 GUID Catcher Xtrem'. the current release version available here at wowace.com can catch up to 1000 UnitGUIDs per server (main purpose of this addon is to get old characters, and well i am currently doing a rewrite). in local tests i tried 5000, 10000 and even 250000(!!!): after digging nearly 1 year with 250000(!!!-one server only) i have not seen that much different UnitGUIDs on my server (and my server is one of the best visited and one of the oldest in europe). conclusion: your number of 3 million UnitGUIDs is not real, even on a ptr/beta server where people from the whole world join. you simply can not dig that much UnitGUIDs in such a short period of (ptr/beta) time. impossible!
- a high or low UnitGUID says nothing without a very large amount of comparable data and server-based experience.
Its been tested before on other PTRs that creating Characters assigns strict ascending IDs. If copying characters or premades follow the same scheme is unclear, however.
- the UnitGUID is definitly date/time based!!! (date/time of character creation! but there is no way to get this info. there is only an estimated date/time based on very large data and (server-based/WoW) experience).
Thats pretty inaccurate. They are numbered sequentially, so while one could argue that the date/time plays a role there, saying "date/time based" implies that the actual date and time take part in calculating the GUID, which is wrong. It doesn't matter if you create a character now, or in one hour. As long as no other player creates one in that time, the GUID will be the same.
I just know that my druid has a pretty low GUID (release day character), and i'm not tranfering it or anything, i want to keep it :p
while we're discussing GUIDs... I see that you can pull GUIDs out of combat logs... and from the code posted it looks like the 12th argument of chat events seem to be GUIDs too (although I can't find it mentioned in documentation... is this new?)
Anyway Q1: if I have a Guid can I look up a player?
Practical example... I have a friend called "John" with a GUID (partial) of 1234567
I would like to check when I log in if name(GUID(1234567)) == "John" and if not then it looks like John has had a namechange. (witness protection?)
I don't mind if it's only run on online characters
Q2: if I have a player can I look up a Guid without waiting for a chat event or combatlog event?
1. If you have a only the GUID, you can't do anything with it. There is no WoW API that takes in a GUID.
2. If you have a player, you can only determine his GUID using the UnitGUID() command with a valid unitID handle (like "party3", "raid34pet", etc), or using the chat events or combat log which also use GUIDs.
It might also be interesting to note that when using private chat channels in WoW, when the current moderator leaves the channel, the next person to get moderator is the person with the lowest GUID.
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
So I wrote a quick and messy test addon to get some Player ID data into an array and im a noob btw.
Paste 2450 (original code)
Paste 2471 (updated snippet)
Question 01: Is it normal there were created over 3.1 million characters on that server?
Even though ppl might make a lot of alts and/or even delete them again, racechanges, and taking into consideration how long that beta server has been up already(4-6 month?)
Question 02: About sorting lua tables/arrays:
I tried table.sort(KethoDatabase.db.profile.test4), but I guess I'm doing that wrong.
So I copied the example function at http://lua-users.org/wiki/SortedIteration and use the following code/macro to call the sorting function which I copied to the test addon:
/run for key, val in orderedPairs(KethoDatabase.db.profile.test4) do print(key.." = "..val); end
So Question 02 is: Can a lua array be sorted numerically or can it only be printed out sorted with this "orderedPairs()" function?
They don't necessarily start at 0000.....00001 for the first toon, do they?
Not if you're using non-numerical keys. It's a hash table, after all. (Or "dictionary" or whatever the cool kids are calling them now.) Rearranging the keys would defeat the whole point of the hash.
What you're doing -- an ancillary table with the numerical keys in whatever order you want, and the values as keys of the original table -- is pretty much the only approach, although there are many variants on the implementation.
2. You can't iterate through a table by keys in such a way that the keys are in sorted order. However, you can use a second array indexed from 1 to N with the values of this table as the keys of the first, sort this one, then access the first table using the sorted keys.
The orderedPairs() essentially does exactly what I described internally, and then gives you back each iteration one by one using the temporary array. Note that the example given that you linked has performance issues.
Specifically, issue number 1 is that if the loop was terminated halfway with a break or return statement, there will be a "memory leak" because t.__orderedIndex = nil was never called to release the memory.
Issue number 2 would be that because a new table is made on every orderedPairs() call, calling it a lot of times very frequently will produce a lot of garbage (if the table is large) to be collected. However, because a new table is made, the function is re-entrant and you can use an orderedPairs() within an orderedPairs().
Well, the lowest Player ID I saw was [49361] = "Erniecool", so I kinda believe they start at 1 ...
For the rest, I didn't really understand all that programming terminology since im just noob. But you are saying rearranging it is not how it works and there are variations on how to implement it and this is how it should kinda work right.
Edit: This gonna take me some time to understand your posts (=.=)
Edit2: So I should make another table "with the values of this table as the keys of the first" then sort it, then use the original table with the sorted keys. (so ehm keys are the things on the left, right)
So the function I copied has performance issues ok .. but I didn't really understand that part of Xinhuan's post. I don't know enough yet to comprehend that :(
t1[300] = "ghi"
t1[100] = "xyz"
t1[200] = "abc"
t1[1000] = "def"
You can't use pairs(t1) because it would iterate through the 4 entries in a random order.
What you do is create a temporary table, say t2, and fill it up like this
t2[1] = 300
t2[2] = 100
t2[3] = 200
t2[4] = 1000
Then you sort t2 to get:
t2[1] = 100
t2[2] = 200
t2[3] = 300
t2[4] = 1000
Then you loop over t2 from t2[1] to t2[4] and use the value stored to access the values stored in t1 in order. So, the whole code looks like this
The fancy orderedPairs() function you see in the link you provided, is just a much fancier way of doing the exact same thing, and requires you to understand what iterators are.
Pretty much! For some of the variations, have a look at
http://lua-users.org/wiki/LuaDirectory
I think the code you're already using is based on the "sorted iteration" link on that page, but some of the more popular variations are also there.
Here's a simple example. If I have a table with three string keys, "foo", "bar", and "baz", there's no telling what order they're in behind the scenes. I might write the table like this:
but that doesn't have anything to do with how they're arranged in memory. Lua will sort them internally however Lua feels like sorting them.
If I want to arrange them in some order, I create a second table like this:
Now I can rearrange that table however I feel like. In particular, I can use the table.sort() routine, which does an in-place sort according to whatever comparison function I pass in. By default it's just alphabetical:
Now if I loop over that table in standard key order (using ipairs or the usual numerical for loop), the values from T2_sorted become the indexes to use into T1, and the result is plucking out entries from T1 in alphabetical order of its keys.
Thank you very much for your dummy proof explanation :p
(I only learned some Lua by trial and error, going to try learn something from this)
Right on the spot (><)
I tried to save the sorted table/array again to the AceDB, so I can e.g. see the AceDB in the SavedVariables folder with notepad++ easily without having to sort it in notepad++ manually.
But without much success(keys in the table/array in random order again), so my way of thinking doesn't really work
Codesnip of my _failed_ attempt:
Anyways concerning the Player ID / UnitGUID:
I made 3 characters in quick succession, without loading them, just creating. Then afterwards loading them. (You can see I reused 1 name "testguida")
I still think the Player ID starts at 1~, but that however the Player ID increases over time.
I think the reasons are that Blizzard assigns UnitGUIDs to players according to time or there are just a lot of characters being created/transferred/racechanged or even a combination of them.
I estimate that almost every second the Player ID increases by 2 to 4 in value. So maybe the idea that 3.1 million characters were created really seems implausible ...
60 seconds * 60 minutes * 24 hours * 120 days = 10 368 000 seconds
That's over 10 million seconds since the start of F&F alpha. Is 3.1 million characters really that unrealistic? They probably have a lot of internal testing as well done on character copying/transferring from live servers.
I had no idea how long the beta realms were up, but neglected to do the math though
That means the GUID really has nothing to do with time then (><)
Is this very bad in comparison?
I tested your code and it works, but ehh the game freezes for like 3 sec when I call the function.
I think maybe its because it runs 3.2 million iterations(?) before it gets to the end of the array/table because of the for do loop ...
some thoughts:
- the UnitGUID in WoW is a 64-bit hexadecimal string. do not use tonumber(). you will get trouble if you do this.
- a WoW UnitGUID looks like: 0x040000000A182FE0
- 0x040 = battlegroup identification (globally unique)
- 000000A182FE0 = character identification (globally unique because of battlegroup identification)
- do not use excessive code execution in COMBAT_LOG*EVENT(s). minimalism rules.
- disable guid scanning/digging/catching in combat!
- simply save the whole UnitGUID and you can sort it easily.
- digging for UnitGUIDs on a test/beta realm is really useless. nearly all characters are created in a very small period of time. if you try to test code for testing purpose, okay, but ptr/beta servers are slow, really very very slow compared to live servers.
- the UnitGUID is definitly date/time based!!! (date/time of character creation! but there is no way to get this info. there is only an estimated date/time based on very large data and (server-based/WoW) experience).
- it's not possible to get a creation date unless you link the UnitGUID with the information someone can see in the account management side (this is the only place where you can see _when_ an account! (not a char!) was created (date only, no time). nobody with brain would allow some external code dig data from the WoW account management side --- or you have a SendAddonMessage() addonbot that sends played time data to you (but played time is not creation date)...).
- UnitGUIDs are incremented exactly by 1. i have catched hundreds of such UnitGUIDs on live servers.
- UnitGUID != BN/RealID. there is currently no way to link these two IDentifiers with the Lua API (which is good and VERY VERY IMPORTANT!!!, and for the sake of privacy concerns hopefully Blizzard will never change this!!!)
- check out GT100GCX aka 'Gnomish Top100 GUID Catcher Xtrem'. the current release version available here at wowace.com can catch up to 1000 UnitGUIDs per server (main purpose of this addon is to get old characters, and well i am currently doing a rewrite). in local tests i tried 5000, 10000 and even 250000(!!!): after digging nearly 1 year with 250000(!!!-one server only) i have not seen that much different UnitGUIDs on my server (and my server is one of the best visited and one of the oldest in europe). conclusion: your number of 3 million UnitGUIDs is not real, even on a ptr/beta server where people from the whole world join. you simply can not dig that much UnitGUIDs in such a short period of (ptr/beta) time. impossible!
- a high or low UnitGUID says nothing without a very large amount of comparable data and server-based experience.
sorry, don't know if this is offtopic or useful
Its been tested before on other PTRs that creating Characters assigns strict ascending IDs. If copying characters or premades follow the same scheme is unclear, however.
Thats pretty inaccurate. They are numbered sequentially, so while one could argue that the date/time plays a role there, saying "date/time based" implies that the actual date and time take part in calculating the GUID, which is wrong. It doesn't matter if you create a character now, or in one hour. As long as no other player creates one in that time, the GUID will be the same.
I just know that my druid has a pretty low GUID (release day character), and i'm not tranfering it or anything, i want to keep it :p
Anyway Q1: if I have a Guid can I look up a player?
Practical example... I have a friend called "John" with a GUID (partial) of 1234567
I would like to check when I log in if name(GUID(1234567)) == "John" and if not then it looks like John has had a namechange. (witness protection?)
I don't mind if it's only run on online characters
Q2: if I have a player can I look up a Guid without waiting for a chat event or combatlog event?
Thanks
Kaz
2. If you have a player, you can only determine his GUID using the UnitGUID() command with a valid unitID handle (like "party3", "raid34pet", etc), or using the chat events or combat log which also use GUIDs.
I think I need to do something hackey to get my idea to work.