/
unique_ids.dm
90 lines (74 loc) · 2.64 KB
/
unique_ids.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Unique Datum Identifiers
// Basically, a replacement for plain \refs that ensure the reference still
// points to the exact same datum/client, but doesn't prevent GC like tags do.
// An unintended side effect of the way UIDs are formatted is that the locate()
// proc will ignore the number and attempt to locate the reference. I consider
// this a feature, since it means they're conveniently backwards compatible.
// Turns this:
// var/myref = "\ref[mydatum]"
// var/datum/D = locate(myref)
// into this:
// var/myUID = mydatum.UID()
// var/datum/D = locateUID(myUID)
/// The next UID to be used (Increments by 1 for each UID)
GLOBAL_VAR_INIT(next_unique_datum_id, 1)
/// Log of all UIDs created in the round. Assoc list with type as key and amount as value
GLOBAL_LIST_EMPTY(uid_log)
/**
* Gets or creates the UID of a datum
*
* BYOND refs are recycled, so this system prevents that. If a datum does not have a UID when this proc is ran, one will be created
* Returns the UID of the datum
*/
/datum/proc/UID()
if(!unique_datum_id)
var/tag_backup = tag
tag = null // Grab the raw ref, not the tag
// num2text can output 8 significant figures max. If we go above 10 million UIDs in a round, shit breaks
unique_datum_id = "\ref[src]_[num2text(GLOB.next_unique_datum_id++, 8)]"
tag = tag_backup
GLOB.uid_log[type]++
return unique_datum_id
/**
* Locates a datum based off of the UID
*
* Replacement for locate() which takes a UID instead of a ref
* Returns the datum, if found
*/
/proc/locateUID(uid)
if(!istext(uid))
return null
var/splitat = findlasttext(uid, "_")
if(!splitat)
return null
var/datum/D = locate(copytext(uid, 1, splitat))
if(D && D.unique_datum_id == uid)
return D
return null
/**
* If the list `L` contains a datum UID who's type matches `D`'s type, returns the UID of that datum in the list. Otherwise returns null.
*/
/proc/is_type_in_UID_list(datum/D, list/L)
if(!length(L))
return
for(var/datum_UID in L)
var/datum/A = locateUID(datum_UID)
if(istype(D, A))
return datum_UID
/**
* Opens a log of UIDs
*
* In-round ability to view what has created a UID, and how many times a UID for that path has been declared
*/
/client/proc/uid_log()
set name = "View UID Log"
set category = "Debug"
set desc = "Shows the log of created UIDs this round"
if(!check_rights(R_DEBUG))
return
var/list/sorted = sortTim(GLOB.uid_log, GLOBAL_PROC_REF(cmp_numeric_dsc), TRUE)
var/list/text = list("<h1>UID Log</h1>", "<p>Current UID: [GLOB.next_unique_datum_id]</p>", "<ul>")
for(var/key in sorted)
text += "<li>[key] - [sorted[key]]</li>"
text += "</ul>"
usr << browse(text.Join(), "window=uidlog")