From e3b5cc0b7beedb8881c8eb2255ccc19a9c095899 Mon Sep 17 00:00:00 2001
From: CHOMPStation2StaffMirrorBot
<94713762+CHOMPStation2StaffMirrorBot@users.noreply.github.com>
Date: Sat, 30 Nov 2024 09:07:20 -0700
Subject: [PATCH] [MIRROR] Ports in-round record updating (#9570)
Co-authored-by: Heroman3003 <31296024+Heroman3003@users.noreply.github.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
---
code/game/machinery/computer/medical.dm | 10 ++
code/game/machinery/computer/security.dm | 10 ++
code/game/machinery/computer/skills.dm | 10 ++
code/modules/client/record_updater.dm | 129 ++++++++++++++++++
.../GeneralRecords/GeneralRecordsOptions.tsx | 8 ++
.../GeneralRecordsViewGeneral.tsx | 1 +
.../MedicalRecords/MedicalRecordsOptions.tsx | 8 ++
.../MedicalRecordsViewMedical.tsx | 15 +-
.../SecurityRecordsOptions.tsx | 8 ++
.../SecurityRecordsViewSecurity.tsx | 21 ++-
vorestation.dme | 1 +
11 files changed, 214 insertions(+), 7 deletions(-)
create mode 100644 code/modules/client/record_updater.dm
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 00339ac273..d36a4d7984 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -298,6 +298,16 @@
active1 = general_record
active2 = medical_record
screen = MED_DATA_RECORD
+ if("sync_r")
+ if(active2)
+ set_temp(client_update_record(src,usr))
+ if("edit_notes")
+ // The modal input in tgui is busted for this sadly...
+ var/new_notes = strip_html_simple(tgui_input_text(usr,"Enter new information here.","Character Preference", html_decode(active2.fields["notes"]), MAX_RECORD_LENGTH, TRUE, prevent_enter = TRUE), MAX_RECORD_LENGTH)
+ if(usr.Adjacent(src))
+ if(new_notes != "" || tgui_alert(usr, "Are you sure you want to delete the current record's notes?", "Confirm Delete", list("Delete", "No")) == "Delete")
+ if(usr.Adjacent(src))
+ active2.fields["notes"] = new_notes
if("new")
if(istype(active1, /datum/data/record) && !istype(active2, /datum/data/record))
var/datum/data/record/R = new /datum/data/record()
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 1be57d146e..9ed9242767 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -270,6 +270,16 @@
qdel(active1)
if(active2)
qdel(active2)
+ if("sync_r")
+ if(active2)
+ set_temp(client_update_record(src,usr))
+ if("edit_notes")
+ // The modal input in tgui is busted for this sadly...
+ var/new_notes = strip_html_simple(tgui_input_text(usr,"Enter new information here.","Character Preference", html_decode(active2.fields["notes"]), MAX_RECORD_LENGTH, TRUE, prevent_enter = TRUE), MAX_RECORD_LENGTH)
+ if(usr.Adjacent(src))
+ if(new_notes != "" || tgui_alert(usr, "Are you sure you want to delete the current record's notes?", "Confirm Delete", list("Delete", "No")) == "Delete")
+ if(usr.Adjacent(src))
+ active2.fields["notes"] = new_notes
if("d_rec")
var/datum/data/record/general_record = locate(params["d_rec"] || "")
if(!data_core.general.Find(general_record))
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index 57524d95fd..9be405d36d 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -214,6 +214,16 @@
for(var/datum/data/record/R in data_core.general)
qdel(R)
set_temp("All employment records deleted.")
+ if("sync_r")
+ if(active1)
+ set_temp(client_update_record(src,active1,usr))
+ if("edit_notes")
+ // The modal input in tgui is busted for this sadly...
+ var/new_notes = strip_html_simple(tgui_input_text(usr,"Enter new information here.","Character Preference", html_decode(active1.fields["notes"]), MAX_RECORD_LENGTH, TRUE, prevent_enter = TRUE), MAX_RECORD_LENGTH)
+ if(usr.Adjacent(src))
+ if(new_notes != "" || tgui_alert(usr, "Are you sure you want to delete the current record's notes?", "Confirm Delete", list("Delete", "No")) == "Delete")
+ if(usr.Adjacent(src))
+ active1.fields["notes"] = new_notes
if("del_r")
if(PDA_Manifest)
PDA_Manifest.Cut()
diff --git a/code/modules/client/record_updater.dm b/code/modules/client/record_updater.dm
new file mode 100644
index 0000000000..de802eedcf
--- /dev/null
+++ b/code/modules/client/record_updater.dm
@@ -0,0 +1,129 @@
+var/global/client_record_update_lock = FALSE
+
+// Manually updating records from medical console to a player's save.
+/proc/get_current_mob_from_record(var/datum/data/record/active)
+ var/datum/transcore_db/db = SStranscore.db_by_mind_name(active.fields["name"])
+ if(db)
+ var/datum/transhuman/mind_record/record = db.backed_up[active.fields["name"]]
+ if(record.mind_ref)
+ var/datum/mind/D = record.mind_ref
+ if(D.current)
+ var/client/C = D.current.client
+ if(C && C.ckey != record.ckey)
+ return null
+ return D.current
+ return null
+
+
+/proc/client_update_record(var/obj/machinery/computer/COM, var/user)
+ if(!COM || QDELETED(COM))
+ return "Invalid console"
+
+ if(jobban_isbanned(user, "Records") )
+ COM.visible_message(span_notice("\The [COM] buzzes!"))
+ playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0)
+ return "Update syncronization denied (OOC: You are banned from editing records)"
+
+ var/record_string = ""
+ var/datum/data/record/active
+ var/console_path = null
+ if(istype(COM,/obj/machinery/computer/med_data))
+ var/obj/machinery/computer/med_data/MCOM = COM
+ active = MCOM.active2
+ record_string = "medical"
+ console_path = /obj/machinery/computer/med_data
+ if(istype(COM,/obj/machinery/computer/skills))
+ var/obj/machinery/computer/skills/ECOM = COM
+ active = ECOM.active1
+ record_string = "employment"
+ console_path = /obj/machinery/computer/skills
+ if(istype(COM,/obj/machinery/computer/secure_data))
+ var/obj/machinery/computer/secure_data/SCOM = COM
+ active = SCOM.active2
+ record_string = "security"
+ console_path = /obj/machinery/computer/secure_data
+
+ if(client_record_update_lock)
+ to_chat(user,"Update already in progress! Please wait a moment...")
+ if(COM && !QDELETED(COM))
+ COM.visible_message(span_notice("\The [COM] buzzes!"))
+ playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0)
+ return "Update already in progress! Please wait a moment..."
+ client_record_update_lock = TRUE
+ spawn(60 SECONDS)
+ client_record_update_lock = FALSE
+
+ if(!active || !console_path)
+ if(COM && !QDELETED(COM))
+ COM.visible_message(span_notice("\The [COM] buzzes!"))
+ playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0)
+ return "Update syncronization failed (OOC: Record or console destroyed)"
+
+ to_chat(user,"Update sent! Please wait for a response...")
+ message_admins("[user] pushed [record_string] record update to [active.fields["name"]].")
+
+ var/mob/M = get_current_mob_from_record(active)
+ if(!M)
+ if(COM && !QDELETED(COM))
+ COM.visible_message(span_notice("\The [COM] buzzes!"))
+ playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0)
+ return "Update syncronization failed (OOC: Client mob does not exist, has no mind record, or is possesssed)"
+
+ var/client/C = M.client
+ if(!C)
+ if(COM && !QDELETED(COM))
+ COM.visible_message(span_notice("\The [COM] buzzes!"))
+ playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0)
+ return "Update syncronization failed (OOC: Record's owner is offline)"
+
+ var/choice = tgui_alert(M, "Your [record_string] record has been updated from the a records console by [user]. Please review the changes made to your [record_string] record. Accepting these changes will SAVE your CURRENT character slot! If your new [record_string] record has errors, it is recomended to have it corrected IC instead of editing it yourself.", "Record Updated", list("Review Changes","Refuse Update"))
+ if(choice == "Refuse Update")
+ message_admins("[active.fields["name"]] refused [record_string] record update from [user] without review.")
+ if(COM && !QDELETED(COM))
+ COM.visible_message(span_notice("\The [COM] buzzes!"))
+ playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0)
+ return "Update syncronization failed (OOC: Client refused without review)"
+
+ var/datum/preferences/P = C.prefs
+ var/new_data = strip_html_simple(tgui_input_text(M,"Please review [user]'s changes to your [record_string] record before confirming. Confirming will SAVE your CURRENT character slot! If your new [record_string] record major errors, it is recomended to have it corrected IC instead of editing it yourself.","Character Preference", html_decode(active.fields["notes"]), MAX_RECORD_LENGTH, TRUE, prevent_enter = TRUE), MAX_RECORD_LENGTH)
+ if(!new_data)
+ message_admins("[active.fields["name"]] refused [record_string] record update from [user] with review.")
+ if(COM && !QDELETED(COM))
+ COM.visible_message(span_notice("\The [COM] buzzes!"))
+ playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0)
+ return "Update syncronization failed (OOC: Client refused with review)"
+ if(!M || !M.client || !P)
+ message_admins("[active.fields["name"]]'s [record_string] record could not be updated, client disconnected.")
+ if(COM && !QDELETED(COM))
+ COM.visible_message(span_notice("\The [COM] buzzes!"))
+ playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0)
+ return "Update syncronization failed (OOC: Client does not exist)"
+
+ // Update records in the consoles, remember this can happen a while after a record is closed on the console... Use cached data.
+ switch(console_path)
+ if(/obj/machinery/computer/med_data)
+ P.med_record = new_data
+ if(active)
+ active.fields["notes"] = new_data
+ if(/obj/machinery/computer/skills)
+ P.gen_record = new_data
+ if(active)
+ active.fields["notes"] = new_data
+ if(/obj/machinery/computer/secure_data)
+ P.sec_record = new_data
+ if(active)
+ active.fields["notes"] = new_data
+
+ // Update player record
+ P.save_preferences()
+ P.save_character()
+ if(M)
+ to_chat(M,span_notice("Your [record_string] record for [active.fields["name"]] has been updated."))
+ message_admins("[active.fields["name"]] accepted the [record_string] record update from [user].")
+
+ // ding!
+ if(COM && !QDELETED(COM))
+ COM.visible_message(span_notice("\The [COM] dings!"))
+ playsound(COM, 'sound/machines/ding.ogg', 50, 1)
+
+ return "Record syncronized."
diff --git a/tgui/packages/tgui/interfaces/GeneralRecords/GeneralRecordsOptions.tsx b/tgui/packages/tgui/interfaces/GeneralRecords/GeneralRecordsOptions.tsx
index 5db9a5c321..457294e6a0 100644
--- a/tgui/packages/tgui/interfaces/GeneralRecords/GeneralRecordsOptions.tsx
+++ b/tgui/packages/tgui/interfaces/GeneralRecords/GeneralRecordsOptions.tsx
@@ -21,6 +21,14 @@ export const GeneralRecordsView = (props) => {
+
{
{general.skills || 'No data found.'}
+ {
{general.comments && general.comments.length === 0 ? (
diff --git a/tgui/packages/tgui/interfaces/MedicalRecords/MedicalRecordsOptions.tsx b/tgui/packages/tgui/interfaces/MedicalRecords/MedicalRecordsOptions.tsx
index 757e79b7cd..a711cdf931 100644
--- a/tgui/packages/tgui/interfaces/MedicalRecords/MedicalRecordsOptions.tsx
+++ b/tgui/packages/tgui/interfaces/MedicalRecords/MedicalRecordsOptions.tsx
@@ -36,6 +36,14 @@ export const MedicalRecordsView = (props) => {
+
{
{field.value}
-
))}
diff --git a/tgui/packages/tgui/interfaces/SecurityRecords/SecurityRecordsOptions.tsx b/tgui/packages/tgui/interfaces/SecurityRecords/SecurityRecordsOptions.tsx
index 276ad42d1a..03e2530eb2 100644
--- a/tgui/packages/tgui/interfaces/SecurityRecords/SecurityRecordsOptions.tsx
+++ b/tgui/packages/tgui/interfaces/SecurityRecords/SecurityRecordsOptions.tsx
@@ -35,6 +35,14 @@ export const SecurityRecordsView = (props) => {
+ act('sync_r')}
+ >
+ Sync Security Record
+
{
{field.value}
- doEdit(field)}
- />
+ {!!field.edit &&
+ (field.edit === 'notes' ? (
+ act('edit_notes')}
+ />
+ ) : (
+ doEdit(field)}
+ />
+ ))}
))}
diff --git a/vorestation.dme b/vorestation.dme
index 9c5f85dbc7..9b0089ad24 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -2169,6 +2169,7 @@
#include "code\modules\client\preferences_toggle_procs.dm"
#include "code\modules\client\preferences_vr.dm"
#include "code\modules\client\preferences_yw.dm"
+#include "code\modules\client\record_updater.dm"
#include "code\modules\client\spam_prevention.dm"
#include "code\modules\client\stored_item.dm"
#include "code\modules\client\ui_style.dm"