Skip to content

Commit

Permalink
Port several tgui-related fixes from /tg/ (#2245)
Browse files Browse the repository at this point in the history
* Fix several SHOULD_NOT_SLEEP hits in SStgui.update_uis() (#75411)

There are several esoteric code paths that lead to `winexists` calls or
sleeps in `ui_data`. This proc is meant to be a command without
sleeping.

See #75232

![image](https://github.com/tgstation/tgstation/assets/8171642/8becd881-d7e8-4fe5-90af-2c2657934d07)

* Moves ui references from the tgui subsystem to datums themselves (#76215)

## About The Pull Request

Unused vars have 0 memory cost, and the ref and list lookup here is
REALLY expensive, for both init and foam spreading.

## Why It's Good For The Game

Saves 0.2s off a station flood on meta, and 0.17s off init. More time in
other qdel heavy areas
Pulled off #76104 for the sake of cleanliness

* Fixes some spurious runtimes in SStgui procs (#76251)

## About The Pull Request

src_object is NOT guaranteed to be passed in. HHHHHHHHHHH
Closes #76249

* Fixes tgui_open_uis tracking (#77101)

Fixes tgstation/tgstation#77097

This breaks uis for everyone with fancy-tgui off and in cases where the
window is closed by external action (byond closing it) which is pretty
bad.

---------

Co-authored-by: Jordan Dominion <Cyberboss@users.noreply.github.com>
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: AnturK <AnturK@users.noreply.github.com>
  • Loading branch information
4 people authored Jun 13, 2024
1 parent 137a65a commit 4399d65
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 45 deletions.
74 changes: 30 additions & 44 deletions code/controllers/subsystem/tgui.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ 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

Expand All @@ -38,12 +36,12 @@ SUBSYSTEM_DEF(tgui)
close_all_uis()

/datum/controller/subsystem/tgui/stat_entry(msg)
msg = "P:[length(open_uis)]"
msg = "P:[length(all_uis)]"
return ..()

/datum/controller/subsystem/tgui/fire(resumed = FALSE)
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)
Expand All @@ -53,7 +51,7 @@ 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

Expand Down Expand Up @@ -172,11 +170,10 @@ SUBSYSTEM_DEF(tgui)
* return datum/tgui The found UI.
*/
/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object)
var/key = "[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
Expand All @@ -192,15 +189,14 @@ SUBSYSTEM_DEF(tgui)
* return int The number of UIs updated.
*/
/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object)
var/count = 0
var/key = "[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.process(wait * 0.1, force = 1)
INVOKE_ASYNC(ui, TYPE_PROC_REF(/datum/tgui, process), wait * 0.1, TRUE)
count++
return count

Expand All @@ -214,12 +210,11 @@ SUBSYSTEM_DEF(tgui)
* return int The number of UIs closed.
*/
/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object)
var/count = 0
var/key = "[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()
Expand All @@ -235,12 +230,11 @@ SUBSYSTEM_DEF(tgui)
*/
/datum/controller/subsystem/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

/**
Expand Down Expand Up @@ -291,13 +285,9 @@ SUBSYSTEM_DEF(tgui)
* required ui datum/tgui The UI to be added.
*/
/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui)
var/key = "[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
Expand All @@ -309,18 +299,14 @@ SUBSYSTEM_DEF(tgui)
* return bool If the UI was removed or not.
*/
/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui)
var/key = "[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)
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

/**
Expand Down Expand Up @@ -355,7 +341,7 @@ 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 changes: 4 additions & 0 deletions code/datums/datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
*/
var/gc_destroyed

/// Open uis owned by this datum
/// Lazy, since this case is semi rare
var/list/open_uis

/// Active timers with this datum as the target
var/list/_active_timers
/// Status traits attached to this datum. associative list of the form: list(trait name (string) = list(source1, source2, source3,...))
Expand Down
2 changes: 1 addition & 1 deletion code/modules/tgui/external.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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[REF(src)])
for (var/datum/tgui/window as anything in open_uis)
window.send_full_update()

/**
Expand Down

0 comments on commit 4399d65

Please sign in to comment.