@@ -112,15 +112,15 @@ SUBSYSTEM_DEF(statpanels)
112112 for (var /image /target_image as anything in target. images)
113113 if (! target_image. loc || target_image. loc. loc != target_mob. listed_turf || ! target_image. override)
114114 continue
115- overrides += target_image. loc
115+ overrides[ target_image. loc] = TRUE
116116
117117 var /list /atoms_to_display = list (target_mob. listed_turf)
118118 for (var /atom/movable /turf_content as anything in target_mob. listed_turf)
119119 if (turf_content. mouse_opacity == MOUSE_OPACITY_TRANSPARENT )
120120 continue
121121 if (turf_content. invisibility > target_mob. see_invisible)
122122 continue
123- if (turf_content in overrides)
123+ if (overrides[turf_content] )
124124 continue
125125 if (turf_content. IsObscured())
126126 continue
@@ -129,6 +129,8 @@ SUBSYSTEM_DEF(statpanels)
129129 // / Set the atoms we're meant to display
130130 var /datum /object_window_info/obj_window = istype(target. obj_window) ? target. obj_window : new (target)
131131 obj_window. atoms_to_show = atoms_to_display
132+ // don't generate icons for stuff the user will not see
133+ obj_window. atoms_to_imagify &= atoms_to_display
132134 refresh_client_obj_view (target, obj_window. min_index, obj_window. max_index)
133135
134136/ datum / controller/ subsystem/ statpanels/ proc / refresh_client_obj_view( client / refresh, min_index = 0 , max_index = 30 )
@@ -160,6 +162,8 @@ SUBSYSTEM_DEF(statpanels)
160162 var /list /turf_items = list ()
161163 var /i = 0
162164 var /client_uid = load_from. UID ()
165+ // While an item's icon is being generated, we send no image URL and let the frontend render an empty slot.
166+ var /static /no_image_url = " "
163167 for (var /atom /turf_item as anything in obj_window. atoms_to_show)
164168 // Limit what we send to the client's rendered section.
165169 i++
@@ -169,7 +173,11 @@ SUBSYSTEM_DEF(statpanels)
169173 // First, we fill up the list of refs to display
170174 // If we already have one, just use that
171175 var /existing_image = already_seen[turf_item]
176+ // rows that are still loading are still sent, we just won't send an image, frontend will hotswap it in
172177 if (existing_image == OBJ_IMAGE_LOADING )
178+ var /obj_m5_uid_loading = turf_item. MD5_UID ()
179+ load_from. m5_uid_cache[obj_m5_uid_loading] = turf_item. unique_datum_id
180+ turf_items[" [ i] " ] = list (" [ turf_item. name] " , obj_m5_uid_loading, no_image_url, " " , client_uid)
173181 continue
174182 // We already have it. Success!
175183
@@ -254,6 +262,10 @@ SUBSYSTEM_DEF(statpanels)
254262 var /client /parent
255263 // / Are we currently tracking a turf?
256264 var /actively_tracking = FALSE
265+ // / Turf we are currently listening to for content changes.
266+ var /turf /tracked_turf
267+ // / Debounce flag for immediate refreshes.
268+ var /pending_turf_refresh = FALSE
257269 // / The minimum index currently sent to the client.
258270 var /min_index = 0
259271 // / The maximum index currently sent to the client.
@@ -264,6 +276,9 @@ SUBSYSTEM_DEF(statpanels)
264276 src . parent = parent
265277
266278/ datum / object_window_info/ Destroy(force, ... )
279+ if (tracked_turf)
280+ UnregisterSignal (tracked_turf, list (COMSIG_ATOM_ENTERED , COMSIG_ATOM_EXITED , COMSIG_TURF_CHANGE ))
281+ tracked_turf = null
267282 atoms_to_show = null
268283 atoms_to_images = null
269284 atoms_to_imagify = null
@@ -303,6 +318,13 @@ SUBSYSTEM_DEF(statpanels)
303318/ datum / object_window_info/ proc / start_turf_tracking()
304319 if (actively_tracking)
305320 stop_turf_tracking ()
321+ var /turf /new_tracked = parent?. mob?. listed_turf
322+ if (new_tracked)
323+ // We're setting up signals here so updates are instant rather than laggy and slow.
324+ tracked_turf = new_tracked
325+ RegisterSignal (tracked_turf, COMSIG_ATOM_ENTERED , PROC_REF (on_tracked_turf_entered))
326+ RegisterSignal (tracked_turf, COMSIG_ATOM_EXITED , PROC_REF (on_tracked_turf_exited))
327+ RegisterSignal (tracked_turf, COMSIG_TURF_CHANGE , PROC_REF (on_tracked_turf_change))
306328 var /static /list /connections = list (
307329 COMSIG_MOVABLE_MOVED = PROC_REF (on_mob_move),
308330 COMSIG_MOB_LOGOUT = PROC_REF (on_mob_logout),
@@ -312,8 +334,38 @@ SUBSYSTEM_DEF(statpanels)
312334
313335/ datum / object_window_info/ proc / stop_turf_tracking()
314336 DeleteComponent (/ datum / component/ connect_mob_behalf)
337+ if (tracked_turf)
338+ UnregisterSignal (tracked_turf, list (COMSIG_ATOM_ENTERED , COMSIG_ATOM_EXITED , COMSIG_TURF_CHANGE ))
339+ tracked_turf = null
340+ pending_turf_refresh = FALSE
315341 actively_tracking = FALSE
316342
343+ / datum / object_window_info/ proc / queue_listedturf_refresh()
344+ if (pending_turf_refresh)
345+ return
346+ pending_turf_refresh = TRUE
347+ // This accumulates all of our updates and does one refresh rather than calling a dozen refreshes when a dozen things change
348+ addtimer (CALLBACK (src , PROC_REF (do_listedturf_refresh)), 1 )
349+
350+ / datum / object_window_info/ proc / do_listedturf_refresh()
351+ pending_turf_refresh = FALSE
352+ if (! parent?. mob?. listed_turf)
353+ return
354+ // If the user moved away, let the existing adjacency logic close the tab.
355+ SSstatpanels. set_turf_examine_tab(parent, parent. mob)
356+
357+ / datum / object_window_info/ proc / on_tracked_turf_entered( atom / source, atom/movable / entered, atom / old_loc)
358+ SIGNAL_HANDLER // COMSIG_ATOM_ENTERED
359+ queue_listedturf_refresh ()
360+
361+ / datum / object_window_info/ proc / on_tracked_turf_exited( atom / source, atom/movable / exiting, direction)
362+ SIGNAL_HANDLER // COMSIG_ATOM_EXITED
363+ queue_listedturf_refresh ()
364+
365+ / datum / object_window_info/ proc / on_tracked_turf_change( atom / source)
366+ SIGNAL_HANDLER // COMSIG_TURF_CHANGE
367+ queue_listedturf_refresh ()
368+
317369/ datum / object_window_info/ proc / on_mob_move( mob / source)
318370 SIGNAL_HANDLER
319371 var /turf /listed = source. listed_turf
@@ -330,7 +382,7 @@ SUBSYSTEM_DEF(statpanels)
330382 SIGNAL_HANDLER
331383 atoms_to_show -= deleted
332384 atoms_to_imagify -= deleted
333- atoms_to_images -= deleted
385+ atoms_to_images[deleted] = null
334386
335387/ mob / proc / set_listed_turf( turf / new_turf)
336388 listed_turf = new_turf
@@ -347,3 +399,6 @@ SUBSYSTEM_DEF(statpanels)
347399 else
348400 client. stat_panel. send_message(" remove_listedturf" )
349401 client. obj_window. stop_turf_tracking()
402+ // Don't generate icons when the tab's closed.
403+ client. obj_window. atoms_to_show. Cut()
404+ client. obj_window. atoms_to_imagify. Cut()
0 commit comments