From ab1136909cb93bc9c2a82c8408e132d1b7daf48c Mon Sep 17 00:00:00 2001
From: mcbalaam <104003807+mcbalaam@users.noreply.github.com>
Date: Wed, 3 Sep 2025 04:55:12 +0300
Subject: [PATCH] Improves the ore silo UI (#92460)
## About The Pull Request
Improves the ore silo UI, continuing
https://github.com/tgstation/tgstation/pull/91142
Before:
After:
All sources of silo material withdrawal are now consistent with naming
to get properly color coded, which helps with looking for stuff.
## Why It's Good For The Game
Better UI readability, more consistent logs
## Changelog
:cl:
qol: Color coded and consistent material silo logs
/:cl:
---------
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
---
.../components/material/remote_materials.dm | 2 +-
code/game/objects/items/rcd/RHD.dm | 2 +-
code/modules/mining/machine_redemption.dm | 2 +-
code/modules/mining/machine_silo.dm | 4 +-
.../mob/living/silicon/robot/robot_model.dm | 2 +-
.../modules/research/machinery/_production.dm | 2 +-
.../modules/vehicles/mecha/mech_fabricator.dm | 2 +-
.../modules/wiremod/core/component_printer.dm | 6 +-
tgui/packages/tgui/interfaces/OreSilo.tsx | 233 +++++++++++++-----
.../tgui/styles/interfaces/OreSilo.scss | 23 --
tgui/packages/tgui/styles/main.scss | 1 -
11 files changed, 183 insertions(+), 96 deletions(-)
delete mode 100644 tgui/packages/tgui/styles/interfaces/OreSilo.scss
diff --git a/code/datums/components/material/remote_materials.dm b/code/datums/components/material/remote_materials.dm
index 6e37ea327e3..1d4d89d819b 100644
--- a/code/datums/components/material/remote_materials.dm
+++ b/code/datums/components/material/remote_materials.dm
@@ -233,7 +233,7 @@ handles linking back and forth.
* name- For logging only. the design you are trying to build e.g. matter bin, etc.
* user_data - in the form rendered by ID_DATA(user), for material logging and (if this component is connected to a silo), permission checking
*/
-/datum/component/remote_materials/proc/use_materials(list/mats, coefficient = 1, multiplier = 1, action = "build", name = "design", alist/user_data)
+/datum/component/remote_materials/proc/use_materials(list/mats, coefficient = 1, multiplier = 1, action = "processed", name = "design", alist/user_data)
if(!can_use_resource(user_data = user_data))
return 0
diff --git a/code/game/objects/items/rcd/RHD.dm b/code/game/objects/items/rcd/RHD.dm
index b303f300c6b..33874d87c68 100644
--- a/code/game/objects/items/rcd/RHD.dm
+++ b/code/game/objects/items/rcd/RHD.dm
@@ -199,7 +199,7 @@
if(user)
balloon_alert(user, "not enough silo material!")
return FALSE
- silo_mats.use_materials(list(/datum/material/iron = SILO_USE_AMOUNT), multiplier = amount, action = "build", name = "consume", user_data = ID_DATA(user))
+ silo_mats.use_materials(list(/datum/material/iron = SILO_USE_AMOUNT), multiplier = amount, action = "RESTOCKED", name = "x restocked an RCD", user_data = ID_DATA(user))
return TRUE
/obj/item/construction/ui_static_data(mob/user)
diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm
index 465bfff2708..c6b9d1a0484 100644
--- a/code/modules/mining/machine_redemption.dm
+++ b/code/modules/mining/machine_redemption.dm
@@ -344,7 +344,7 @@
var/amount = round(min(text2num(params["sheets"]), 50, can_smelt_alloy(alloy)))
if(amount < 1) //no negative mats
return
- materials.use_materials(alloy.materials, multiplier = amount, action = "released", name = "sheets", user_data = ID_DATA(usr))
+ materials.use_materials(alloy.materials, multiplier = amount, action = "withdrawn", name = "sheets", user_data = ID_DATA(usr))
var/output
if(ispath(alloy.build_path, /obj/item/stack/sheet))
output = new alloy.build_path(src, amount)
diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm
index 467b7786e08..743f3eec6f7 100644
--- a/code/modules/mining/machine_silo.dm
+++ b/code/modules/mining/machine_silo.dm
@@ -144,14 +144,14 @@
/obj/machinery/ore_silo/proc/on_item_consumed(datum/component/material_container/container, obj/item/item_inserted, last_inserted_id, mats_consumed, amount_inserted, atom/context, alist/user_data)
SIGNAL_HANDLER
- silo_log(context, "DEPOSIT", amount_inserted, item_inserted.name, mats_consumed, user_data)
+ silo_log(context, "DEPOSITED", amount_inserted, item_inserted.name, mats_consumed, user_data)
SEND_SIGNAL(context, COMSIG_SILO_ITEM_CONSUMED, container, item_inserted, last_inserted_id, mats_consumed, amount_inserted)
/obj/machinery/ore_silo/proc/log_sheets_ejected(datum/component/material_container/container, obj/item/stack/sheet/sheets, atom/context, alist/user_data)
SIGNAL_HANDLER
- silo_log(context, "EJECT", -sheets.amount * SHEET_MATERIAL_AMOUNT, "[sheets.singular_name]", sheets.custom_materials, user_data)
+ silo_log(context, "WITHDRAWN", -sheets.amount * SHEET_MATERIAL_AMOUNT, "[sheets.name]", sheets.custom_materials, user_data)
/obj/machinery/ore_silo/screwdriver_act(mob/living/user, obj/item/tool)
. = ITEM_INTERACT_BLOCKING
diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm
index d473cf205fd..866602cc718 100644
--- a/code/modules/mob/living/silicon/robot/robot_model.dm
+++ b/code/modules/mob/living/silicon/robot/robot_model.dm
@@ -213,7 +213,7 @@
if(!to_stock) //Nothing for us in the silo
continue
- storage_datum.energy += charger.materials.use_materials(list(GET_MATERIAL_REF(storage_datum.mat_type) = to_stock), action = "resupplied", name = "units", user_data = ID_DATA(robot))
+ storage_datum.energy += charger.materials.use_materials(list(GET_MATERIAL_REF(storage_datum.mat_type) = to_stock), action = "restocked", name = "units", user_data = ID_DATA(robot))
charger.balloon_alert(robot, "+ [to_stock]u [initial(storage_datum.mat_type.name)]")
playsound(charger, 'sound/items/weapons/gun/general/mag_bullet_insert.ogg', 50, vary = FALSE)
return
diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm
index 7a89429333d..9fc61e3d135 100644
--- a/code/modules/research/machinery/_production.dm
+++ b/code/modules/research/machinery/_production.dm
@@ -423,7 +423,7 @@
say("Unable to continue production, missing materials.")
finalize_build()
return
- materials.use_materials(design_materials, material_cost_coefficient, is_stack ? items_remaining : 1, "built", "[design.name]", user_data = user_data)
+ materials.use_materials(design_materials, material_cost_coefficient, is_stack ? items_remaining : 1, "processed", "[design.name]", user_data = user_data)
var/atom/movable/created
if(is_stack)
diff --git a/code/modules/vehicles/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm
index c5318bc3cd6..a87740d769d 100644
--- a/code/modules/vehicles/mecha/mech_fabricator.dm
+++ b/code/modules/vehicles/mecha/mech_fabricator.dm
@@ -236,7 +236,7 @@
say("Not enough resources. Processing stopped.")
return FALSE
- rmat.use_materials(D.materials, component_coeff, 1, "built", "[D.name]", user_data)
+ rmat.use_materials(D.materials, component_coeff, 1, "processed", "[D.name]", user_data)
being_built = D
build_finish = world.time + get_construction_time_w_coeff(initial(D.construction_time))
build_start = world.time
diff --git a/code/modules/wiremod/core/component_printer.dm b/code/modules/wiremod/core/component_printer.dm
index 343f0db5e6f..bece40978eb 100644
--- a/code/modules/wiremod/core/component_printer.dm
+++ b/code/modules/wiremod/core/component_printer.dm
@@ -132,7 +132,7 @@
if (!materials.mat_container.has_materials(design.materials, efficiency_coeff))
return
- materials.use_materials(design.materials, efficiency_coeff, 1, "printed", "[design.name]", user_data)
+ materials.use_materials(design.materials, efficiency_coeff, 1, "processed", "[design.name]", user_data)
return new design.build_path(drop_location())
/obj/machinery/component_printer/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
@@ -160,7 +160,7 @@
balloon_alert_to_viewers("printed [design.name]")
- materials.use_materials(design.materials, efficiency_coeff, 1, "printed", "[design.name]", user_data)
+ materials.use_materials(design.materials, efficiency_coeff, 1, "processed", "[design.name]", user_data)
var/atom/printed_design = new design.build_path(drop_location())
printed_design.pixel_x = printed_design.base_pixel_x + rand(-5, 5)
printed_design.pixel_y = printed_design.base_pixel_y + rand(-5, 5)
@@ -408,7 +408,7 @@
say("Not enough materials.")
return TRUE
- materials.use_materials(design["materials"], efficiency_coeff, 1, design["name"], design["materials"], user_card)
+ materials.use_materials(design["materials"], efficiency_coeff, 1, "processed", design["name"], user_card)
print_module(design)
balloon_alert_to_viewers("printed [design["name"]]")
if ("remove_mat")
diff --git a/tgui/packages/tgui/interfaces/OreSilo.tsx b/tgui/packages/tgui/interfaces/OreSilo.tsx
index 61d4f01373a..9e48a87c0ae 100644
--- a/tgui/packages/tgui/interfaces/OreSilo.tsx
+++ b/tgui/packages/tgui/interfaces/OreSilo.tsx
@@ -3,16 +3,17 @@ import {
Box,
Button,
Collapsible,
- Divider,
Icon,
Image,
LabeledList,
NoticeBox,
Section,
Stack,
+ Table,
Tabs,
Tooltip,
VirtualList,
+ Input
} from 'tgui-core/components';
import { type BooleanLike, classes } from 'tgui-core/react';
import { capitalize } from 'tgui-core/string';
@@ -22,6 +23,8 @@ import { Window } from '../layouts';
import { MaterialAccessBar } from './Fabrication/MaterialAccessBar';
import type { Material } from './Fabrication/Types';
+import { useFuzzySearch } from 'tgui-core/fuzzysearch';
+
type Machine = {
name: string;
icon: string;
@@ -68,6 +71,13 @@ type Data = {
id_required: BooleanLike;
};
+const actionToColor = {
+ DEPOSITED: 'green',
+ WITHDRAWN: 'red',
+ PROCESSED: 'blue',
+ RESTOCKED: 'purple',
+};
+
export const OreSilo = (props: Data) => {
const { act, data } = useBackend();
const { SHEET_MATERIAL_AMOUNT, machines, logs } = data;
@@ -104,12 +114,7 @@ export const OreSilo = (props: Data) => {
onRemove={(index) => act('remove', { id: index })}
/>
) : null}
- {currentTab === Tab.Logs && (
- <>
-
-
- >
- )}
+ {currentTab === Tab.Logs && }
@@ -175,9 +180,9 @@ const MachineDisplay = (props: MachineProps) => {
className={
machine.on_hold
? classes([
- 'FabricatorRecipe__Title',
- 'FabricatorRecipe__Title--disabled',
- ])
+ 'FabricatorRecipe__Title',
+ 'FabricatorRecipe__Title--disabled',
+ ])
: 'FabricatorRecipe__Title'
}
>
@@ -235,34 +240,94 @@ const RestrictButton = () => {
const { act, data } = useBackend();
const { id_required } = data;
return (
-
-
-
+
);
};
const LogsList = (props: LogsListProps) => {
const { logs } = props;
- return logs.length > 0 ? (
-
-
-
- {logs.map((log, index) => (
-
- ))}
-
-
- ) : (
- No log entries currently present!
- );
+ const searchableLogs = logs.map((log, index) => ({
+ id: index,
+ log,
+ searchString: [
+ log.action.toLowerCase(),
+ log.user_data.name.toLowerCase(),
+ log.user_data.assignment.toLowerCase(),
+ log.raw_materials.toLowerCase(),
+ log.machine_name.toLowerCase(),
+ log.area_name.toLowerCase(),
+ log.noun.toLowerCase(),
+ ].join(' '),
+ }));
+
+ const { query, setQuery, results } = useFuzzySearch({
+ searchArray: searchableLogs,
+ matchStrategy: 'smart',
+ getSearchString: (item) => item.searchString,
+ });
+
+ const filteredLogs = query ? results.map(result => result.log) : logs;
+
+ return (
+
+
+ }
+ >
+
+
+ setQuery(value)}
+ />
+
+
+
+
+
+
+
+ 0}
+ pr={1}>
+ {filteredLogs.length > 0 ? (
+
+ {filteredLogs.map((log, index) => (
+
+ ))}
+
+ ) : (
+
+ {query ? 'No logs seem to match your request.' : 'Nothing here...'}
+
+ )}
+
+
+
+ );
};
const UserItem = (props: UserData) => {
@@ -281,17 +346,18 @@ const UserItem = (props: UserData) => {
const { act, data } = useBackend();
const { banned_users } = data;
return (
-
- {name}
- {assignment}
+
+ {name},
+ {assignment}
{!id_read_failure && !silicon_override && (
)}
@@ -300,7 +366,7 @@ const UserItem = (props: UserData) => {
};
const formatAmount = (action: string, amount: number) => {
- const isSheetAction = action === 'EJECT' || action === 'DEPOSIT';
+ const isSheetAction = action === 'WITHDRAWN' || action === 'DEPOSITED';
const rawAmount = Math.abs(amount);
if (!isSheetAction) {
return rawAmount;
@@ -320,28 +386,73 @@ const LogEntry = (props: Log) => {
noun,
user_data,
} = props;
- return (
-
-
-
- {time}
-
- {capitalize(machine_name)}
-
- {area_name}
- 0 ? 'good' : 'bad'}
- >
- {raw_materials}
-
-
-
-
-
-
-
+ const [expanded, setExpanded] = useState(false);
+
+ return (
+
+ setExpanded(!expanded)}
+ >
+
+
+
+
+
+
+
+
+
+
+
+ {` ${formatAmount(action, amount)} ${noun}`}
+
+
+
+
+
+
+
+ {expanded && (
+
+
+
+ Time
+ {time}
+
+
+ Machine
+ {capitalize(machine_name)}
+
+
+ Location
+ {area_name}
+
+
+ Materials
+ 0 ? 'good' : 'bad'}>
+ {raw_materials}
+
+
+
+ User
+
+
+
+
+
+
+ )}
+
);
};
diff --git a/tgui/packages/tgui/styles/interfaces/OreSilo.scss b/tgui/packages/tgui/styles/interfaces/OreSilo.scss
deleted file mode 100644
index 024e95af316..00000000000
--- a/tgui/packages/tgui/styles/interfaces/OreSilo.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-.OreSilo {
- .__LogEntry {
- font-size: 1rem;
- outline-style: ridge;
- outline-width: 1px;
- background-blend-mode: screen;
- .__UserItem {
- font-family: 'Helvetica';
- font-kerning: auto;
- text-rendering: optimizeLegibility;
- .__Name {
- outline: ridge black;
- outline-offset: 1.5px;
- margin-right: 1.5px;
- }
- .__Assignment {
- outline: ridge black;
- outline-offset: 1.5px;
- letter-spacing: 1.1px;
- }
- }
- }
-}
diff --git a/tgui/packages/tgui/styles/main.scss b/tgui/packages/tgui/styles/main.scss
index e810f5b5d78..ad5d9498735 100644
--- a/tgui/packages/tgui/styles/main.scss
+++ b/tgui/packages/tgui/styles/main.scss
@@ -34,7 +34,6 @@
@include meta.load-css('./interfaces/NtosNotepad.scss');
@include meta.load-css('./interfaces/NuclearBomb.scss');
@include meta.load-css('./interfaces/Orbit.scss');
-@include meta.load-css('./interfaces/OreSilo.scss');
@include meta.load-css('./interfaces/Paper.scss');
@include meta.load-css('./interfaces/PreferencesMenu.scss');
@include meta.load-css('./interfaces/RequestManager.scss');