From bc83fc1e9f42e960a95b4e9621e5ad16a2e7d924 Mon Sep 17 00:00:00 2001
From: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
Date: Fri, 26 Aug 2022 19:25:48 -0400
Subject: [PATCH] Makes the game start faster by optimizing round-start
manifest injections (#69393)
* Massively optimizes the manifest_inject() proc by relaying the creation of the Security Records pictures to be on-demand
* Implements the change in the Security records and improves the photo's resolution as well
* Implements the change in the Medical records and improves the photo's resolution as well
* Updates the usage of the photos in human code
* Actually makes AI holograms still work with this new change
* Makes the appearance_holder a static variable, to avoid having to re-instanciate it all the time
* Uses the mutable_appearance instead of a static atom/movable/screen
* Less static atom/movable/screen stuff in the AI code too
* Removes my funny comment :(
* Removes some redundant null checks
* Updates the documentation for get_flat_human_icon() and get_flat_existing_human_icon()
* Removes get_id_photo() as it's no longer used
---
code/__HELPERS/icons.dm | 6 +-
code/datums/datacore.dm | 83 +++++++++++++------
code/game/machinery/computer/medical.dm | 34 ++++----
code/game/machinery/computer/security.dm | 58 +++++++------
code/modules/mob/living/carbon/human/human.dm | 4 +-
code/modules/mob/living/silicon/ai/ai.dm | 9 +-
6 files changed, 120 insertions(+), 74 deletions(-)
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index b551f7886b7..6eb9a2e40dc 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -1050,7 +1050,8 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
return J
return 0
-//For creating consistent icons for human looking simple animals
+/// # If you already have a human and need to get its flat icon, call `get_flat_existing_human_icon()` instead.
+/// For creating consistent icons for human looking simple animals.
/proc/get_flat_human_icon(icon_id, datum/job/job, datum/preferences/prefs, dummy_key, showDirs = GLOB.cardinals, outfit_override = null)
var/static/list/humanoid_icon_cache = list()
if(icon_id && humanoid_icon_cache[icon_id])
@@ -1082,7 +1083,8 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
* A simpler version of get_flat_human_icon() that uses an existing human as a base to create the icon.
* Does not feature caching yet, since I could not think of a good way to cache them without having a possibility
* of using the cached version when we don't want to, so only use this proc if you just need this flat icon
- * generated once.
+ * generated once and handle the caching yourself if you need to access that icon multiple times, or
+ * refactor this proc to feature caching of icons.
*
* Arguments:
* * existing_human - The human we want to get a flat icon out of.
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index cc741243d09..46dfadaffc3 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -19,16 +19,61 @@ GLOBAL_DATUM_INIT(data_core, /datum/datacore, new)
var/list/fields = list()
/datum/data/record/Destroy()
- if(src in GLOB.data_core.medical)
- GLOB.data_core.medical -= src
- if(src in GLOB.data_core.security)
- GLOB.data_core.security -= src
- if(src in GLOB.data_core.general)
- GLOB.data_core.general -= src
- if(src in GLOB.data_core.locked)
- GLOB.data_core.locked -= src
+ GLOB.data_core.medical -= src
+ GLOB.data_core.security -= src
+ GLOB.data_core.general -= src
+ GLOB.data_core.locked -= src
. = ..()
+/// A helper proc to get the front photo of a character from the record.
+/// Handles calling `get_photo()`, read its documentation for more information.
+/datum/data/record/proc/get_front_photo()
+ return get_photo("photo_front", SOUTH)
+
+/// A helper proc to get the side photo of a character from the record.
+/// Handles calling `get_photo()`, read its documentation for more information.
+/datum/data/record/proc/get_side_photo()
+ return get_photo("photo_side", WEST)
+
+/**
+ * You shouldn't be calling this directly, use `get_front_photo()` or `get_side_photo()`
+ * instead.
+ *
+ * This is the proc that handles either fetching (if it was already generated before) or
+ * generating (if it wasn't) the specified photo from the specified record. This is only
+ * intended to be used by records that used to try to access `fields["photo_front"]` or
+ * `fields["photo_side"]`, and will return an empty icon if there isn't any of the necessary
+ * fields.
+ *
+ * Arguments:
+ * * field_name - The name of the key in the `fields` list, of the record itself.
+ * * orientation - The direction in which you want the character appearance to be rotated
+ * in the outputed photo.
+ *
+ * Returns an empty `/icon` if there was no `character_appearance` entry in the `fields` list,
+ * returns the generated/cached photo otherwise.
+ */
+/datum/data/record/proc/get_photo(field_name, orientation)
+ if(fields[field_name])
+ return fields[field_name]
+
+ if(!fields["character_appearance"])
+ return new /icon()
+
+ var/mutable_appearance/character_appearance = fields["character_appearance"]
+ character_appearance.setDir(orientation)
+
+ var/icon/picture_image = getFlatIcon(character_appearance)
+
+ var/datum/picture/picture = new
+ picture.picture_name = "[fields["name"]]"
+ picture.picture_desc = "This is [fields["name"]]."
+ picture.picture_image = picture_image
+
+ var/obj/item/photo/photo = new(null, picture)
+ fields[field_name] = photo
+ return photo
+
/datum/data/crime
name = "crime"
var/crimeName = ""
@@ -223,17 +268,9 @@ GLOBAL_DATUM_INIT(data_core, /datum/datacore, new)
var/static/record_id_num = 1001
var/id = num2hex(record_id_num++,6)
- var/image = get_id_photo(H, show_directions)
- var/datum/picture/pf = new
- var/datum/picture/ps = new
- pf.picture_name = "[H]"
- ps.picture_name = "[H]"
- pf.picture_desc = "This is [H]."
- ps.picture_desc = "This is [H]."
- pf.picture_image = icon(image, dir = SOUTH)
- ps.picture_image = icon(image, dir = WEST)
- var/obj/item/photo/photo_front = new(null, pf)
- var/obj/item/photo/photo_side = new(null, ps)
+ // We need to compile the overlays now, otherwise we're basically copying an empty icon.
+ COMPILE_OVERLAYS(H)
+ var/mutable_appearance/character_appearance = new(H.appearance)
//These records should ~really~ be merged or something
//General Record
@@ -255,8 +292,7 @@ GLOBAL_DATUM_INIT(data_core, /datum/datacore, new)
G.fields["gender"] = "Female"
else
G.fields["gender"] = "Other"
- G.fields["photo_front"] = photo_front
- G.fields["photo_side"] = photo_side
+ G.fields["character_appearance"] = character_appearance
general += G
//Medical Record
@@ -305,14 +341,11 @@ GLOBAL_DATUM_INIT(data_core, /datum/datacore, new)
L.fields["identity"] = H.dna.unique_identity
L.fields["species"] = H.dna.species.type
L.fields["features"] = H.dna.features
- L.fields["image"] = image
+ L.fields["character_appearance"] = character_appearance
L.fields["mindref"] = H.mind
locked += L
return
-/datum/datacore/proc/get_id_photo(mob/living/carbon/human/human, show_directions = list(SOUTH))
- return get_flat_existing_human_icon(human, show_directions)
-
//Todo: Add citations to the prinout - you get them from sec record's "citation" field, same as "crim" (which is frankly a terrible fucking field name)
///Standardized printed records. SPRs. Like SATs but for bad guys who probably didn't actually finish school. Input the records and out comes a paper.
/proc/print_security_record(datum/data/record/general_data, datum/data/record/security, atom/location)
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 2776ecf6eff..51fbfd512f3 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -96,15 +96,17 @@
dat += "
| Medical Record |
"
if(active1 in GLOB.data_core.general)
- if(istype(active1.fields["photo_front"], /obj/item/photo))
- var/obj/item/photo/P1 = active1.fields["photo_front"]
- user << browse_rsc(P1.picture.picture_image, "photo_front")
- if(istype(active1.fields["photo_side"], /obj/item/photo))
- var/obj/item/photo/P2 = active1.fields["photo_side"]
- user << browse_rsc(P2.picture.picture_image, "photo_side")
+ var/front_photo = active1.get_front_photo()
+ if(istype(front_photo, /obj/item/photo))
+ var/obj/item/photo/photo_front = front_photo
+ user << browse_rsc(photo_front.picture.picture_image, "photo_front")
+ var/side_photo = active1.get_side_photo()
+ if(istype(side_photo, /obj/item/photo))
+ var/obj/item/photo/photo_side = side_photo
+ user << browse_rsc(photo_side.picture.picture_image, "photo_side")
dat += "| Name: | [active1.fields["name"]] | "
- dat += " | "
- dat += " |
"
+ dat += " | "
+ dat += " | "
dat += "| ID: | [active1.fields["id"]] |
"
dat += "| Gender: | [active1.fields["gender"]] |
"
dat += "| Age: | [active1.fields["age"]] |
"
@@ -370,16 +372,16 @@
active2.fields["b_dna"] = t1
if("show_photo_front")
if(active1)
- if(active1.fields["photo_front"])
- if(istype(active1.fields["photo_front"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_front"]
- P.show(usr)
+ var/front_photo = active1.get_front_photo()
+ if(istype(front_photo, /obj/item/photo))
+ var/obj/item/photo/photo = front_photo
+ photo.show(usr)
if("show_photo_side")
if(active1)
- if(active1.fields["photo_side"])
- if(istype(active1.fields["photo_side"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_side"]
- P.show(usr)
+ var/side_photo = active1.get_side_photo()
+ if(istype(side_photo, /obj/item/photo))
+ var/obj/item/photo/photo = side_photo
+ photo.show(usr)
else
else if(href_list["p_stat"])
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 14bc3569161..aa9bf03d9c7 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -336,12 +336,14 @@
if(3)
dat += "Security Record
"
if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1))
- if(istype(active1.fields["photo_front"], /obj/item/photo))
- var/obj/item/photo/P1 = active1.fields["photo_front"]
- user << browse_rsc(P1.picture.picture_image, "photo_front")
- if(istype(active1.fields["photo_side"], /obj/item/photo))
- var/obj/item/photo/P2 = active1.fields["photo_side"]
- user << browse_rsc(P2.picture.picture_image, "photo_side")
+ var/front_photo = active1.get_front_photo()
+ if(istype(front_photo, /obj/item/photo))
+ var/obj/item/photo/photo_front = front_photo
+ user << browse_rsc(photo_front.picture.picture_image, "photo_front")
+ var/side_photo = active1.get_side_photo()
+ if(istype(side_photo, /obj/item/photo))
+ var/obj/item/photo/photo_side = side_photo
+ user << browse_rsc(photo_side.picture.picture_image, "photo_side")
dat += {" |
- 
+ |
|
|
"}
@@ -574,7 +576,7 @@ What a mess.*/
printing = 1
sleep(30)
if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))//make sure the record still exists.
- var/obj/item/photo/photo = active1.fields["photo_front"]
+ var/obj/item/photo/photo = active1.get_front_photo()
new /obj/item/poster/wanted(loc, photo.picture.picture_image, wanted_name, info, headerText)
printing = 0
if("Print Missing")
@@ -591,7 +593,7 @@ What a mess.*/
printing = 1
sleep(30)
if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))//make sure the record still exists.
- var/obj/item/photo/photo = active1.fields["photo_front"]
+ var/obj/item/photo/photo = active1.get_front_photo()
new /obj/item/poster/wanted/missing(loc, photo.picture.picture_image, missing_name, info, headerText)
printing = 0
@@ -754,10 +756,11 @@ What a mess.*/
return
active1.fields["species"] = t1
if("show_photo_front")
- if(active1.fields["photo_front"])
- if(istype(active1.fields["photo_front"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_front"]
- P.show(usr)
+ if(active1)
+ var/front_photo = active1.get_front_photo()
+ if(istype(front_photo, /obj/item/photo))
+ var/obj/item/photo/photo = front_photo
+ photo.show(usr)
if("upd_photo_front")
var/obj/item/photo/photo = get_photo(usr)
if(photo)
@@ -771,15 +774,17 @@ What a mess.*/
I.Crop(dw/2, dh/2, w - dw/2, h - dh/2)
active1.fields["photo_front"] = photo
if("print_photo_front")
- if(active1.fields["photo_front"])
- if(istype(active1.fields["photo_front"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_front"]
- print_photo(P.picture.picture_image, active1.fields["name"])
+ if(active1)
+ var/front_photo = active1.get_front_photo()
+ if(istype(front_photo, /obj/item/photo))
+ var/obj/item/photo/photo_front = front_photo
+ print_photo(photo_front.picture.picture_image, active1.fields["name"])
if("show_photo_side")
- if(active1.fields["photo_side"])
- if(istype(active1.fields["photo_side"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_side"]
- P.show(usr)
+ if(active1)
+ var/side_photo = active1.get_side_photo()
+ if(istype(side_photo, /obj/item/photo))
+ var/obj/item/photo/photo = side_photo
+ photo.show(usr)
if("upd_photo_side")
var/obj/item/photo/photo = get_photo(usr)
if(photo)
@@ -793,10 +798,11 @@ What a mess.*/
I.Crop(dw/2, dh/2, w - dw/2, h - dh/2)
active1.fields["photo_side"] = photo
if("print_photo_side")
- if(active1.fields["photo_side"])
- if(istype(active1.fields["photo_side"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_side"]
- print_photo(P.picture.picture_image, active1.fields["name"])
+ if(active1)
+ var/side_photo = active1.get_side_photo()
+ if(istype(side_photo, /obj/item/photo))
+ var/obj/item/photo/photo_side = side_photo
+ print_photo(photo_side.picture.picture_image, active1.fields["name"])
if("crim_add")
if(istype(active1, /datum/data/record))
var/t1 = tgui_input_text(usr, "Input crime names", "Security Records")
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 16b9d2eff50..214320d2c09 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -136,9 +136,9 @@
return
var/obj/item/photo/photo_from_record = null
if(href_list["photo_front"])
- photo_from_record = target_record.fields["photo_front"]
+ photo_from_record = target_record.get_front_photo()
else if(href_list["photo_side"])
- photo_from_record = target_record.fields["photo_side"]
+ photo_from_record = target_record.get_side_photo()
if(photo_from_record)
photo_from_record.show(human_user)
return
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index b3cfe93d9a1..2c3a74c49d7 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -660,7 +660,7 @@
var/list/personnel_list = list()
for(var/datum/data/record/record_datum in GLOB.data_core.locked)//Look in data core locked.
- personnel_list["[record_datum.fields["name"]]: [record_datum.fields["rank"]]"] = record_datum.fields["image"]//Pull names, rank, and image.
+ personnel_list["[record_datum.fields["name"]]: [record_datum.fields["rank"]]"] = record_datum.fields["character_appearance"]//Pull names, rank, and image.
if(!length(personnel_list))
tgui_alert(usr,"No suitable records found. Aborting.")
@@ -670,10 +670,13 @@
return
if(isnull(personnel_list[input]))
return
- var/icon/character_icon = personnel_list[input]
+ var/mutable_appearance/character_icon = personnel_list[input]
if(character_icon)
qdel(holo_icon)//Clear old icon so we're not storing it in memory.
- holo_icon = getHologramIcon(icon(character_icon))
+ character_icon.setDir(SOUTH)
+
+ var/icon/icon_for_holo = getFlatIcon(character_icon)
+ holo_icon = getHologramIcon(icon(icon_for_holo))
if("My Character")
switch(tgui_alert(usr,"WARNING: Your AI hologram will take the appearance of your currently selected character ([usr.client.prefs?.read_preference(/datum/preference/name/real_name)]). Are you sure you want to proceed?", "Customize", list("Yes","No")))