-
Member
Ahhh ok ill try that, thanks mate. Confusing since IDA is saying that the GUID is a __int64, or is that just the pseudocode being off?, I'm assuming I have to take it with a grain of salt and try to look at the asm a bit more?
https://i.imgur.com/DHEANIi.png
-
Contributor
Originally Posted by
unsigned
Ahhh ok ill try that, thanks mate. Confusing since IDA is saying that the GUID is a __int64, or is that just the pseudocode being off?, I'm assuming I have to take it with a grain of salt and try to look at the asm a bit more?
https://i.imgur.com/DHEANIi.png
If you notice, its a int64*
When it's used in the first spot its val[1] and then second time *val meaning first one is the second int64 (high) and second time the first int64 (low)
The second one could've also just been val[0]. With that info, you can see it's int64 val[2]. Make sense?
-
Post Thanks / Like - 1 Thanks
unsigned (1 members gave Thanks to scizzydo for this useful post)
-
Member
Yep makes sense thanks mate <3
-
Howdy!
Revisiting this for a bit because I've finally got a better understanding of how it works. In the past I've done a one size fits all approach to the OM, and it's worked okay, but it just worked and I didn't question or consider how.
What I know now is that guid hashing is also part of the equation and the other half is being able to write a good custom enumerator using the OM's cur_mgr. I'm looking for a balance of utility, speed, and simplicity. What I did was instead of the limitations of EnumVisibleObjectsPtr, I wrote my own and removed my prior need for control guard and such (mutex/cv). It's possible to let the game do all the freeing and updating, and you just query it in real time. If you want to do the hashmap thing then use it best for single object queries.
The fun comes in when doing collections working in tandem with your callback(s) (and now without any global variable desynchronization just no g_vars at all). If you set this type of thing up you can have super quick single fetches as well as do things like just return the whole collection. If you have an unlocker style setup from there you can further toy around by returning everything in a table. I used to do similar, but it was all desynched. Now I just grab the objects and have things like unit.guid, unit.xyz, unit.name, etc. Makes life ez to just:
Code:
local rabbits = OM("Rabbit")
for idx, values in pairs(rabbits) do
print(idx, values.guid, values.x, values.y, values.z, values.name)
end
I would be happy to share things I discovered over the weekend, but for code that has evolved and struggled over a year or two I can't hand it out. Best of luck to you though, and thanks to this thread for the ideas and suggestions.
-
Been working pretty intently and changing even more up, and finally some results! (From the center of my Garrison)
Timings range from 0.03 milliseconds to 0.3 milliseconds for ~400 objects.
object_timing.png
-
Established Member
Originally Posted by
Glitt
Howdy!
Revisiting this for a bit because I've finally got a better understanding of how it works. In the past I've done a one size fits all approach to the OM, and it's worked okay, but it just worked and I didn't question or consider how.
....
I'm pretty lost trying to understand what you're working on. I haven't looked at EnumVisibleObjectsPtr in a while, but I doubt it has any synchronization.
Just generally in video game development, world updates are always single threaded for physics and networking synchronization.
If I am not mistaken more recent graphic pipelines use multithreading like directx12, which means wnd proc or the internal set timer are needed instead for thread safety.
So if you're bot already has a thread safe execution spot, the object manager should be available and not have any race conditions when querying.
Additionally, for the benchmarks you have below I would suggest checking out filtering by entry id instead of name to remove some confounding variables.
-
My description came a little sooner than completion of the OM, so it's not entirely accurate in the explanation. To simplify, I just have a guard/lock on the dll's OM query function, so that if two scripts were running they wouldn't ever conflict with the globals they now would need to share. I originally eliminated the need for globals using a pointer to a vector, but it made most sense to do the following:
- query everything for "all/many" searches since it's faster than it needs to be by a considerable amount.
- return immediately when doing "single" searches
- make circumstantial callbacks instead of being completely generic e.g. return the player, return matching names, filter by combat range etc.
To further clarify my setup that I'm all giddy over is just a lua c function that is "smart" enough to know if you are searching by guid, unit, or name and that will route to the most appropriate callback. For example on the lua side of it:
Code:
-- single by guid
target = cplusplus("Objects", UnitGUID("target"))
print("Target facing:", cplusplus("Facing", target))
-- many by name
rabbits = {cplusplus("Objects", "Rabbit")}
for i, rabbit in pairs(rabbits) do
print(i, "Rabbit facing:", cplusplus("Facing", rabbit))
end
Last edited by Glitt; 09-05-2023 at 09:45 AM.
Reason: typo