diff --git a/code/modules/cooking/machinery/smartfridge.dm b/code/modules/cooking/machinery/smartfridge.dm
index 1d2e4ad6281..5b3f3a30918 100644
--- a/code/modules/cooking/machinery/smartfridge.dm
+++ b/code/modules/cooking/machinery/smartfridge.dm
@@ -43,6 +43,8 @@
var/datum/wires/smartfridge/wires = null
atmos_canpass = CANPASS_DENSITY
+ VAR_PRIVATE/static/list/base64_cache = list()
+
/obj/machinery/smartfridge/secure
is_secure = 1
@@ -95,6 +97,7 @@
for(var/obj/item/reagent_containers/food/snacks/grown/g in contents)
item_quants[g.name]++
update_overlays()
+ update_static_data_for_all_viewers()
/obj/machinery/smartfridge/Initialize()
. = ..()
@@ -230,6 +233,10 @@
if(S.on_dry(src)) //Drying rack keeps the item but changes the name. This prevents pre-dried item lingering in the UI as vendable
item_quants[S.name]++
item_quants[old_name]--
+ if(item_quants[old_name] <= 0 || item_quants[S.name] == 1)
+ update_static_data_for_all_viewers()
+ if(item_quants[old_name] <= 0)
+ item_quants -= old_name
return
/obj/machinery/smartfridge/drying_rack/update_overlays()
@@ -360,25 +367,32 @@
user.remove_from_mob(attacking_item)
attacking_item.forceMove(src)
item_quants[attacking_item.name]++
+ if(item_quants[attacking_item.name] == 1)
+ update_static_data_for_all_viewers()
user.visible_message("[user] adds \a [attacking_item] to [src].", SPAN_NOTICE("You add [attacking_item] to [src]."))
update_overlays()
- return
+ return TRUE
if(istype(attacking_item, /obj/item/storage))
var/obj/item/storage/P = attacking_item
var/plants_loaded = 0
+ var/update_static_data = FALSE
for(var/obj/G in P.contents)
if(accept_check(G))
if(length(contents) >= max_n_of_items)
break
P.remove_from_storage(G,src)
item_quants[G.name]++
+ if(item_quants[G.name] == 1)
+ update_static_data = TRUE
plants_loaded++
if(plants_loaded)
user.visible_message("[user] loads [src] with [P].", SPAN_NOTICE("You load [src] with [P]."))
if(length(P.contents) > 0)
to_chat(user, SPAN_NOTICE("Some items are refused."))
update_overlays()
+ if(update_static_data)
+ update_static_data_for_all_viewers()
return TRUE
to_chat(user, SPAN_NOTICE("[src] smartly refuses [attacking_item]."))
return TRUE
@@ -416,43 +430,55 @@
/obj/machinery/smartfridge/ui_data(mob/user)
var/list/data = list()
- data["contents"] = null
data["electrified"] = seconds_electrified > 0
data["shoot_inventory"] = shoot_inventory
data["locked"] = locked
data["secure"] = is_secure
data["sort_alphabetically"] = ui_sort_alphabetically
- var/list/items = list()
- for (var/i = 1 to length(item_quants))
+ var/list/stocks
+ for (var/i in 1 to length(item_quants))
var/K = item_quants[i]
var/count = item_quants[K]
if(count > 0)
+ LAZYADDASSOC(stocks, capitalize(K), count)
- var/obj/item/item_used = null
- for (var/obj/item/O in contents)
- if(O.name == K)
- item_used = O
- break
+ data["stocks"] = stocks
- var/icon/item_icon = null
- if(item_used)
- if(istype(item_used, /obj/item/seeds))
- var/obj/item/seeds/S = item_used
- item_icon = S.update_appearance(TRUE)
- else
- item_icon = new /icon(item_used.icon, item_used.icon_state)
+ return data
- var/final_icon = null
- if(item_icon)
- final_icon = icon2base64(item_icon)
+/obj/machinery/smartfridge/ui_static_data(mob/user)
+ var/list/data = list()
+ data["contents"] = null
- items.Add(list(list(
- "display_name" = capitalize(K),
- "vend" = i,
- "quantity" = count,
- "icon" = final_icon,
- )))
+ var/list/items = list()
+ for (var/i = 1 to length(item_quants))
+ var/K = item_quants[i]
+ var/obj/item/item_used = null
+ for (var/obj/item/O in contents - component_parts)
+ if(O.name == K)
+ item_used = O
+ break
+
+ if(!item_used)
+ continue
+
+ var/final_icon = base64_cache["[K]_[item_used.type]_[item_used.icon_state]"]
+ if(!final_icon)
+ var/icon/item_icon
+ if(istype(item_used, /obj/item/seeds))
+ var/obj/item/seeds/S = item_used
+ item_icon = S.update_appearance(TRUE)
+ else
+ item_icon = getFlatIcon(item_used)
+ final_icon = icon2base64(item_icon)
+ base64_cache["[K]_[item_used.type]_[item_used.icon_state]"] = final_icon
+
+ items.Add(list(list(
+ "display_name" = capitalize(K),
+ "vend" = i,
+ "icon" = final_icon,
+ )))
if(length(items) > 0)
data["contents"] = items
@@ -497,6 +523,10 @@
update_overlays()
if(i <= 0)
break
+
+ if(item_quants[K] <= 0)
+ update_static_data_for_all_viewers()
+ item_quants -= K
if("switch_sort_alphabetically")
ui_sort_alphabetically = !ui_sort_alphabetically
@@ -510,6 +540,7 @@
for (var/O in item_quants)
if(item_quants[O] <= 0) //Try to use a record that actually has something to dump.
+ item_quants -= O
continue
item_quants[O]--
@@ -518,6 +549,10 @@
T.forceMove(loc)
throw_item = T
break
+
+ if(item_quants[O] <= 0)
+ update_static_data_for_all_viewers()
+ item_quants -= O
break
if(!throw_item)
return FALSE
diff --git a/html/changelogs/johnwildkins-smartfridge.yml b/html/changelogs/johnwildkins-smartfridge.yml
new file mode 100644
index 00000000000..2667a7ec58f
--- /dev/null
+++ b/html/changelogs/johnwildkins-smartfridge.yml
@@ -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: "Move smartfridge icon generation to static data and cache results to improve performance."
+ - bugfix: "Fix chemical bottles not having proper colors in SmartFridge UI."
diff --git a/tgui/packages/tgui/interfaces/SmartFridge.tsx b/tgui/packages/tgui/interfaces/SmartFridge.tsx
index ee0c6ef1b63..fee46ce3100 100644
--- a/tgui/packages/tgui/interfaces/SmartFridge.tsx
+++ b/tgui/packages/tgui/interfaces/SmartFridge.tsx
@@ -5,6 +5,7 @@ import { Window } from '../layouts';
export type FridgeData = {
contents: Item[];
+ stocks: { [display_name: string]: number };
seconds_electrified: BooleanLike;
shoot_inventory: BooleanLike;
locked: number; // goes to -1
@@ -15,7 +16,6 @@ export type FridgeData = {
type Item = {
display_name: string;
vend: number;
- quantity: number;
icon?: string | null;
};
@@ -87,93 +87,98 @@ export const ContentsWindow = (props, context) => {
})
: itemList;
+ const itemStock = (item: Item) => data.stocks[item.display_name] || 0;
+
return (
- {itemListSorted.map((item) => (
-
- {/* Item icon */}
- {item.icon ? (
+ {itemListSorted.map((item) => {
+ const quantity = itemStock(item);
+ return (
+
+ {/* Item icon */}
+ {item.icon ? (
+
+ ) : null}
+ {/* Name stuff */}
- ) : null}
- {/* Name stuff */}
-
- {item.display_name}
+ style={{
+ flex: 2,
+ minWidth: 0,
+ whiteSpace: 'normal',
+ overflowWrap: 'break-word',
+ wordBreak: 'break-word',
+ }}
+ >
+ {item.display_name}
+
+ {/* Amount */}x{quantity}
+ {/* Vend buttons */}
+
+ {quantity > 0 && (
+
- {/* Amount */}x{item.quantity}
- {/* Vend buttons */}
-
- {item.quantity > 0 && (
-
- act('vendItem', { vendItem: item.vend, amount: 1 })
- }
- />
- )}
- {item.quantity > 5 && (
-
- act('vendItem', { vendItem: item.vend, amount: 5 })
- }
- />
- )}
- {item.quantity > 10 && (
-
- act('vendItem', { vendItem: item.vend, amount: 10 })
- }
- />
- )}
- {item.quantity > 25 && (
-
- act('vendItem', { vendItem: item.vend, amount: 25 })
- }
- />
- )}
-
-
- ))}
+ );
+ })}
);