• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

lua and unit data

Status
Not open for further replies.
Level 17
Joined
Apr 27, 2008
Messages
2,455
With lua, i suppose you're still using an unit indexer ?
and this custom unit value as a key of a list(s), where you can store other data ?

I wanted a native way in lua to detect when an unit is removed with weak tables and __gc method, but then i realized garbage collector isn't instant and because of the nature of an unit it wouldn't work anyway. (it might be no reference left to it, that doesn't mean you can't ref it again later :GroupEnum, nor that the unit should be destroyed :p)

Of course if you control the whole units lifes in script the unit indexer doesn't need any "custom" way to detect when an unit is removed of the game.
 
You don't really need a unit indexer to store data about units since arrays (tables, in Lua) aren't limited to 8192 (or 32k) indices anymore. You can even use the unit handle or handle ID as the key directly, however you can't iterate over them without desyncing. In Lua, handle IDs are not in sync and handles have different addresses between clients.

As far as detecting when a unit leaves the map, I believe the best solution is still to detect the undefend order.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
You don't really need a unit indexer to store data about units since arrays (tables, in Lua) aren't limited to 8192 (or 32k) indices anymore
. You can even use the unit handle or handle ID as the key directly, however you can't iterate over them without desyncing. In Lua, handle IDs are not in sync and handles have different addresses between clients.

As far as detecting when a unit leaves the map, I believe the best solution is still to detect the undefend order.

See, i had to ask, i didn't expected handles id not being synced lol.
And for the unit indexer it was more about unit removal detection and memory cleaning after that.

code id is not synced neither (functions) ?
Only agent type is ?

Well, agent extends handle, i thought it was the opposite from my old memory.
Their id are not in sync neither ?

I remember reading somewhere pairs function was async, i understand know why, it's not pairs by itself (or maybe it is too), but the input is not the same for every player, unless it's specific synced type as key.

But what is sync or async ?
 
Last edited:
code id is not synced neither (functions) ?

I don't think Lua has any concept of the code type.

Only agent type is ?
Well, agent extends handle, i thought it was the opposite from my old memory.
Their id are not in sync neither ?

Any agent/handle may return different handle IDs between clients. I don't think anyone really expected this behavior and I had to find out the hard way by debugging desyncs.

I remember reading somewhere pairs function was async, i understand know why, it's not pairs by itself (or maybe it is too), but the input is not the same for every player, unless it's specific synced type as key.

But what is sync or async ?

pairs iteration order is undefined. The order can differ between clients. If you rely on the correct order you can use ipairs or your own pairs function (lua-users wiki: Sorted Iteration). There's even a one line minified version that you can paste into your script in order iterate in order with pairs.

Lua:
_10=pairs function _1(_6)local _2={}for _4 in _10(_6)do table.insert(_2,_4)end table.sort(_2)return _2 end function _3(_6,_5)if _5==nil then _6._7=_1(_6)_4=_6._7[1]return _4,_6[_4]end _4=nil for _8 = 1,table.getn(_6._7)do if _6._7[_8]==_5 then _4=_6._7[_8+1]end end if _4 then return _4,_6[_4]end _6._7=nil return end function _9(_6)return _3,_6,nil end pairs=_9
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
hmm i don't see how sorting a different set of keys for each players would make the pairs sync safe.
or maybe you were just mentioning this method.
hopefully when values are sync it's easy to sort by value, using an other table

Lua:
t1[key1]=syncvalue1
t2[syncvalue1]=key1

well, if only values are all different though

btw getn n and setn no longer exist in lua 5.3 for tables, only the length operator #
i suppose you must have a key such as "n" if you want a custom size(a size different than the biggest index before a nil value), instead of d, or use a metatable, or a function, whatever
 
Last edited:
Level 9
Joined
Mar 26, 2017
Messages
376
Any agent/handle may return different handle IDs between clients. I don't think anyone really expected this behavior and I had to find out the hard way by debugging desyncs.

If I may ask ITT, what was the reason for desyncs with different handle ID's in your map?
As long as the hande ID number has no meaning (like for sorting), it should not be a problem as long as the Handle ID for a client consistently refers to the same object?

Because I don't want to find out the hard way, I'm curious if you would expect whether these systems could cause problems:
1) For an implementation to recycle timers I have a table 'TimerList' which stores timer handles as a key, with value true. As soon as a timer runs out, instead of destroying, I add it to the TimerList. In order to fetch a timer from the TimerList, I call next(TimerList), which retrieves one key (timer handle) from the TimerList in an arbitrary order.

2) For unit indexing, I have two tables 'UnitGroup' and 'UnitData'. If a unit is created, it uses the length # operator to determine the first unused key integer (id), and then sets UnitGroup[id] = unit handle and UnitData[unit handle] = id. On death, the unit id can be retrieved with the UnitData table, by using the unit handle as a key. Then the unit is cleaned up from both tables.
 
Its totally safe in some cases but not in others. For example, iterating a table with pairs and creating new handles or issuing orders based on the data in that table can cause the each client to perform actions out of order.

I misspoke when saying you cant iterate at all.

In my case specifically, i was syncing the handle ID of the BlzGetMouseFocus unit in order to create a custom OnClick event for units without actually selecting them.
 
Last edited:
My map desynced because of different HandleIds. As soon any trigger run there was a desync. But that was because my map iterated a table filled with functions. Each saved under their own Lua id, which is kinda random for the iteration. The functions created triggers, triggeractions and events. Therefore they had different handleIds and desynced.

I am not convinced that in Lua warcraft 3 HandleId does not match on default. If that is not the case in your map, it should have a reason in the maps code like in my example.
 
Level 9
Joined
Mar 26, 2017
Messages
376
That's good to know.

I was previously under the impression that only things like pairs iteration + break/return could be dangerous. For instance if it modified unit state of a different unit over clients.

I'm now making a form of AI that periodically iterates over a Unit Group with pairs (as a lua table), and then order the units to attackmove to a specific point. Even though all units get the same order at the same game clock timestamp, the orders are not issued in the exact same sequence. I will be wary of desync for this implementation.
 
Status
Not open for further replies.
Top