So, as many will know, there is an issue in A2Epoch (possibily from DayZ) in the unique identifier generation not always producing unique identifiers.
What is the unique identifier and how is it used ?.
Epoch uses two object identifiers.
ObjectID
ObjectUID
ObjectID is generated by the MySQL DB backend. ObjectUID is generated within the ARMA 2 game world via SQF code.
Why two identifiers ?.
For some reason... there is only one HiveExt.dll call to get the ObjectID for an object in the DB. This call is the one used to load all the DB objects in to ARMA. The offshoot of this is that when a new object is created and saved to the DB, the DB creates a unique objectID but this objectID cannot get back to the ARMA 2 game world until the ARMA 2 server process is restarted and all the objects are then read from the DB again.
To get around this, the ObjectUID is created when a new object is created in the game world. This is used to reference the object in the game world and on the DB if the ARMA 2 engine does not know the DB assigned ObjectID.
So, what is the problem ?.
Whilst the code to generate a unique objectUID looks fairly good, it does not always create a unique ID. THis means that manipulation of any new objects that have not yet got an objectID in the game world (ie. created after the last server restart) but having an objectUID that matches the objectUID of an object currently in the DB will cause all sorts of problems.
How is the objectUID calculated currently ?.
There are three functions used to calculate the objectUID currently (all defined in server_functions.sqf).
dayz_objectUID - No longer used it seems.
dayz_objectUID2 - Used for objects objectUID generation.
dayz_objectUID3 - Used for vehicle objectUID generation.
dayz_objectUID just works out the required input parameters and then calls dayz_objectUID2.
dayz_objectUID2 generates the objectUID for the object by applying the following calculation.
x,y,z coords each multiplied by 10.
Results made positive if required by multiplying by -10 and rounded to a whole number.
3 numbers are concatenated together (X + Y + Z).
The objects direction (in degrees) after rounding is then concatenated to the result.
dayz_objectUID3 does the same but adds the mission time (time in seconds since the ARMA 2 mission was started) to the direction value before adding it to the result for the x/y/x/ * 10 part.
A set of coodinates ( [dir,[x,y,z]] ) for an object of [0,[1,1,10]] will produce the same result as a set of coordinates of [0,[1,10,1]]. The uniqueness plays on the probability of combination resulting in the same onjectUID being generated as unlikely. The more items you have in your DB then the more likely it is to happen.
Ok, so what can we do about it ?.
So this is the purpose of this thread. Both to highlight the issues to those who were not aware and to have a discussion on peoples thoughts on a better solution.
I am curious as to why the code does not start at 0 and each time a objectUID is needed it just increments (possibly by 2 / 5 / 10). A server global variable could hold the current value and be populated on server restart by the highest objectUID found in the loaded objects. The only issue I can see is if multiple requests for a new objectUID resulted in the same objectUIDs being given out to multiple requestors as the global 'current objectUID' variable cannot be updated quickly enough. Presumabily that ould be managed by a basic schedualing system enforcing a FIFO queue so each request could be processed one at a time.
Any other thoughts or observations ?. I am hoping we can all come up with a better solution that does not require any custom .dlls or DB table changes. Good news is that any new generation system should be pretty easy to plugin to Epoch.
Question
RimBlock
So, as many will know, there is an issue in A2Epoch (possibily from DayZ) in the unique identifier generation not always producing unique identifiers.
What is the unique identifier and how is it used ?.
Epoch uses two object identifiers.
ObjectID is generated by the MySQL DB backend. ObjectUID is generated within the ARMA 2 game world via SQF code.
Why two identifiers ?.
For some reason... there is only one HiveExt.dll call to get the ObjectID for an object in the DB. This call is the one used to load all the DB objects in to ARMA. The offshoot of this is that when a new object is created and saved to the DB, the DB creates a unique objectID but this objectID cannot get back to the ARMA 2 game world until the ARMA 2 server process is restarted and all the objects are then read from the DB again.
To get around this, the ObjectUID is created when a new object is created in the game world. This is used to reference the object in the game world and on the DB if the ARMA 2 engine does not know the DB assigned ObjectID.
So, what is the problem ?.
Whilst the code to generate a unique objectUID looks fairly good, it does not always create a unique ID. THis means that manipulation of any new objects that have not yet got an objectID in the game world (ie. created after the last server restart) but having an objectUID that matches the objectUID of an object currently in the DB will cause all sorts of problems.
How is the objectUID calculated currently ?.
There are three functions used to calculate the objectUID currently (all defined in server_functions.sqf).
dayz_objectUID just works out the required input parameters and then calls dayz_objectUID2.
dayz_objectUID2 generates the objectUID for the object by applying the following calculation.
dayz_objectUID3 does the same but adds the mission time (time in seconds since the ARMA 2 mission was started) to the direction value before adding it to the result for the x/y/x/ * 10 part.
Worked example for dayz_objectUID2
Worldspace = [351.545[11079.8,11834.3,-0.380997]]
=
X = 11079.8 * 10 = 110798
Y = 11834.3 * 10 = 118343
Z = -0.380997 * 10 = -3.80997 * -10 (make positive) = 38.0997 round = 38
DIR = 351.545 rounded = 352
= concat 110798 + 118343 + 38 + 352
Calculated objectUID
11079811834338352
Stored ObjectUID
11079811834338352
So why is it not random ?.
A set of coodinates ( [dir,[x,y,z]] ) for an object of [0,[1,1,10]] will produce the same result as a set of coordinates of [0,[1,10,1]]. The uniqueness plays on the probability of combination resulting in the same onjectUID being generated as unlikely. The more items you have in your DB then the more likely it is to happen.
Ok, so what can we do about it ?.
So this is the purpose of this thread. Both to highlight the issues to those who were not aware and to have a discussion on peoples thoughts on a better solution.
I am curious as to why the code does not start at 0 and each time a objectUID is needed it just increments (possibly by 2 / 5 / 10). A server global variable could hold the current value and be populated on server restart by the highest objectUID found in the loaded objects. The only issue I can see is if multiple requests for a new objectUID resulted in the same objectUIDs being given out to multiple requestors as the global 'current objectUID' variable cannot be updated quickly enough. Presumabily that ould be managed by a basic schedualing system enforcing a FIFO queue so each request could be processed one at a time.
Any other thoughts or observations ?. I am hoping we can all come up with a better solution that does not require any custom .dlls or DB table changes. Good news is that any new generation system should be pretty easy to plugin to Epoch.
Over to you...
Link to comment
Share on other sites
9 answers to this question
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now