mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-13 08:56:49 +01:00
SmartFridge Fixes (#21957)
- moves smartfridge icon generation to ui_static_data and adds a cache (inspired by / ported in part from tgstation/tgstation#48394 ) - because we cache it, we can now gFI the items and so we fix certain things not having icons - bottlemaxxers stay winning, etc. i actually tested this pr and it works great, upvotes to the left <img width="1197" height="749" alt="image" src="https://github.com/user-attachments/assets/7e41dce0-47aa-4fd2-9e18-cc17758a53de" />
This commit is contained in:
@@ -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("<b>[user]</b> 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("<b>[user]</b> 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
|
||||
|
||||
@@ -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."
|
||||
@@ -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 (
|
||||
<Section>
|
||||
<Box>
|
||||
{itemListSorted.map((item) => (
|
||||
<Box
|
||||
key={`${item.vend}-${item.display_name}`}
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
padding: '4px 0',
|
||||
}}
|
||||
>
|
||||
{/* Item icon */}
|
||||
{item.icon ? (
|
||||
{itemListSorted.map((item) => {
|
||||
const quantity = itemStock(item);
|
||||
return (
|
||||
<Box
|
||||
key={`${item.vend}-${item.display_name}`}
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
padding: '4px 0',
|
||||
}}
|
||||
>
|
||||
{/* Item icon */}
|
||||
{item.icon ? (
|
||||
<Box
|
||||
as="img"
|
||||
src={`data:image/png;base64,${item.icon}`}
|
||||
style={{ width: '32px', height: '32px', flexShrink: 0 }}
|
||||
/>
|
||||
) : null}
|
||||
{/* Name stuff */}
|
||||
<Box
|
||||
as="img"
|
||||
src={`data:image/png;base64,${item.icon}`}
|
||||
style={{ width: '32px', height: '32px', flexShrink: 0 }}
|
||||
/>
|
||||
) : null}
|
||||
{/* Name stuff */}
|
||||
<Box
|
||||
style={{
|
||||
flex: 2,
|
||||
minWidth: 0,
|
||||
whiteSpace: 'normal',
|
||||
overflowWrap: 'break-word',
|
||||
wordBreak: 'break-word',
|
||||
}}
|
||||
>
|
||||
{item.display_name}
|
||||
style={{
|
||||
flex: 2,
|
||||
minWidth: 0,
|
||||
whiteSpace: 'normal',
|
||||
overflowWrap: 'break-word',
|
||||
wordBreak: 'break-word',
|
||||
}}
|
||||
>
|
||||
{item.display_name}
|
||||
</Box>
|
||||
{/* Amount */}x{quantity}
|
||||
{/* Vend buttons */}
|
||||
<Box
|
||||
style={{
|
||||
flex: 1.2,
|
||||
minWidth: 0,
|
||||
whiteSpace: 'normal',
|
||||
overflowWrap: 'break-word',
|
||||
wordBreak: 'break-word',
|
||||
}}
|
||||
>
|
||||
{quantity > 0 && (
|
||||
<Button
|
||||
content="x1"
|
||||
icon="arrow-alt-circle-down"
|
||||
width="50px"
|
||||
onClick={() =>
|
||||
act('vendItem', { vendItem: item.vend, amount: 1 })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{quantity > 5 && (
|
||||
<Button
|
||||
content="x5"
|
||||
icon="arrow-alt-circle-down"
|
||||
width="50px"
|
||||
onClick={() =>
|
||||
act('vendItem', { vendItem: item.vend, amount: 5 })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{quantity > 10 && (
|
||||
<Button
|
||||
content="x10"
|
||||
icon="arrow-alt-circle-down"
|
||||
width="50px"
|
||||
onClick={() =>
|
||||
act('vendItem', { vendItem: item.vend, amount: 10 })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{quantity > 25 && (
|
||||
<Button
|
||||
content="x25"
|
||||
icon="arrow-alt-circle-down"
|
||||
width="50px"
|
||||
onClick={() =>
|
||||
act('vendItem', { vendItem: item.vend, amount: 25 })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
{/* Amount */}x{item.quantity}
|
||||
{/* Vend buttons */}
|
||||
<Box
|
||||
style={{
|
||||
flex: 1.2,
|
||||
minWidth: 0,
|
||||
whiteSpace: 'normal',
|
||||
overflowWrap: 'break-word',
|
||||
wordBreak: 'break-word',
|
||||
}}
|
||||
>
|
||||
{item.quantity > 0 && (
|
||||
<Button
|
||||
content="x1"
|
||||
icon="arrow-alt-circle-down"
|
||||
width="50px"
|
||||
onClick={() =>
|
||||
act('vendItem', { vendItem: item.vend, amount: 1 })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{item.quantity > 5 && (
|
||||
<Button
|
||||
content="x5"
|
||||
icon="arrow-alt-circle-down"
|
||||
width="50px"
|
||||
onClick={() =>
|
||||
act('vendItem', { vendItem: item.vend, amount: 5 })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{item.quantity > 10 && (
|
||||
<Button
|
||||
content="x10"
|
||||
icon="arrow-alt-circle-down"
|
||||
width="50px"
|
||||
onClick={() =>
|
||||
act('vendItem', { vendItem: item.vend, amount: 10 })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{item.quantity > 25 && (
|
||||
<Button
|
||||
content="x25"
|
||||
icon="arrow-alt-circle-down"
|
||||
width="50px"
|
||||
onClick={() =>
|
||||
act('vendItem', { vendItem: item.vend, amount: 25 })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user