Begin, the Lag Wars Have (#21839)

<img width="700" height="848" alt="image"
src="https://github.com/user-attachments/assets/e0db50af-35db-43c7-b78e-6c1ea5ac569c"
/>

you take a tiny little two year LOA and this happens
this PR hits some large lag culprits:
- UpdateOverlays() getting spammed by human/update_icon. This was 0.85%
of server CPU time during the event. Doesn't sound like a whole lot but
it's insane. 99% of it was caused by sloppy duplicate calls of
update_icon in set_dir (as well as update icon itself!). Refactored to
stop that
- Makes Follow menu update manually, which cuts down on the 2.8 million
REF() calls it made during the event. This was ~1% of CPU time including
ui_data as well.
- Gets rid of a bunch of random runtimes and some lighting-related
harddels.
- NanoUIs now clean themselves up when their owner qdels rather than
forcing the owner to do REF(src) and close all matching UIs. saves us
~0.1% server cpu time! wowza!
This commit is contained in:
Wildkins
2026-02-09 18:20:48 -05:00
committed by GitHub
parent 6ad39a46f7
commit 3d183d7262
19 changed files with 103 additions and 80 deletions
+3 -3
View File
@@ -132,13 +132,12 @@
set category = "Ghost"
set desc = "Follow and haunt a mob."
var/datum/tgui_module/follow_menu/GM = new /datum/tgui_module/follow_menu(usr)
GM.ui_interact(usr)
GLOB.follow_menu.ui_interact(src)
// This is the ghost's follow verb with an argument
/mob/abstract/ghost/proc/ManualFollow(var/atom/movable/target)
if(!target)
return
return FALSE
//Stops orbit if there's any; TG doesn't do this, but if you don't it breaks the orbiting reference
//if you are jumping from one mob to another, hence why we're doing it here
@@ -154,6 +153,7 @@
to_chat(src, SPAN_NOTICE("Now following \the <b>[target]</b>."))
update_sight()
return TRUE
/mob/abstract/ghost/proc/update_sight()
//if they are on a restricted level, then set the ghost vision for them.
@@ -109,9 +109,9 @@
var/datum/sprite_accessory/hair/hair = GLOB.hair_styles_list[h_style]
var/datum/sprite_accessory/facial_hair/facial = GLOB.facial_hair_styles_list[f_style]
if(!facial.keep_as_skeleton && f_style)
if(facial && !facial.keep_as_skeleton)
f_style = "Shaved"
if(!hair.keep_as_skeleton && h_style)
if(hair && !hair.keep_as_skeleton)
h_style = "Bald"
update_hair(0)
@@ -1466,7 +1466,7 @@
self = 1
if ((src.species.flags & NO_BLOOD) || (status_flags & FAKEDEATH))
to_chat(usr, SPAN_WARNING(self ? "You have no pulse." : "[src] has no pulse!"))
to_chat(usr, SPAN_WARNING("[self ? "You have" : "[src] has"] no pulse!"))
return
if(!self)
@@ -38,7 +38,6 @@
var/size_multiplier = 1 //multiplier for the mob's icon size
var/damage_multiplier = 1 //multiplies melee combat damage
var/icon_update = 1 //whether icon updating shall take place
var/default_lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
@@ -122,9 +122,9 @@
/mob/living/carbon/human/set_dir(var/new_dir, ignore_facing_dir = FALSE)
. = ..()
if(. && tail_style)
update_tail_showing(1)
update_tail_showing(!lying)
if(lying)
update_icon(forceDirUpdate = TRUE)
update_icon(TRUE)
/mob/living/carbon/human/Move()
. = ..()
@@ -995,7 +995,9 @@
/datum/species/proc/handle_stance_damage(var/mob/living/carbon/human/H, var/damage_only = FALSE)
var/static/support_limbs = list(
BP_L_LEG = BP_R_LEG,
BP_L_FOOT = BP_R_FOOT
BP_L_FOOT = BP_R_FOOT,
BP_R_LEG = BP_L_LEG,
BP_R_FOOT = BP_L_FOOT
)
var/has_opposite_limb = FALSE
@@ -104,26 +104,29 @@ There are several things that need to be remembered:
var/list/overlays_raw[TOTAL_LAYERS] // Our set of "raw" overlays that can be modified, but cannot be directly applied to the mob without preprocessing.
var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed
#define UPDATE_ICON_IGNORE_DIRECTION_UPDATE -1
// Updates overlays from overlays_raw.
/mob/living/carbon/human/update_icon(var/forceDirUpdate = FALSE)
if (QDELETED(src))
return // No point.
var/update_lying = (lying_prev != lying) || forceDirUpdate || size_multiplier != 1
var/draw_specific_icon = (!lying || species.prone_icon)
if(update_lying && draw_specific_icon)
update_inv_l_hand(FALSE)
update_inv_r_hand(FALSE)
update_hud() //TODO: remove the need for this
ClearOverlays()
if(cloaked)
icon = 'icons/mob/human.dmi'
icon_state = "body_cloaked"
AddOverlays(list(overlays_raw[L_HAND_LAYER], overlays_raw[R_HAND_LAYER]))
else if (icon_update)
SetOverlays(list(overlays_raw[L_HAND_LAYER], overlays_raw[R_HAND_LAYER]))
else
var/list/ovr = list()
if (icon != stand_icon)
icon = stand_icon
var/list/ovr = list()
// We manually add each element instead of just using Copy() so that lists are appended instead of inserted.
for (var/item in overlays_raw)
if (item)
@@ -137,18 +140,20 @@ There are several things that need to be remembered:
var/icon/aura_overlay = icon(A.icon, icon_state = A.icon_state)
ovr += aura_overlay
AddOverlays(ovr)
if (((lying_prev != lying) || forceDirUpdate || size_multiplier != 1) && forceDirUpdate != UPDATE_ICON_IGNORE_DIRECTION_UPDATE)
if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone.
var/matrix/M = matrix()
SetOverlays(ovr)
if(update_lying) //Only rotate them if we're not drawing a specific icon for being prone.
var/matrix/M = matrix()
M.Scale(size_multiplier)
if(draw_specific_icon)
M.Translate(0, 16*(size_multiplier-1))
animate(src, transform = M, time = ANIM_LYING_TIME)
else
switch(src.dir)
if(SOUTH,EAST)
M.Turn(90)
else
M.Turn(-90)
M.Scale(size_multiplier)
M.Translate(1,-6)
animate(src, transform = M, time = (forceDirUpdate ? 0 : ANIM_LYING_TIME))
@@ -157,15 +162,6 @@ There are several things that need to be remembered:
if(istype(src.r_hand, /obj/item/gun) && lying)
HeldObjectDirTransform(slot_r_hand, src.dir)
else
update_inv_l_hand(FALSE)
update_inv_r_hand(FALSE)
update_icon(UPDATE_ICON_IGNORE_DIRECTION_UPDATE)
var/matrix/M = matrix()
M.Scale(size_multiplier)
M.Translate(0, 16*(size_multiplier-1))
animate(src, transform = M, time = ANIM_LYING_TIME)
UpdateOverlays()
lying_prev = lying
@@ -196,9 +192,7 @@ There are several things that need to be remembered:
animate(item_image, transform = item_transform)
overlays_raw[layer] = item_image
update_icon(UPDATE_ICON_IGNORE_DIRECTION_UPDATE)
#undef UPDATE_ICON_IGNORE_DIRECTION_UPDATE
update_icon()
//DAMAGE OVERLAYS
//constructs damage icon for each organ from mask * damage field and saves it in our overlays_raw list (as a list of icons).
@@ -1245,7 +1239,7 @@ There are several things that need to be remembered:
overlays_raw[L_HAND_LAYER] = null
if(update_icons)
update_icon(forceDirUpdate = TRUE)
update_icon(TRUE)
/mob/living/carbon/human/update_inv_r_hand(update_icons = TRUE)
if (QDELETED(src))
@@ -1284,7 +1278,7 @@ There are several things that need to be remembered:
overlays_raw[R_HAND_LAYER] = null
if(update_icons)
update_icon(forceDirUpdate = TRUE)
update_icon(TRUE)
/mob/living/carbon/human/update_inv_wrists(var/update_icons=1)
if (QDELETED(src))
@@ -1389,7 +1383,7 @@ There are several things that need to be remembered:
if(species.tail && !(mutations & HUSK) && !(mutations & SKELETON) && !(wear_suit && wear_suit.flags_inv & HIDETAIL))
var/icon/tail_s = get_tail_icon()
overlays_raw[tail_layer] = image(tail_s, icon_state = "[tail_style]_s")
animate_tail_reset()
animate_tail_reset(FALSE)
update_tail_accessory(FALSE)
if(update_icons)
@@ -1414,7 +1408,7 @@ There are several things that need to be remembered:
return tail_icon
/mob/living/carbon/human/proc/set_tail_state(var/mob_state)
/mob/living/carbon/human/proc/set_tail_state(var/mob_state, var/update = TRUE)
if(!tail_style)
return
@@ -1428,8 +1422,7 @@ There are several things that need to be remembered:
if(tail_overlay && species.tail_animation)
if(tail_overlay.icon_state != mob_state)
tail_overlay.icon_state = mob_state
update_tail_accessory()
update_icon()
update_tail_accessory(update)
return tail_overlay
return null
@@ -1461,11 +1454,11 @@ There are several things that need to be remembered:
/mob/living/carbon/human/proc/animate_tail_fast()
set_tail_state("[tail_style]_loop")
/mob/living/carbon/human/proc/animate_tail_reset()
/mob/living/carbon/human/proc/animate_tail_reset(var/update = TRUE)
if(stat != DEAD && !lying)
set_tail_state("[tail_style]_idle")
set_tail_state("[tail_style]_idle", update)
else
set_tail_state("[tail_style]_static")
set_tail_state("[tail_style]_static", update)
/mob/living/carbon/human/proc/animate_tail_stop(var/update_icons=1)
set_tail_state("[tail_style]_static")
+10 -2
View File
@@ -1,3 +1,5 @@
GLOBAL_DATUM_INIT(follow_menu, /datum/tgui_module/follow_menu, new)
/datum/tgui_module/follow_menu/ui_interact(var/mob/user, var/datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -14,9 +16,15 @@
return
if(action == "follow_target")
ghost.ManualFollow(locate(params["follow_target"]) in GLOB.mob_list)
if(!ghost.ManualFollow(locate(params["follow_target"]) in GLOB.mob_list))
to_chat(ghost, SPAN_WARNING("Failed to follow selected target. Refreshing mob list..."))
return TRUE
/datum/tgui_module/follow_menu/ui_data(mob/user)
if(action == "refresh")
ui.send_full_update()
return TRUE
/datum/tgui_module/follow_menu/ui_static_data(mob/user)
var/list/data = list()
// Don't worry about this is_mod check being for storytellers as well - all it does is highlight antags in red.
var/is_mod = check_rights(R_MOD|R_ADMIN, 0, user) || isstoryteller(user)
+1 -1
View File
@@ -519,7 +519,7 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/process(update = 0)
if (!src_object || !user)
if (QDELETED(src_object) || QDELETED(user))
close()
return
+5 -6
View File
@@ -194,12 +194,11 @@
/obj/item/organ/external/hand/is_malfunctioning()
. = ..()
if(!.)
if(owner.is_mechanical())
var/actuator_type = limb_name == BP_L_HAND ? BP_ACTUATORS_LEFT : BP_ACTUATORS_RIGHT
var/obj/item/organ/internal/machine/actuators/actuator = owner.internal_organs_by_name[actuator_type]
if(!actuator || (actuator.status & ORGAN_DEAD))
return TRUE
if(!. && owner?.is_mechanical())
var/actuator_type = limb_name == BP_L_HAND ? BP_ACTUATORS_LEFT : BP_ACTUATORS_RIGHT
var/obj/item/organ/internal/machine/actuators/actuator = owner.internal_organs_by_name[actuator_type]
if(!actuator || (actuator.status & ORGAN_DEAD))
return TRUE
/obj/item/organ/external/hand/take_damage(brute, burn, damage_flags, used_weapon, list/forbidden_limbs, silent)
. = ..()
@@ -312,7 +312,7 @@
M.hallucination = max(M.hallucination, drug_strength)
if(prob(15))
to_chat(SPAN_GOOD(pick("The floor is melting...", "Everything is so much brighter! Wow!", "Everything is shifting around you.")))
to_chat(M, SPAN_GOOD(pick("The floor is melting...", "Everything is so much brighter! Wow!", "Everything is shifting around you.")))
/singleton/reagent/drugs/night_juice
+1
View File
@@ -170,6 +170,7 @@
"can_force" = shuttle.can_force(),
"can_rename_ship" = can_rename_ship,
"ship_name" = shuttle.name,
"current_location" = shuttle.get_location_name(),
)
/obj/machinery/computer/shuttle_control/ui_act(action, params)
+2 -4
View File
@@ -202,15 +202,13 @@
if(powered && cell?.charge < charge_use && !organic)
return FALSE
on = TRUE
set_light_range_power_color(initial(light_range))
set_light_on(on)
set_light(initial(light_range))
update_icon()
return TRUE
/obj/vehicle/proc/turn_off()
on = FALSE
set_light_range_power_color(0)
set_light_on(on)
set_light(0)
update_icon()
/obj/vehicle/emag_act(var/remaining_charges, mob/user as mob)