From d0317781e8ff9aeb8607f0d5c7a0cb9cc66ecb3a Mon Sep 17 00:00:00 2001 From: PaulMullen Date: Sat, 19 Nov 2022 14:52:22 +0000 Subject: [PATCH 01/13] smartfridge ui mostly done, making backend work --- code/game/machinery/kitchen/smartfridge.dm | 170 +++++++--- tgui/packages/tgui/interfaces/SmartFridge.tsx | 297 ++++++++++++++++++ .../tgui/styles/interfaces/SmartFridge.scss | 93 ++++++ tgui/packages/tgui/styles/main.scss | 1 + 4 files changed, 510 insertions(+), 51 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/SmartFridge.tsx create mode 100644 tgui/packages/tgui/styles/interfaces/SmartFridge.scss diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index 0435243d9a97..9e3f51ae2484 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -34,6 +34,11 @@ var/networked = FALSE var/transfer_mode = FALSE +/obj/structure/machinery/smartfridge/Initialize(mapload, ...) + . = ..() + GLOB.vending_products[/obj/item/reagent_container/glass/bottle] = 1 + GLOB.vending_products[/obj/item/storage/pill_bottle] = 1 + /obj/structure/machinery/smartfridge/proc/accept_check(var/obj/item/O as obj) if(istype(O,/obj/item/reagent_container/food/snacks/grown/) || istype(O,/obj/item/seeds/)) return 1 @@ -90,8 +95,6 @@ user.visible_message(SPAN_NOTICE("[user] has added \the [O] to \the [src]."), \ SPAN_NOTICE("You add \the [O] to \the [src].")) - nanomanager.update_uis(src) - else if(istype(O, /obj/item/storage/bag/plants)) var/obj/item/storage/bag/plants/P = O var/plants_loaded = 0 @@ -99,9 +102,9 @@ if(accept_check(G)) P.remove_from_storage(G,src) if(item_quants[G.name]) - item_quants[G.name]++ + item_quants[G.name] += G else - item_quants[G.name] = 1 + item_quants[G.name] = list(G) plants_loaded++ if(plants_loaded) @@ -111,8 +114,6 @@ if(P.contents.len > 0) to_chat(user, SPAN_NOTICE("Some items are refused.")) - nanomanager.update_uis(src) - else if(!(O.flags_item & NOBLUDGEON)) //so we can spray, scan, c4 the machine. to_chat(user, SPAN_NOTICE("\The [src] smartly refuses [O].")) return 1 @@ -128,15 +129,14 @@ if(shock(user, 100)) return - ui_interact(user) + tgui_interact(user) /obj/structure/machinery/smartfridge/proc/add_item(var/obj/item/O) O.forceMove(src) - if(item_quants[O.name]) - item_quants[O.name]++ + item_quants[O.name] += O else - item_quants[O.name] = 1 + item_quants[O.name] = list(O) /obj/structure/machinery/smartfridge/proc/add_network_item(var/obj/item/O) if(is_in_network()) @@ -153,54 +153,121 @@ //* SmartFridge Menu //********************/ -/obj/structure/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_interaction(src) - - var/data[0] - data["contents"] = null - data["wires"] = null - data["panel_open"] = panel_open - data["electrified"] = seconds_electrified > 0 - data["shoot_inventory"] = shoot_inventory - data["locked"] = locked - data["secure"] = is_secure_fridge - data["networked"] = is_in_network() - data["transfer_mode"] = transfer_mode - - var/list/items[0] +/obj/structure/machinery/smartfridge/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if (!ui) + ui = new(user, src, "SmartFridge", name) + ui.open() + +/obj/structure/machinery/smartfridge/ui_static_data(mob/user) + . = ..(user) + .["networked"] = is_in_network() + +/obj/structure/machinery/smartfridge/ui_data(mob/user) + . = list() + .["secure"] = is_secure_fridge + .["transfer_mode"] = transfer_mode + .["locked"] = locked + + var/list/wire_descriptions = get_wire_descriptions() + var/list/panel_wires = list() + for(var/wire = 1 to wire_descriptions.len) + panel_wires += list(list("desc" = wire_descriptions[wire], "cut" = isWireCut(wire))) + + .["electrical"] = list( + "electrified" = seconds_electrified > 0, + "panel_open" = panel_open, + "wires" = panel_wires, + "shoot_inventory" = shoot_inventory, + ) + + var/list/local_items = list() for (var/i=1 to length(item_quants)) - var/K = item_quants[i] - var/count = item_quants[K] - if (count > 0) - items.Add(list(list("display_name" = html_encode(capitalize(K)), "vend" = i, "quantity" = count))) + var/obj/item_index = item_quants[i] + var/list/item_list = item_quants[item_index] + var/count = length(item_list) + if(count < 1) + continue + + var/item_name = item_list[1].name + var/item_path = item_list[1].type + var/item_desc = item_list[1].desc + + var/imgid = replacetext(replacetext("[item_path]", "/obj/item/", ""), "/", "-") - if (length(items) > 0) - data["contents"] = items + var/item_type = "other" + if(ispath(item_path, /obj/item/reagent_container/glass/bottle/)) + item_type = "bottle" + else if(ispath(item_path, /obj/item/storage/pill_bottle/)) + item_type = "pills" + if (count > 0) + var/list/local_item = list( + "display_name" = capitalize(item_name), + "item" = item_path, + "index" = i, + "quantity" = count, + "image" = imgid, + "category" = item_type, + "desc" = item_desc, + ) + local_items += list(local_item) + + var/list/networked_items = list() if(is_in_network()) - var/list/networked_items = list() for (var/i=1 to length(chemical_data.shared_item_quantity)) - var/K = chemical_data.shared_item_quantity[i] - var/count = chemical_data.shared_item_quantity[K] + var/item_name = chemical_data.shared_item_quantity[i] + var/count = chemical_data.shared_item_quantity[item_name] if (count > 0) - networked_items.Add(list(list("display_name" = html_encode(capitalize(K)), "vend" = i, "quantity" = count))) + var/list/networked_item = list("display_name" = capitalize(item_name), "index" = i, "quantity" = count) + networked_items += list(networked_item) - if (length(networked_items) > 0) - data["networked_contents"] = networked_items + .["storage"] = list( + "contents" = local_items, + "networked" = networked_items, + ) - var/list/wire_descriptions = get_wire_descriptions() - var/list/panel_wires = list() - for(var/wire = 1 to wire_descriptions.len) - panel_wires += list(list("desc" = wire_descriptions[wire], "cut" = isWireCut(wire))) +/obj/structure/machinery/smartfridge/ui_assets(mob/user) + return list(get_asset_datum(/datum/asset/spritesheet/vending_products)) - if (panel_wires) - data["wires"] = panel_wires +/obj/structure/machinery/smartfridge/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + var/mob/user = usr + src.add_fingerprint(user) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "smartfridge.tmpl", src.name, 420, 500) - ui.set_initial_data(data) - ui.open() + switch(action) + if("vend") + if(!ispowered) + to_chat(user, SPAN_WARNING("[src] has no power.")) + return FALSE + if (!in_range(src, usr)) + return FALSE + if(is_secure_fridge) + if(locked == FRIDGE_LOCK_COMPLETE) + to_chat(usr, SPAN_DANGER("Access denied.")) + return FALSE + if(!allowed(usr) && locked == FRIDGE_LOCK_ID) + to_chat(usr, SPAN_DANGER("Access denied.")) + return FALSE + var/index=params["index"] + var/amount=params["amount"] + + var/K = quantity_holder[index] + var/count = length(quantity_holder[K]) + + if(count > 0) + quantity_holder[K] = max(count - amount, 0) + var/i = amount + if(!transfer_mode) + for(var/obj/O in source) + if(O.name == K) + source.Remove(O) + O.forceMove(loc) + i-- + if (i <= 0) + return TRUE /obj/structure/machinery/smartfridge/Topic(href, href_list) if (..()) return 0 @@ -381,10 +448,11 @@ return 0 for (var/O in item_quants) - if(item_quants[O] <= 0) //Try to use a record that actually has something to dump. + var/list/item_list = item_quants[O] + if(length(item_list) <= 0) //Try to use a record that actually has something to dump. continue - - item_quants[O]-- + var/obj/target_item = item_quants[1] + item_list.Remove(target_item) for(var/obj/T in contents) if(T.name == O) T.forceMove(src.loc) diff --git a/tgui/packages/tgui/interfaces/SmartFridge.tsx b/tgui/packages/tgui/interfaces/SmartFridge.tsx new file mode 100644 index 000000000000..e90646f04574 --- /dev/null +++ b/tgui/packages/tgui/interfaces/SmartFridge.tsx @@ -0,0 +1,297 @@ +import { classes } from 'common/react'; +import { useBackend, useLocalState } from '../backend'; +import { Box, Button, Icon, Flex, NoticeBox, Section, Stack, Tabs } from '../components'; +import { BoxProps } from '../components/Box'; +import { Table, TableCell, TableRow } from '../components/Table'; +import { Window } from '../layouts'; + +interface MachineElectrical { + electrified: number; + panel_open: number; + wires: WireSpec[]; +} + +interface WireSpec { + desc: string; + cut: number; +} + +interface SmartFridgeData { + secure: number; + transfer_mode: number; + locked: number; + electrical: MachineElectrical; + storage: { + contents: StorageItem[]; + networked: StorageItem[]; + }; + networked: number; +} + +interface StorageItem { + index: number; + display_name: string; + vend: number; + quantity: number; + item: string; + image: string; + category: string; +} + +const ContentsTable = ( + props: { isLocal: boolean; items: StorageItem[] }, + context +) => { + return ( + + {props.items + .sort((a, b) => a.display_name.localeCompare(b.display_name)) + .map((x) => ( + + + + ))} +
+ ); +}; + +const Contents = ( + props: { isLocal: boolean; items: StorageItem[]; title: string }, + context +) => { + const [tabIndex, setTabIndex] = useLocalState(context, 'contentsTab', 'all'); + const allItems = props.items; + + if (allItems.length === 0) { + return ( +
+ No items present +
+ ); + } + + const categories = new Map(); + categories.set('all', allItems); + allItems.forEach((x) => { + const categoryArray = categories.get(x.category) ?? new Array(); + categoryArray.push(x); + categories.set(x.category, categoryArray); + }); + + const categoryIterable = Array.from(categories.entries()); + return ( +
+ + {categoryIterable + .sort((a, b) => a[0].localeCompare(b[0])) + .map((value) => { + const key = value[0]; + const items = value[1]; + return ( + setTabIndex(key)}> + {key} ({items.length}) + + ); + })} + + + {categoryIterable.map((x) => { + if (tabIndex !== x[0]) { + return undefined; + } + return ( + + ); + })} +
+ ); +}; + +const ContentItem = ( + props: { isLocal: boolean; item: StorageItem }, + context +) => { + const { data, act } = useBackend(context); + const { item } = props; + return ( + <> + + + + {item.quantity} + + + + + {props.isLocal && } + {!props.isLocal && } + + + + + + ); +}; + +const ElectricalPanelClosed = (props: BoxProps, context) => { + const { data } = useBackend(context); + return ( + + + + + + + + + + + + + + + + + + + Electrical hazard authorised personnel only + + + + + + + + + + + + + + + + + + + ); +}; + +const WireControl = (props: { wire: WireSpec }, context) => { + return ( + <> + {props.wire.desc} + + {props.wire.cut === 0 && } + {props.wire.cut === 1 && } + + + ); +}; + +const ElectricalPanelOpen = (props: BoxProps, context) => { + const { data } = useBackend(context); + return ( + + + + + {data.electrical.wires.map((x) => ( + + + + ))} +
+
+ + + +
+
+ ); +}; + +const ElectricalPanel = (props, context) => { + const { data } = useBackend(context); + const isOpen = data.electrical.panel_open === 1; + return ( +
+ {!isOpen && ( + <> +
+ +
+
+ +
+ + )} + {isOpen && ( + <> +
+ +
+
+ +
+ + )} +
+ ); +}; + +export const SmartFridge = (_, context) => { + const { data } = useBackend(context); + return ( + + + + {data.secure && ( + + Smart fridge is secure + + )} + + + + {data.networked === 1 && ( + + + + )} + + + + + + + ); +}; diff --git a/tgui/packages/tgui/styles/interfaces/SmartFridge.scss b/tgui/packages/tgui/styles/interfaces/SmartFridge.scss new file mode 100644 index 000000000000..c7c054880260 --- /dev/null +++ b/tgui/packages/tgui/styles/interfaces/SmartFridge.scss @@ -0,0 +1,93 @@ +$electrical-width: 300px; + +.SmartFridge { + .ItemIconCell { + width: 32px; + } + .ItemIcon { + min-width: 32px; + max-width: 32px; + max-height: 32px; + margin-top: -6px; + margin-bottom: -6px; + } + + .ContentsTable { + .ContentRow { + margin-top: 2px; + margin-bottom: 2px; + &:nth-child(even) { + background-color: black; + } + } + } + + .VendButton { + width: 100%; + display: block; + .Button__content { + align-self: flex-start; + text-align: left; + margin-top: -2px; + margin-bottom: -1px; + } + } + + .ElectricalAccessPanel { + border-bottom: 2px solid #606060; + border-left: 2px solid #606060; + border-right: 2px solid grey; + border-top: 2px solid grey; + width: $electrical-width; + display: flex; + flex-direction: row; + overflow-x: hidden; + overflow-y: hidden; + + .PanelClosed { + width: $electrical-width; + height: 100%; + } + .PanelOpen { + width: $electrical-width; + height: 100%; + padding: 6px; + } + .ElectricalSafetySign { + height: 100%; + } + span { + text-align: center; + } + .WarningIcon { + border: 2px solid black; + padding: 3px; + font-weight: bold; + } + .OpenSafetySign { + border-top: 1px solid black; + margin-bottom: -6px; + margin-left: -6px; + margin-right: -6px; + } + .WireLabel { + overflow: auto; + word-wrap: break-word; + width: 100px; + } + .WirePanel { + display: inline-table; + span { + border: 2px solid black; + } + } + .WireControl { + height: 50px; + } + .WireSketch { + border: 1px solid white; + height: 100%; + width: 2px; + } + } +} diff --git a/tgui/packages/tgui/styles/main.scss b/tgui/packages/tgui/styles/main.scss index 9bf82bee4467..52e2a57874de 100644 --- a/tgui/packages/tgui/styles/main.scss +++ b/tgui/packages/tgui/styles/main.scss @@ -59,6 +59,7 @@ @include meta.load-css('./interfaces/ResearchTerminal.scss'); @include meta.load-css('./interfaces/Roulette.scss'); @include meta.load-css('./interfaces/Safe.scss'); +@include meta.load-css('./interfaces/SmartFridge.scss'); @include meta.load-css('./interfaces/SquadInfo.scss'); @include meta.load-css('./interfaces/TachyonArray.scss'); @include meta.load-css('./interfaces/Techweb.scss'); From d824a24bbfa53ddc9b8860e59bfa8b68a914ba8e Mon Sep 17 00:00:00 2001 From: PaulMullen Date: Sat, 19 Nov 2022 19:47:41 +0000 Subject: [PATCH 02/13] basic vending working --- code/game/machinery/kitchen/smartfridge.dm | 28 +++++------ tgui/packages/tgui/interfaces/SmartFridge.tsx | 46 +++++++++++++------ .../tgui/styles/interfaces/SmartFridge.scss | 8 ++++ 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index 9e3f51ae2484..d05f7630dc57 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -183,7 +183,7 @@ var/list/local_items = list() for (var/i=1 to length(item_quants)) - var/obj/item_index = item_quants[i] + var/item_index = item_quants[i] var/list/item_list = item_quants[item_index] var/count = length(item_list) if(count < 1) @@ -254,20 +254,20 @@ var/index=params["index"] var/amount=params["amount"] - var/K = quantity_holder[index] - var/count = length(quantity_holder[K]) + var/item_index = item_quants[index] + var/list/item_list = item_quants[item_index] + var/count = length(item_list) - if(count > 0) - quantity_holder[K] = max(count - amount, 0) - var/i = amount - if(!transfer_mode) - for(var/obj/O in source) - if(O.name == K) - source.Remove(O) - O.forceMove(loc) - i-- - if (i <= 0) - return TRUE + if(count <= 0) + return FALSE + + var/i = amount + for(var/obj/item in item_list) + item_list.Remove(item) + item.forceMove(loc) + i-- + if (i <= 0) + return TRUE /obj/structure/machinery/smartfridge/Topic(href, href_list) if (..()) return 0 diff --git a/tgui/packages/tgui/interfaces/SmartFridge.tsx b/tgui/packages/tgui/interfaces/SmartFridge.tsx index e90646f04574..de570cfcd147 100644 --- a/tgui/packages/tgui/interfaces/SmartFridge.tsx +++ b/tgui/packages/tgui/interfaces/SmartFridge.tsx @@ -135,7 +135,7 @@ const ContentItem = ( - {props.isLocal && } + {props.isLocal && } @@ -155,12 +155,16 @@ const ElectricalPanelClosed = (props: BoxProps, context) => { props.className, ])}> - - + + @@ -169,21 +173,33 @@ const ElectricalPanelClosed = (props: BoxProps, context) => { - - + + - + - Electrical hazard authorised personnel only - - - + + Electrical hazard authorised
+ personnel only +
- - + + @@ -200,7 +216,7 @@ const ElectricalPanelClosed = (props: BoxProps, context) => { const WireControl = (props: { wire: WireSpec }, context) => { return ( <> - {props.wire.desc} + {props.wire.desc} {props.wire.cut === 0 && } {props.wire.cut === 1 && } @@ -221,7 +237,7 @@ const ElectricalPanelOpen = (props: BoxProps, context) => { {data.electrical.wires.map((x) => ( - + ))} diff --git a/tgui/packages/tgui/styles/interfaces/SmartFridge.scss b/tgui/packages/tgui/styles/interfaces/SmartFridge.scss index c7c054880260..54e7cd2db3e7 100644 --- a/tgui/packages/tgui/styles/interfaces/SmartFridge.scss +++ b/tgui/packages/tgui/styles/interfaces/SmartFridge.scss @@ -57,12 +57,15 @@ $electrical-width: 300px; height: 100%; } span { + display: flex; text-align: center; } .WarningIcon { border: 2px solid black; padding: 3px; font-weight: bold; + width: 200px; + height: 100%; } .OpenSafetySign { border-top: 1px solid black; @@ -77,6 +80,7 @@ $electrical-width: 300px; } .WirePanel { display: inline-table; + margin-bottom: 6px; span { border: 2px solid black; } @@ -91,3 +95,7 @@ $electrical-width: 300px; } } } + +.Test { + border: 4px solid red; +} From 9aa4912fef897f17097e822547806d14b0715d83 Mon Sep 17 00:00:00 2001 From: PaulMullen Date: Sat, 19 Nov 2022 23:40:02 +0000 Subject: [PATCH 03/13] electrical panel in own file, smart fridge good to go --- code/game/machinery/kitchen/smartfridge.dm | 214 +++++++++--------- tgui/packages/tgui/interfaces/SmartFridge.tsx | 166 +------------- .../interfaces/common/ElectricalPanel.tsx | 184 +++++++++++++++ .../tgui/styles/interfaces/SmartFridge.scss | 68 ------ .../interfaces/common/ElectricalPanel.scss | 100 ++++++++ tgui/packages/tgui/styles/main.scss | 1 + 6 files changed, 398 insertions(+), 335 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/common/ElectricalPanel.tsx create mode 100644 tgui/packages/tgui/styles/interfaces/common/ElectricalPanel.scss diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index d05f7630dc57..91693f6022d2 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -91,7 +91,7 @@ if(accept_check(O)) if(user.drop_held_item()) - add_item(O) + add_item(item_quants, O) user.visible_message(SPAN_NOTICE("[user] has added \the [O] to \the [src]."), \ SPAN_NOTICE("You add \the [O] to \the [src].")) @@ -131,21 +131,16 @@ tgui_interact(user) -/obj/structure/machinery/smartfridge/proc/add_item(var/obj/item/O) +/obj/structure/machinery/smartfridge/proc/add_item(var/list/target, var/obj/item/O) O.forceMove(src) - if(item_quants[O.name]) - item_quants[O.name] += O + if(target[O.name]) + target[O.name] += O else - item_quants[O.name] = list(O) + target[O.name] = list(O) /obj/structure/machinery/smartfridge/proc/add_network_item(var/obj/item/O) if(is_in_network()) - chemical_data.shared_item_storage.Add(O) - - if(chemical_data.shared_item_quantity[O.name]) - chemical_data.shared_item_quantity[O.name]++ - else - chemical_data.shared_item_quantity[O.name] = 1 + add_item(chemical_data.shared_item_storage, O) return TRUE return FALSE @@ -159,6 +154,14 @@ ui = new(user, src, "SmartFridge", name) ui.open() +/obj/structure/machinery/smartfridge/ui_state(mob/user) + return GLOB.not_incapacitated_and_adjacent_strict_state + +/obj/structure/machinery/smartfridge/ui_status(mob/user, datum/ui_state/state) + . = ..() + if(inoperable()) + return UI_CLOSE + /obj/structure/machinery/smartfridge/ui_static_data(mob/user) . = ..(user) .["networked"] = is_in_network() @@ -179,6 +182,7 @@ "panel_open" = panel_open, "wires" = panel_wires, "shoot_inventory" = shoot_inventory, + "powered" = ispowered, ) var/list/local_items = list() @@ -215,11 +219,34 @@ var/list/networked_items = list() if(is_in_network()) - for (var/i=1 to length(chemical_data.shared_item_quantity)) - var/item_name = chemical_data.shared_item_quantity[i] - var/count = chemical_data.shared_item_quantity[item_name] + for (var/i=1 to length(chemical_data.shared_item_storage)) + var/item_index = chemical_data.shared_item_storage[i] + var/list/item_list = chemical_data.shared_item_storage[item_index] + var/count = length(item_list) + if(count < 1) + continue + var/item_name = item_list[1].name + var/item_path = item_list[1].type + var/item_desc = item_list[1].desc + + var/imgid = replacetext(replacetext("[item_path]", "/obj/item/", ""), "/", "-") + + var/item_type = "other" + if(ispath(item_path, /obj/item/reagent_container/glass/bottle/)) + item_type = "bottle" + else if(ispath(item_path, /obj/item/storage/pill_bottle/)) + item_type = "pills" + if (count > 0) - var/list/networked_item = list("display_name" = capitalize(item_name), "index" = i, "quantity" = count) + var/list/networked_item = list( + "display_name" = capitalize(item_name), + "item" = item_path, + "index" = i, + "quantity" = count, + "image" = imgid, + "category" = item_type, + "desc" = item_desc, + ) networked_items += list(networked_item) .["storage"] = list( @@ -254,8 +281,13 @@ var/index=params["index"] var/amount=params["amount"] - var/item_index = item_quants[index] - var/list/item_list = item_quants[item_index] + var/list/target_list = item_quants + if(params["isLocal"] == 0) + target_list = chemical_data.shared_item_storage + + var/item_index = target_list[index] + var/list/item_list = target_list[item_index] + var/count = length(item_list) if(count <= 0) @@ -265,124 +297,80 @@ for(var/obj/item in item_list) item_list.Remove(item) item.forceMove(loc) + user.put_in_any_hand_if_possible(item, disable_warning = TRUE) i-- if (i <= 0) return TRUE - -/obj/structure/machinery/smartfridge/Topic(href, href_list) - if (..()) return 0 - - var/mob/user = usr - var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") - - src.add_fingerprint(user) - - if (href_list["close"]) - user.unset_interaction() - ui.close() - return FALSE - - if (href_list["toggletransfer"]) - if(is_secure_fridge) - if(locked == FRIDGE_LOCK_COMPLETE) - to_chat(usr, SPAN_DANGER("Access denied.")) - return FALSE - if(!allowed(usr) && locked == FRIDGE_LOCK_ID) - to_chat(usr, SPAN_DANGER("Access denied.")) - return FALSE - if(is_in_network() && !transfer_mode) - transfer_mode = TRUE - else - transfer_mode = FALSE - return TRUE - - if (href_list["vend"]) - if(!ispowered) - to_chat(usr, SPAN_WARNING("[src] has no power.")) - return FALSE - if (!in_range(src, usr)) - return FALSE - if(is_secure_fridge) - if(locked == FRIDGE_LOCK_COMPLETE) - to_chat(usr, SPAN_DANGER("Access denied.")) + if("transfer") + if(!ispowered) + to_chat(user, SPAN_WARNING("[src] has no power.")) return FALSE - if(!allowed(usr) && locked == FRIDGE_LOCK_ID) - to_chat(usr, SPAN_DANGER("Access denied.")) + if (!in_range(src, usr)) return FALSE - var/index = text2num(href_list["vend"]) - var/amount = text2num(href_list["amount"]) - var/from_network = text2num(href_list["network"]) - + if(is_secure_fridge) + if(locked == FRIDGE_LOCK_COMPLETE) + to_chat(usr, SPAN_DANGER("Access denied.")) + return FALSE + if(!allowed(usr) && locked == FRIDGE_LOCK_ID) + to_chat(usr, SPAN_DANGER("Access denied.")) + return FALSE + var/index=params["index"] + var/amount=params["amount"] - // Sanity check, there are probably ways to press the button when it shouldn't be possible. - var/list/source = contents - var/list/quantity_holder = item_quants - // Validate we can reach the shared network. - transfer_mode = transfer_mode && is_in_network() + var/source = item_quants + var/target = chemical_data.shared_item_storage + if(params["isLocal"] == 0) + source = chemical_data.shared_item_storage + target = item_quants - if(is_in_network() && from_network) - source = chemical_data.shared_item_storage - quantity_holder = chemical_data.shared_item_quantity + var/item_index = source[index] + var/list/item_list = source[item_index] + var/count = length(item_list) - var/K = quantity_holder[index] - var/count = quantity_holder[K] + if(count <= 0) + return FALSE - if(count > 0) - quantity_holder[K] = max(count - amount, 0) var/i = amount - if(!transfer_mode) - for(var/obj/O in source) - if(O.name == K) - source.Remove(O) - O.forceMove(loc) - i-- - if (i <= 0) - return TRUE - else - for(var/obj/O in source) - if(O.name == K) - if(from_network) - contents.Add(O) - item_quants[K]++ - source.Remove(O) - else - chemical_data.shared_item_storage.Add(O) - chemical_data.shared_item_quantity[K]++ - source.Remove(O) - i-- - if(i <= 0) - return TRUE - - return TRUE - - if (panel_open) - if (href_list["cutwire"]) - var/obj/item/held_item = usr.get_held_item() + for(var/obj/item in item_list) + item_list.Remove(item) + add_item(target, item) + i-- + if (i <= 0) + return TRUE + if("cutwire") + if(!panel_open) + return FALSE + var/obj/item/held_item = user.get_held_item() if (!held_item || !HAS_TRAIT(held_item, TRAIT_TOOL_WIRECUTTERS)) to_chat(user, "You need wirecutters!") return TRUE - var/wire = text2num(href_list["cutwire"]) - if (isWireCut(wire)) - mend(wire) - else - cut(wire) + var/wire = params["wire"] + cut(wire) return TRUE - - if (href_list["pulsewire"]) - var/obj/item/held_item = usr.get_held_item() + if("fixwire") + if(!panel_open) + return FALSE + var/obj/item/held_item = user.get_held_item() + if (!held_item || !HAS_TRAIT(held_item, TRAIT_TOOL_WIRECUTTERS)) + to_chat(user, "You need wirecutters!") + return TRUE + var/wire = params["wire"] + mend(wire) + return TRUE + if("pulsewire") + if(!panel_open) + return FALSE + var/obj/item/held_item = user.get_held_item() if (!held_item || !HAS_TRAIT(held_item, TRAIT_TOOL_MULTITOOL)) - to_chat(usr, "You need a multitool!") + to_chat(user, "You need multitool!") return TRUE - - var/wire = text2num(href_list["pulsewire"]) + var/wire = params["wire"] if (isWireCut(wire)) to_chat(usr, "You can't pulse a cut wire.") return TRUE - pulse(wire) return TRUE - return FALSE //************* diff --git a/tgui/packages/tgui/interfaces/SmartFridge.tsx b/tgui/packages/tgui/interfaces/SmartFridge.tsx index de570cfcd147..01bbb4603b11 100644 --- a/tgui/packages/tgui/interfaces/SmartFridge.tsx +++ b/tgui/packages/tgui/interfaces/SmartFridge.tsx @@ -1,26 +1,14 @@ import { classes } from 'common/react'; import { useBackend, useLocalState } from '../backend'; -import { Box, Button, Icon, Flex, NoticeBox, Section, Stack, Tabs } from '../components'; -import { BoxProps } from '../components/Box'; +import { Button, Icon, NoticeBox, Section, Stack, Tabs } from '../components'; import { Table, TableCell, TableRow } from '../components/Table'; import { Window } from '../layouts'; - -interface MachineElectrical { - electrified: number; - panel_open: number; - wires: WireSpec[]; -} - -interface WireSpec { - desc: string; - cut: number; -} +import { ElectricalPanel } from './common/ElectricalPanel'; interface SmartFridgeData { secure: number; transfer_mode: number; locked: number; - electrical: MachineElectrical; storage: { contents: StorageItem[]; networked: StorageItem[]; @@ -116,6 +104,7 @@ const ContentItem = ( ) => { const { data, act } = useBackend(context); const { item } = props; + const itemref = { 'index': item.index, 'amount': 1, isLocal: props.isLocal }; return ( <> @@ -130,14 +119,18 @@ const ContentItem = ( preserveWhitespace textAlign="center" icon="circle-down" - onClick={() => act('vend', { 'index': item.index, 'amount': 1 })}> + onClick={() => act('vend', itemref)}> {item.display_name} - - {props.isLocal && } - + {data.networked === 1 && ( + + } - {props.wire.cut === 1 && } - - - ); -}; - -const ElectricalPanelOpen = (props: BoxProps, context) => { - const { data } = useBackend(context); - return ( - - - -
- {data.electrical.wires.map((x) => ( - - - - ))} -
-
- - - -
- - ); -}; - -const ElectricalPanel = (props, context) => { - const { data } = useBackend(context); - const isOpen = data.electrical.panel_open === 1; - return ( -
- {!isOpen && ( - <> -
- -
-
- -
- - )} - {isOpen && ( - <> -
- -
-
- -
- - )} -
- ); -}; - export const SmartFridge = (_, context) => { const { data } = useBackend(context); return ( diff --git a/tgui/packages/tgui/interfaces/common/ElectricalPanel.tsx b/tgui/packages/tgui/interfaces/common/ElectricalPanel.tsx new file mode 100644 index 000000000000..c5d6ce0f765d --- /dev/null +++ b/tgui/packages/tgui/interfaces/common/ElectricalPanel.tsx @@ -0,0 +1,184 @@ +import { classes } from 'common/react'; +import { useBackend } from '../../backend'; +import { Box, Button, Icon, Flex, NoticeBox } from '../../components'; +import { BoxProps } from '../../components/Box'; +import { Table, TableCell, TableRow } from '../../components/Table'; + +interface ElectricalData { + electrical: MachineElectrical; +} + +interface MachineElectrical { + electrified: number; + panel_open: number; + wires: WireSpec[]; + powered: number; +} + +interface WireSpec { + desc: string; + cut: number; +} + +const ElectricalPanelClosed = (props: BoxProps, context) => { + return ( + + + + + + + + + + + + + + + + + + + + Electrical hazard authorised
+ personnel only +
+
+
+
+ + + + + + + + + + +
+
+ ); +}; + +const WireControl = (props: { wire: WireSpec; index: number }, context) => { + const { data, act } = useBackend(context); + const target = props.index + 1; + return ( + <> + {props.wire.desc} + +
+ + + {props.wire.cut === 0 && ( +