Lag War Day 2: TGUI performance improvements (#21848)

<img width="707" height="659" alt="image"
src="https://github.com/user-attachments/assets/6c8db0bf-dec6-40f2-86e8-120531fa5693"
/>

the traitor uplink is causing a genuine hostage situation to the server
by simply being open due to the frankly insane amount of data that it
builds and ships every single UI process tick (which is very often!!!)

i've never been ragebaited by a single .dm file before so hard in my
entire developer career so I simply neutered it into using static data
and hit the commit button. it might break, if it does we're burning it
to the ground and remaking it. genuinely heinous crimes going on there

In addition I'm porting:

* [Fix several SHOULD_NOT_SLEEP hits in SStgui.update_uis()
tgstation/tgstation#75411](https://github.com/tgstation/tgstation/pull/75411)
* [Moves ui references from the tgui subsystem to datums themselves
tgstation/tgstation#76215](https://github.com/tgstation/tgstation/pull/76215)
* [Fixes some spurious runtimes in SStgui procs
tgstation/tgstation#76251](https://github.com/tgstation/tgstation/pull/76251)
* [Fixes tgui_open_uis tracking
tgstation/tgstation#77101](https://github.com/tgstation/tgstation/pull/77101)

moving ui references to the datums themselves is a pretty nice
performance boost because otherwise we have to iterate across all open
uis every time a list input closes which sucks! the rest are just fixes
to that original PR.

thank you for your attention to this matter
This commit is contained in:
Wildkins
2026-02-14 02:17:23 +00:00
committed by GitHub
parent efe710f425
commit 84d3a447ab
7 changed files with 126 additions and 124 deletions
@@ -6,7 +6,7 @@ PROCESSING_SUBSYSTEM_DEF(nanoui)
stat_tag = "A"
// NanoUI stuff.
var/list/open_uis = list()
var/list/open_nanouis = list()
/**
* Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data
@@ -43,10 +43,10 @@ PROCESSING_SUBSYSTEM_DEF(nanoui)
*/
/datum/controller/subsystem/processing/nanoui/proc/get_open_ui(mob/user, src_object, ui_key)
var/src_object_key = REF(src_object)
if (!LAZYLEN(open_uis[src_object_key]) || !LAZYLEN(open_uis[src_object_key][ui_key]))
if (!LAZYLEN(open_nanouis[src_object_key]) || !LAZYLEN(open_nanouis[src_object_key][ui_key]))
return null
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
for (var/datum/nanoui/ui in open_nanouis[src_object_key][ui_key])
if (ui.user == user)
return ui
@@ -62,11 +62,11 @@ PROCESSING_SUBSYSTEM_DEF(nanoui)
*/
/datum/controller/subsystem/processing/nanoui/proc/update_uis(src_object)
var/src_object_key = REF(src_object)
if (!LAZYLEN(open_uis[src_object_key]))
if (!LAZYLEN(open_nanouis[src_object_key]))
return 0
. = 0
var/list/obj_uis = open_uis[src_object_key]
var/list/obj_uis = open_nanouis[src_object_key]
for (var/ui_key in obj_uis)
for (var/thing in obj_uis[ui_key])
var/datum/nanoui/ui = thing
@@ -83,11 +83,11 @@ PROCESSING_SUBSYSTEM_DEF(nanoui)
*/
/datum/controller/subsystem/processing/nanoui/proc/close_uis(src_object)
var/src_object_key = REF(src_object)
if (!open_uis[src_object_key] || !islist(open_uis[src_object_key]))
if (!open_nanouis[src_object_key] || !islist(open_nanouis[src_object_key]))
return 0
. = 0
var/list/obj_uis = open_uis[src_object_key]
var/list/obj_uis = open_nanouis[src_object_key]
for (var/ui_key in obj_uis)
for (var/thing in obj_uis[ui_key])
var/datum/nanoui/ui = thing
@@ -105,27 +105,27 @@ PROCESSING_SUBSYSTEM_DEF(nanoui)
* Returns the number of UIs updated
*/
/datum/controller/subsystem/processing/nanoui/proc/update_user_uis(mob/user, src_object, ui_key)
if (!LAZYLEN(user.open_uis))
if (!LAZYLEN(user.open_nanouis))
return 0 // has no open uis
. = 0
for (var/thing in user.open_uis)
for (var/thing in user.open_nanouis)
var/datum/nanoui/ui = thing
if (NULL_OR_EQUAL(src_object, ui.src_object) && NULL_OR_EQUAL(ui_key, ui.ui_key))
ui.process(1)
.++
/datum/controller/subsystem/processing/nanoui/proc/close_user_uis(mob/user, src_object, ui_key)
if (!LAZYLEN(user.open_uis))
if (!LAZYLEN(user.open_nanouis))
return 0
for (var/thing in user.open_uis)
for (var/thing in user.open_nanouis)
var/datum/nanoui/ui = thing
if (NULL_OR_EQUAL(src_object, ui.src_object) && NULL_OR_EQUAL(ui_key, ui.ui_key))
ui.close()
.++
//testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [.] uis")
//testing("nanomanager/close_user_uis mob [user.name] closed [open_nanouis.len] of [.] uis")
/**
* Add a /nanoui ui to the list of open uis
@@ -135,12 +135,12 @@ PROCESSING_SUBSYSTEM_DEF(nanoui)
*/
/datum/controller/subsystem/processing/nanoui/proc/ui_opened(datum/nanoui/ui)
var/src_object_key = REF(ui.src_object)
LAZYINITLIST(open_uis[src_object_key])
LAZYINITLIST(open_nanouis[src_object_key])
LAZYADD(ui.user.open_uis, ui)
LAZYADD(open_uis[src_object_key][ui.ui_key], ui)
LAZYADD(ui.user.open_nanouis, ui)
LAZYADD(open_nanouis[src_object_key][ui.ui_key], ui)
START_PROCESSING(SSnanoui, ui)
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_nanouis [ui.user.open_nanouis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
/**
* Remove a /nanoui ui from the list of open uis
@@ -153,14 +153,14 @@ PROCESSING_SUBSYSTEM_DEF(nanoui)
/datum/controller/subsystem/processing/nanoui/proc/ui_closed(datum/nanoui/ui)
var/src_object_key = REF(ui.src_object)
var/ui_key = ui.ui_key
var/list/obj_uis = open_uis[src_object_key]
var/list/obj_uis = open_nanouis[src_object_key]
if (!LAZYLEN(obj_uis) || !obj_uis[ui_key])
return 0 // Wasn't open.
STOP_PROCESSING(SSnanoui, ui)
if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface)
LAZYREMOVE(ui.user.open_uis, ui)
LAZYREMOVE(ui.user.open_nanouis, ui)
obj_uis[ui_key] -= ui
@@ -168,9 +168,9 @@ PROCESSING_SUBSYSTEM_DEF(nanoui)
obj_uis -= ui_key
if (!LAZYLEN(obj_uis))
open_uis -= src_object_key
open_nanouis -= src_object_key
//testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
//testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_nanouis [ui.user.open_nanouis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
return 1
@@ -192,16 +192,16 @@ PROCESSING_SUBSYSTEM_DEF(nanoui)
*/
/datum/controller/subsystem/processing/nanoui/proc/user_transferred(mob/oldMob, mob/newMob)
//testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]")
if (!oldMob || !LAZYLEN(oldMob.open_uis) || !LAZYLEN(open_uis))
if (!oldMob || !LAZYLEN(oldMob.open_nanouis) || !LAZYLEN(open_nanouis))
//testing("nanomanager/user_transferred mob [oldMob.name] has no open uis")
return 0 // has no open uis
for (var/thing in oldMob.open_uis)
for (var/thing in oldMob.open_nanouis)
var/datum/nanoui/ui = thing
ui.user = newMob
LAZYADD(newMob.open_uis, ui)
LAZYADD(newMob.open_nanouis, ui)
oldMob.open_uis = null
oldMob.open_nanouis = null
return 1 // success
+29 -46
View File
@@ -19,10 +19,8 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
/// A list of UIs scheduled to process
var/list/current_run = list()
/// A list of open UIs
var/list/open_uis = list()
/// A list of open UIs, grouped by src_object.
var/list/open_uis_by_src = list()
/// A list of all open UIs
var/list/all_uis = list()
/// The HTML base used for all UIs.
var/basehtml
@@ -58,13 +56,13 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
close_all_uis()
/datum/controller/subsystem/processing/tgui/stat_entry(msg)
msg = "P:[length(open_uis)]"
msg = "P:[length(all_uis)]"
return ..()
/datum/controller/subsystem/processing/tgui/fire(resumed = FALSE)
CAN_BE_REDEFINED(TRUE)
if(!resumed)
src.current_run = open_uis.Copy()
src.current_run = all_uis.Copy()
// Cache for sanic speed (lists are references anyways)
var/list/current_run = src.current_run
while(current_run.len)
@@ -74,7 +72,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
if(ui?.user && ui.src_object)
ui.process(wait * 0.1)
else
open_uis.Remove(ui)
ui.close(0)
if(MC_TICK_CHECK)
return
@@ -193,11 +191,9 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
* return datum/tgui The found UI.
*/
/datum/controller/subsystem/processing/tgui/proc/get_open_ui(mob/user, datum/src_object)
var/key = text_ref(src_object)
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
if(!LAZYLEN(src_object?.open_uis))
return null
for(var/datum/tgui/ui in open_uis_by_src[key])
for(var/datum/tgui/ui in src_object.open_uis)
// Make sure we have the right user
if(ui.user == user)
return ui
@@ -213,15 +209,13 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
* return int The number of UIs updated.
*/
/datum/controller/subsystem/processing/tgui/proc/update_uis(datum/src_object)
if(!LAZYLEN(src_object?.open_uis))
return 0
var/count = 0
var/key = text_ref(src_object)
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return count
for(var/datum/tgui/ui in open_uis_by_src[key])
for(var/datum/tgui/ui in src_object.open_uis)
// Check if UI is valid.
if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.process(wait * 0.1, force = 1)
INVOKE_ASYNC(ui, TYPE_PROC_REF(/datum/tgui, process), wait * 0.1, TRUE)
count++
return count
@@ -235,12 +229,11 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
* return int The number of UIs closed.
*/
/datum/controller/subsystem/processing/tgui/proc/close_uis(datum/src_object)
var/count = 0
var/key = text_ref(src_object)
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return count
for(var/datum/tgui/ui in open_uis_by_src[key])
if(!LAZYLEN(src_object?.open_uis))
return 0
var/count = 0
for(var/datum/tgui/ui in src_object.open_uis)
// Check if UI is valid.
if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.close()
@@ -256,12 +249,11 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
*/
/datum/controller/subsystem/processing/tgui/proc/close_all_uis()
var/count = 0
for(var/key in open_uis_by_src)
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.close()
count++
for(var/datum/tgui/ui in all_uis)
// Check if UI is valid.
if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.close()
count++
return count
/**
@@ -312,13 +304,9 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
* required ui datum/tgui The UI to be added.
*/
/datum/controller/subsystem/processing/tgui/proc/on_open(datum/tgui/ui)
var/key = text_ref(ui.src_object)
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
open_uis_by_src[key] = list()
ui.user.tgui_open_uis |= ui
var/list/uis = open_uis_by_src[key]
uis |= ui
open_uis |= ui
ui.user?.tgui_open_uis |= ui
LAZYOR(ui.src_object.open_uis, ui)
all_uis |= ui
/**
* private
@@ -330,19 +318,14 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
* return bool If the UI was removed or not.
*/
/datum/controller/subsystem/processing/tgui/proc/on_close(datum/tgui/ui)
var/key = text_ref(ui.src_object)
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return FALSE
// Remove it from the list of processing UIs.
open_uis.Remove(ui)
all_uis -= ui
current_run -= ui
// If the user exists, remove it from them too.
if(ui.user)
ui.user.tgui_open_uis.Remove(ui)
ui.user.unset_machine()
var/list/uis = open_uis_by_src[key]
uis.Remove(ui)
if(length(uis) == 0)
open_uis_by_src.Remove(key)
ui.user.tgui_open_uis -= ui
if(ui.src_object)
LAZYREMOVE(ui.src_object.open_uis, ui)
return TRUE
/**
@@ -377,7 +360,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
for(var/datum/tgui/ui in source.tgui_open_uis)
// Inform the UIs of their new owner.
ui.user = target
target.tgui_open_uis.Add(ui)
target.tgui_open_uis += ui
// Clear the old list.
source.tgui_open_uis.Cut()
return TRUE
+4
View File
@@ -7,6 +7,10 @@
*/
var/gc_destroyed
/// Open uis owned by this datum
/// Lazy, since this case is semi rare
var/list/open_uis
var/tmp/list/active_timers
/// Active timers with this datum as the target
+53 -52
View File
@@ -25,8 +25,6 @@ A list of items and costs is stored under the datum of every game mode, alongsid
var/list/tgui_items
/// The current menu we are in.
var/tgui_menu = 0
/// Additional data for TGUI use.
var/list/tgui_data = list()
// Assoc list of item to times bought; shared/referenced by child uplinks
var/list/purchase_log = list()
/// Mind of the uplink's owner.
@@ -73,12 +71,6 @@ Then check if it's true, if true return. This will stop the normal menu appearin
var/pda_code = ""
/obj/item/uplink/hidden/New()
..()
tgui_data = list()
update_tgui_data()
/obj/item/uplink/hidden/Initialize(mapload, datum/mind/owner, new_telecrystals, new_bluecrystals)
. = ..()
return INITIALIZE_HINT_LATELOAD
@@ -119,13 +111,15 @@ Then check if it's true, if true return. This will stop the normal menu appearin
/obj/item/uplink/hidden/ui_data(mob/user)
var/list/data = list()
data["welcome"] = welcome
data["menu"] = tgui_menu
data["telecrystals"] = telecrystals
data["bluecrystals"] = bluecrystals
data["menu"] = tgui_menu
update_tgui_data()
data += tgui_data
return data
/obj/item/uplink/hidden/ui_static_data(mob/user)
. = ..()
. += update_tgui_data()
// Interaction code. Gathers a list of items purchasable from the paren't uplink and displays it. It also adds a lock button.
/obj/item/uplink/hidden/interact(mob/user)
ui_interact(user, null)
@@ -137,25 +131,31 @@ Then check if it's true, if true return. This will stop the normal menu appearin
if(action == "buy_item")
var/datum/uplink_item/UI = (locate(params["buy_item"]) in GLOB.uplink.items)
UI.buy(src, usr)
update_static_data(usr, ui)
else if(action == "lock")
toggle()
SStgui.close_uis(src)
else if(action == "return")
tgui_menu = round(tgui_menu/10)
update_static_data(usr, ui)
else if(action == "menu")
tgui_menu = text2num(params["menu"])
if(params["id"])
exploit_id = params["id"]
if(params["category"])
category = locate(params["category"]) in GLOB.uplink.categories
update_static_data(usr, ui)
if(action == "contract_interact")
var/list/params_webint = list("location" = "contract_details", "contract" = params["contract_interact"])
usr.client.process_webint_link("interface/login/sso_server", list2params(params_webint))
update_static_data(usr, ui)
if(action == "contract_page")
tgui_data["contracts_current_page"] = text2num(params["contract_page"])
.["contracts_current_page"] = text2num(params["contract_page"])
update_static_data(usr, ui)
if(action == "contract_view")
tgui_data["contracts_view"] = text2num(params["contract_view"])
tgui_data["contracts_current_page"] = 1
.["contracts_view"] = text2num(params["contract_view"])
.["contracts_current_page"] = 1
update_static_data(usr, ui)
return 1
@@ -175,6 +175,7 @@ Then check if it's true, if true return. This will stop the normal menu appearin
return newItem
/obj/item/uplink/hidden/proc/update_tgui_data()
. = list()
if(tgui_menu == 0)
var/list/categories = list()
var/list/items = list()
@@ -185,62 +186,62 @@ Then check if it's true, if true return. This will stop the normal menu appearin
if(item.can_view(src))
items[++items.len] = new_tgui_item_data(item)
tgui_data["categories"] = categories
tgui_data["items"] = items
.["categories"] = categories
.["items"] = items
else if(tgui_menu == 1)
var/items[0]
for(var/datum/uplink_item/item in category?.items)
if(item.can_view(src))
items[++items.len] = new_tgui_item_data(item)
tgui_data["items"] = items
.["items"] = items
else if(tgui_menu == 2)
var/permanentData[0]
for(var/datum/record/general/locked/record in SSrecords.records_locked)
permanentData[++permanentData.len] = list("name" = record.name,"id" = record.id, "has_exploitables" = !!record.exploit_record)
tgui_data["exploit_records"] = permanentData
.["exploit_records"] = permanentData
else if(tgui_menu == 21)
tgui_data["exploit_exists"] = 0
.["exploit_exists"] = 0
for(var/datum/record/general/locked/L in SSrecords.records_locked)
if(L.id == exploit_id)
tgui_data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value.
.["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value.
// We trade off being able to automatically add shit for more control over what gets passed to json
// and if it's sanitized for html.
tgui_data["exploit"]["tgui_exploit_record"] = html_decode(L.exploit_record) // this user input is already sanitized and encoded when saved to the DB, we can just decode it and slap it into a span
tgui_data["exploit"]["name"] = html_encode(L.name)
tgui_data["exploit"]["sex"] = html_encode(L.sex)
tgui_data["exploit"]["age"] = html_encode(L.age)
tgui_data["exploit"]["species"] = html_encode(L.species)
tgui_data["exploit"]["rank"] = html_encode(L.rank)
tgui_data["exploit"]["citizenship"] = html_encode(L.citizenship)
tgui_data["exploit"]["employer"] = html_encode(L.employer)
tgui_data["exploit"]["religion"] = html_encode(L.religion)
tgui_data["exploit"]["fingerprint"] = html_encode(L.fingerprint)
.["exploit"]["tgui_exploit_record"] = html_decode(L.exploit_record) // this user input is already sanitized and encoded when saved to the DB, we can just decode it and slap it into a span
.["exploit"]["name"] = html_encode(L.name)
.["exploit"]["sex"] = html_encode(L.sex)
.["exploit"]["age"] = html_encode(L.age)
.["exploit"]["species"] = html_encode(L.species)
.["exploit"]["rank"] = html_encode(L.rank)
.["exploit"]["citizenship"] = html_encode(L.citizenship)
.["exploit"]["employer"] = html_encode(L.employer)
.["exploit"]["religion"] = html_encode(L.religion)
.["exploit"]["fingerprint"] = html_encode(L.fingerprint)
tgui_data["exploit_exists"] = 1
.["exploit_exists"] = 1
break
else if(tgui_menu == 3)
tgui_data["contracts_found"] = 0
.["contracts_found"] = 0
if(establish_db_connection(GLOB.dbcon))
tgui_data["contracts"] = list()
.["contracts"] = list()
if (!tgui_data["contracts_current_page"])
tgui_data["contracts_current_page"] = 1
if (!.["contracts_current_page"])
.["contracts_current_page"] = 1
if (!tgui_data["contracts_view"])
tgui_data["contracts_view"] = 1
if (!.["contracts_view"])
.["contracts_view"] = 1
var/query_details[0]
switch (tgui_data["contracts_view"])
switch (.["contracts_view"])
if (1)
query_details["status"] = "open"
if (2)
query_details["status"] = "closed"
else
tgui_data["contracts_view"] = 1
.["contracts_view"] = 1
query_details["status"] = "open"
var/DBQuery/index_query = GLOB.dbcon.NewQuery("SELECT count(*) as Total_Contracts FROM ss13_syndie_contracts WHERE deleted_at IS NULL AND status = :status:")
@@ -263,12 +264,12 @@ Then check if it's true, if true return. This will stop the normal menu appearin
for (var/i = 1, i <= pages, i++)
contracts_pages.Add(i)
tgui_data["contracts_pages"] = contracts_pages
.["contracts_pages"] = contracts_pages
if (tgui_data["contracts_current_page"] > pages)
if (.["contracts_current_page"] > pages)
return
query_details["offset"] = (tgui_data["contracts_current_page"] - 1) * 10
query_details["offset"] = (.["contracts_current_page"] - 1) * 10
var/DBQuery/list_query = GLOB.dbcon.NewQuery("SELECT contract_id, contractee_name, title FROM ss13_syndie_contracts WHERE deleted_at IS NULL AND status = :status: LIMIT 10 OFFSET :offset:")
list_query.Execute(query_details)
@@ -279,21 +280,21 @@ Then check if it's true, if true return. This will stop the normal menu appearin
"contractee" = list_query.item[2],
"title" = list_query.item[3])))
tgui_data["contracts"] = contracts
.["contracts"] = contracts
tgui_data["contracts_found"] = 1
.["contracts_found"] = 1
if(tgui_menu == 31)
tgui_data["contracts_found"] = 0
.["contracts_found"] = 0
if (GLOB.config.sql_enabled && establish_db_connection(GLOB.dbcon))
tgui_data["contracts"] = list()
.["contracts"] = list()
if (!tgui_data["contracts_current_page"])
tgui_data["contracts_current_page"] = 1
if (!.["contracts_current_page"])
.["contracts_current_page"] = 1
if (!tgui_data["contracts_view"])
tgui_data["contracts_view"] = 1
if (!.["contracts_view"])
.["contracts_view"] = 1
var/query_details[0]
query_details["contract_id"] = exploit_id
@@ -302,7 +303,7 @@ Then check if it's true, if true return. This will stop the normal menu appearin
select_query.Execute(query_details)
if (select_query.NextRow())
tgui_data["contracts_found"] = 1
.["contracts_found"] = 1
var/contract[0]
contract["id"] = select_query.item[1]
@@ -322,7 +323,7 @@ Then check if it's true, if true return. This will stop the normal menu appearin
contract["description"] = replacetext(contract["description"], ascii2text(13), "")
contract["reward_other"] = select_query.item[6]
tgui_data["contract"] = contract
.["contract"] = contract
// I placed this here because of how relevant it is.
// You place this in your uplinkable item to check if an uplink is active or not.
+1 -1
View File
@@ -37,4 +37,4 @@
return
// Used by the Nano UI Manager (/datum/SSnanoui) to track UIs opened by this mob
/mob/var/list/open_uis = list()
/mob/var/list/open_nanouis = list()
+1 -1
View File
@@ -70,7 +70,7 @@
* change static data.
*/
/datum/proc/update_static_data_for_all_viewers()
for (var/datum/tgui/window as anything in SStgui.open_uis_by_src[text_ref(src)])
for (var/datum/tgui/window as anything in open_uis)
window.send_full_update()
/**
+14
View File
@@ -0,0 +1,14 @@
# Your name.
author: JohnWildkins
# 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: "Change traitor uplink to use static data to improve server performance."
- refactor: "Open UIs are now tracked by their owner datum rather than by the tgui subsystem, to improve server performance when closing UIs."