mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-20 12:29:23 +01:00
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:
@@ -115,10 +115,6 @@
|
||||
if (!isturf(src))
|
||||
cleanup_events(src)
|
||||
|
||||
var/ui_key = REF(src)
|
||||
if(LAZYISIN(SSnanoui.open_uis, ui_key))
|
||||
SSnanoui.close_uis(src)
|
||||
|
||||
//BEGIN: ECS SHIT
|
||||
var/list/dc = _datum_components
|
||||
if(dc)
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
take_damage(25)
|
||||
return
|
||||
else
|
||||
return attackby(user, user)
|
||||
return attackby(null, user)
|
||||
|
||||
/obj/machinery/door/window/emag_act(var/remaining_charges, var/mob/user)
|
||||
if (density && operable())
|
||||
|
||||
@@ -257,10 +257,7 @@
|
||||
/obj/item/Destroy()
|
||||
if(ismob(loc))
|
||||
var/mob/m = loc
|
||||
m.drop_from_inventory(src)
|
||||
m.update_inv_r_hand()
|
||||
m.update_inv_l_hand()
|
||||
src.loc = null
|
||||
m.drop_from_inventory(src, null)
|
||||
|
||||
if(!QDELETED(action))
|
||||
QDEL_NULL(action) // /mob/living/proc/handle_actions() creates it, for ungodly reasons
|
||||
@@ -930,7 +927,7 @@ GLOBAL_LIST_INIT(slot_flags_enumeration, list(
|
||||
user.langchat_speech("holds up [src].", viewers, GLOB.all_languages, skip_language_check = TRUE, animation_style = LANGCHAT_FAST_POP, additional_styles = list("langchat_small", "emote"))
|
||||
for (var/mob/M in viewers)
|
||||
if(!user.is_invisible_to(M))
|
||||
M.show_message("<b>[user]</b> holds up [icon2html(src, viewers)] [src]. <a href='byond://?src=[REF(M)];lookitem=[REF(src)]'>Take a closer look.</a>",1)
|
||||
M.show_message("<b>[user]</b> holds up [icon2html(src, M)] [src]. <a href='byond://?src=[REF(M)];lookitem=[REF(src)]'>Take a closer look.</a>",1)
|
||||
|
||||
/mob/living/carbon/verb/showoff()
|
||||
set name = "Show Held Item"
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Your name.
|
||||
author: Wildkins
|
||||
|
||||
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||
delete-after: True
|
||||
|
||||
# Any changes you've made. See valid prefix list above.
|
||||
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||
# SCREW THIS UP AND IT WON'T WORK.
|
||||
# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
|
||||
# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
|
||||
changes:
|
||||
- refactor: "Every single datum no longer does REF(src) on /Destroy to see if it has an open nanoui"
|
||||
- bugfix: "Showing held items no longer causes every recording device to runtime."
|
||||
- refactor: "Every obj/item/Destroy no longer updates the held mob's icon three times."
|
||||
- refactor: "Follow menu is now a global UI and should no longer DDOS the server when 50 people have it open"
|
||||
- refactor: "Follow menu no longer auto-updates the list of mobs while open, use the refresh button."
|
||||
- bugfix: "Fix runtime when a /human without hair or facial hair would be skeletonized"
|
||||
- refactor: "Cleaned up human icon update code. Lying / direction changes no longer cause four update_icon calls. Tailed species turning no longer causes six."
|
||||
- bugfix: "Fix runtime caused by detached / ownerless mechanical hands."
|
||||
- bugfix: "Fix colorspace runtime."
|
||||
- bugfix: "Fix lighting harddel caused by using improper handlers for static lights."
|
||||
- bugfix: "Lifts now grey out the current location, instead of throwing a runtime when you click it."
|
||||
- bugfix: "Fix runtime when a bloodless/fakedeath mob has their pulse taken."
|
||||
@@ -30,17 +30,20 @@ export const FollowMenu = (props, context) => {
|
||||
<Section
|
||||
title="Follow Menu"
|
||||
buttons={
|
||||
<Input
|
||||
autoFocus
|
||||
autoSelect
|
||||
placeholder="Search by name"
|
||||
width="40vw"
|
||||
maxLength={512}
|
||||
onInput={(e, value) => {
|
||||
setSearchTerm(value);
|
||||
}}
|
||||
value={searchTerm}
|
||||
/>
|
||||
<>
|
||||
<Input
|
||||
autoFocus
|
||||
autoSelect
|
||||
placeholder="Search by name"
|
||||
width="40vw"
|
||||
maxLength={512}
|
||||
onInput={(e, value) => {
|
||||
setSearchTerm(value);
|
||||
}}
|
||||
value={searchTerm}
|
||||
/>
|
||||
<Button content="Refresh" onClick={() => act('refresh')} />
|
||||
</>
|
||||
}
|
||||
>
|
||||
{data.categories.sort().map((category) => (
|
||||
|
||||
@@ -14,6 +14,7 @@ export type ShuttleControlConsoleMultiLiftData = {
|
||||
can_pick: boolean;
|
||||
destination_name: string;
|
||||
destinations: string[];
|
||||
current_location: string;
|
||||
};
|
||||
|
||||
export const ShuttleControlConsoleMultiLift = (props, context) => {
|
||||
@@ -30,7 +31,9 @@ export const ShuttleControlConsoleMultiLift = (props, context) => {
|
||||
<Button
|
||||
content="Go To"
|
||||
icon="arrow-right-to-bracket"
|
||||
disabled={!data.can_pick}
|
||||
disabled={
|
||||
!data.can_pick || data.current_location === destination
|
||||
}
|
||||
onClick={() => act('pick', { destination: destination })}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
|
||||
Reference in New Issue
Block a user