From 3df98437c6b9546c074db758e0531761b7934284 Mon Sep 17 00:00:00 2001
From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Date: Thu, 7 Oct 2021 13:20:44 +0100
Subject: [PATCH 1/5] Moves CUI entries to CDL
---
code/controllers/subsystem/ticker.dm | 54 +++++++++-
code/datums/custom_user_item.dm | 66 ++++++++++++
code/modules/client/client_defines.dm | 6 ++
.../client/login_processing/45-cuis.dm | 20 ++++
code/modules/customitems/item_spawning.dm | 101 ------------------
code/modules/mob/new_player/new_player.dm | 2 +-
paradise.dme | 3 +-
7 files changed, 148 insertions(+), 104 deletions(-)
create mode 100644 code/datums/custom_user_item.dm
create mode 100644 code/modules/client/login_processing/45-cuis.dm
delete mode 100644 code/modules/customitems/item_spawning.dm
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 28f69ba1795..7e61d0d71fa 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -408,12 +408,64 @@ SUBSYSTEM_DEF(ticker)
if(player.mind.assigned_role != player.mind.special_role)
SSjobs.AssignRank(player, player.mind.assigned_role, FALSE)
SSjobs.EquipRank(player, player.mind.assigned_role, FALSE)
- EquipCustomItems(player)
+ equip_cuis(player)
+
if(captainless)
for(var/mob/M in GLOB.player_list)
if(!isnewplayer(M))
to_chat(M, "Captainship not forced on anyone.")
+/datum/controller/subsystem/ticker/proc/equip_cuis(var/mob/living/carbon/human/H)
+ for(var/datum/custom_user_item/cui in H.client.cui_entries)
+ // Skip items with invalid character names
+ if(cui.characer_name != H.real_name)
+ continue
+
+ var/ok = FALSE
+
+ if(!cui.all_jobs_allowed)
+ var/alt_blocked = FALSE
+ if(H.mind.role_alt_title)
+ if(!(H.mind.role_alt_title in cui.allowed_jobs))
+ alt_blocked = TRUE
+ if(!(H.mind.assigned_role in cui.allowed_jobs) || alt_blocked)
+ continue
+
+ var/obj/item/I = new cui.object_typepath()
+ var/name_override = cui.item_name_override
+ var/desc_override = cui.item_desc_override
+
+ if(istype(H.back, /obj/item/storage)) // Try to place it in something on the mob's back
+ var/obj/item/storage/S = H.back
+ if(S.contents.len < S.storage_slots)
+ I.forceMove(H.back)
+ ok = TRUE
+ to_chat(H, "Your [I.name] has been added to your [H.back.name].")
+
+ if(!ok)
+ for(var/obj/item/storage/S in H.contents) // Try to place it in any item that can store stuff, on the mob.
+ if(S.contents.len < S.storage_slots)
+ I.forceMove(S)
+ ok = TRUE
+ to_chat(H, "Your [I.name] has been added to your [S.name].")
+ break
+
+ if(name_override)
+ I.name = name_override
+ if(desc_override)
+ I.desc = desc_override
+
+ if(!ok) // Finally, since everything else failed, place it on the ground
+ var/turf/T = get_turf(H)
+ if(T)
+ I.forceMove(T)
+ to_chat(H, "Your [I.name] is on the [T.name] below you.")
+ else
+ to_chat(H, "Your [I.name] couldnt spawn anywhere on you or even on the floor below you. Please file a bug report.")
+
+ H.regenerate_icons()
+
+
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
var/m
if(selected_tip)
diff --git a/code/datums/custom_user_item.dm b/code/datums/custom_user_item.dm
new file mode 100644
index 00000000000..4b666c39e9d
--- /dev/null
+++ b/code/datums/custom_user_item.dm
@@ -0,0 +1,66 @@
+/**
+ * # Custom User Item
+ *
+ * Holder for CUIs
+ *
+ * This datum is a older that is essentially a "model" of the `customuseritems`
+ * database table, and is used for giving people their CUIs on spawn.
+ * It is instanced as part of the client data loading framework on the client.
+ *
+ */
+/datum/custom_user_item
+ /// Can this be used on all characters?
+ var/all_characters_allowed = FALSE
+ /// Name of the character that can have this item.
+ var/characer_name
+ /// Are all jobs allowed?
+ var/all_jobs_allowed = FALSE
+ /// List of allowed jobs
+ var/allowed_jobs = list()
+ /// Custom item typepath
+ var/object_typepath
+ /// Custom item name override
+ var/item_name_override
+ /// Custom item description override
+ var/item_desc_override
+ /// Raw job mask
+ var/raw_job_mask
+
+
+/**
+ * CUI Info Parser
+ *
+ * Parses all the raw info into usable stuff, and also does validity checks
+ * Returns TRUE if its a valid item, and FALSE if not
+ *
+ * Arguments:
+ * * owning_ckey - Player who owns this item. Used for logging purposes.
+ */
+/datum/custom_user_item/proc/parse_info(owning_ckey)
+ . = FALSE // Setting this here means it will return false even if it runtimes
+
+ // Sort path
+ if(!object_typepath || !ispath(object_typepath))
+ stack_trace("Incorrect database entry found in table 'customuseritems' path value is [object_typepath ? object_typepath : "(NULL)"], which doesnt exist. Ask the host to look at CUI entries for [owning_ckey]")
+ return
+
+ // Sort job mask
+ if(raw_job_mask == "*")
+ all_jobs_allowed = TRUE
+ else
+ var/list/local_allowed_jobs = splittext(raw_job_mask, ",")
+ for(var/i in 1 to length(local_allowed_jobs))
+ if(istext(local_allowed_jobs[i]))
+ local_allowed_jobs[i] = trim(local_allowed_jobs[i])
+
+ allowed_jobs = local_allowed_jobs
+
+ // Sort character name
+ if(characer_name == "*")
+ all_characters_allowed = TRUE
+
+ return TRUE
+
+
+/datum/custom_user_item/vv_edit_var(var_name, var_value)
+ return FALSE // fuck off
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index f68e20b1903..7c011962c08 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -117,10 +117,16 @@
/// Client's pAI save
var/datum/pai_save/pai_save
+ /// List of the clients CUIs
+ var/list/datum/custom_user_item/cui_entries = list()
+
/client/vv_edit_var(var_name, var_value)
switch(var_name)
// I know we will never be in a world where admins are editing client vars to let people bypass TOS
// But guess what, if I have the ability to overengineer something, I am going to do it
if("tos_consent")
return FALSE
+ // Dont fuck with this
+ if("cui_entries")
+ return FALSE
return ..()
diff --git a/code/modules/client/login_processing/45-cuis.dm b/code/modules/client/login_processing/45-cuis.dm
new file mode 100644
index 00000000000..88bfca44638
--- /dev/null
+++ b/code/modules/client/login_processing/45-cuis.dm
@@ -0,0 +1,20 @@
+/datum/client_login_processor/cuis
+ priority = 45
+
+/datum/client_login_processor/cuis/get_query(client/C)
+ var/datum/db_query/query = SSdbcore.NewQuery("SELECT cuiRealName, cuiPath, cuiItemName, cuiDescription, cuiJobMask FROM customuseritems WHERE cuiCKey=:ckey", list(
+ "ckey" = C.ckey
+ ))
+ return query
+
+/datum/client_login_processor/cuis/process_result(datum/db_query/Q, client/C)
+ while(Q.NextRow())
+ var/datum/custom_user_item/cui = new()
+ cui.characer_name = Q.item[1]
+ cui.object_typepath = text2path(Q.item[2])
+ cui.item_name_override = Q.item[3]
+ cui.item_desc_override = Q.item[4]
+ cui.raw_job_mask = Q.item[5]
+
+ if(cui.parse_info(C.ckey))
+ C.cui_entries += cui
diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm
deleted file mode 100644
index 5f998861cf6..00000000000
--- a/code/modules/customitems/item_spawning.dm
+++ /dev/null
@@ -1,101 +0,0 @@
-/proc/EquipCustomItems(mob/living/carbon/human/M)
- if(!SSdbcore.IsConnected())
- return
-
- // Grab the info we want.
- var/datum/db_query/query = SSdbcore.NewQuery({"
- SELECT cuiPath, cuiPropAdjust, cuiJobMask, cuiDescription, cuiItemName FROM customuseritems
- WHERE cuiCKey=:ckey AND (cuiRealName=:realname OR cuiRealName='*')"}, list(
- "ckey" = M.ckey,
- "realname" = M.real_name
- ))
- if(!query.warn_execute(async = FALSE)) // Dont make this async. Youll make roundstart slow. Trust me.
- qdel(query)
- return
-
- while(query.NextRow())
- var/path = text2path(query.item[1])
- var/propadjust = query.item[2]
- var/jobmask = query.item[3]
- var/ok = 0
- if(!path || !ispath(path))
- log_debug("Incorrect database entry found in table 'customuseritems' path value = [path], cuiPath is null. cuiCKey='[M.ckey]' AND (cuiRealName='[M.real_name]' OR cuiRealName='*'")
- continue
- if(jobmask != "*")
- var/list/allowed_jobs = splittext(jobmask,",")
- for(var/i = 1, i <= allowed_jobs.len, i++)
- if(istext(allowed_jobs[i]))
- allowed_jobs[i] = trim(allowed_jobs[i])
- var/alt_blocked = 0
- if(M.mind.role_alt_title)
- if(!(M.mind.role_alt_title in allowed_jobs))
- alt_blocked = 1
- if(!(M.mind.assigned_role in allowed_jobs) || alt_blocked)
- continue
-
- var/obj/item/Item = new path()
- var/description = query.item[4]
- var/newname = query.item[5]
- if(istype(Item,/obj/item/card/id))
- var/obj/item/card/id/I = Item
- for(var/obj/item/card/id/C in M)
- //default settings
- I.name = "[M.real_name]'s ID Card ([M.mind.role_alt_title ? M.mind.role_alt_title : M.mind.assigned_role])"
- I.registered_name = M.real_name
- I.access = C.access
- I.assignment = C.assignment
- I.blood_type = C.blood_type
- I.dna_hash = C.dna_hash
- I.fingerprint_hash = C.fingerprint_hash
- qdel(C)
- ok = M.equip_or_collect(I, slot_wear_id, 0) //if 1, last argument deletes on fail
- break
- else if(istype(M.back, /obj/item/storage)) // Try to place it in something on the mob's back
- var/obj/item/storage/S = M.back
- if(S.contents.len < S.storage_slots)
- Item.loc = M.back
- ok = 1
- to_chat(M, "Your [Item.name] has been added to your [M.back.name].")
- if(ok == 0)
- for(var/obj/item/storage/S in M.contents) // Try to place it in any item that can store stuff, on the mob.
- if(S.contents.len < S.storage_slots)
- Item.loc = S
- ok = 1
- to_chat(M, "Your [Item.name] has been added to your [S.name].")
- break
- if(description)
- Item.desc = description
- if(newname)
- Item.name = newname
-
- if(ok == 0) // Finally, since everything else failed, place it on the ground
- Item.loc = get_turf(M.loc)
-
- HackProperties(Item,propadjust)
- M.regenerate_icons()
- qdel(query)
-
-// This is hacky, but since it's difficult as fuck to make a proper parser in BYOND without killing the server, here it is. - N3X
-/proc/HackProperties(mob/living/carbon/human/M, obj/item/I, script)
- var/list/statements = splittext(script,";")
- if(statements.len == 0)
- return
- for(var/statement in statements)
- var/list/assignmentChunks = splittext(statement,"=")
- var/varname = assignmentChunks[1]
- var/list/typeChunks=splittext(script,":")
- var/desiredType=typeChunks[1]
- switch(desiredType)
- if("string")
- var/output = typeChunks[2]
- output = replacetext(output,"{REALNAME}", M.real_name)
- output = replacetext(output,"{ROLE}", M.mind.assigned_role)
- output = replacetext(output,"{ROLE_ALT}", "[M.mind.role_alt_title ? M.mind.role_alt_title : M.mind.assigned_role]")
- I.vars[varname]=output
- if("number")
- I.vars[varname]=text2num(typeChunks[2])
- if("icon")
- if(typeChunks.len==2)
- I.vars[varname]=new /icon(typeChunks[2])
- if(typeChunks.len==3)
- I.vars[varname]=new /icon(typeChunks[2],typeChunks[3])
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 04aca83e512..9370829c746 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -359,7 +359,7 @@
character.buckled.dir = character.dir
character = SSjobs.EquipRank(character, rank, 1) //equips the human
- EquipCustomItems(character)
+ SSticker.equip_cuis(character) // Gives them their CUIs
SSticker.mode.latespawn(character)
diff --git a/paradise.dme b/paradise.dme
index dfcad75c3b4..4be89df7af8 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -277,6 +277,7 @@
#include "code\datums\callback.dm"
#include "code\datums\chatmessage.dm"
#include "code\datums\click_intercept.dm"
+#include "code\datums\custom_user_item.dm"
#include "code\datums\datacore.dm"
#include "code\datums\datum.dm"
#include "code\datums\datumvars.dm"
@@ -1385,6 +1386,7 @@
#include "code\modules\client\login_processing\38-alts_cid.dm"
#include "code\modules\client\login_processing\39-cid_count.dm"
#include "code\modules\client\login_processing\40-pai_save.dm"
+#include "code\modules\client\login_processing\45-cuis.dm"
#include "code\modules\client\login_processing\__client_login_processor.dm"
#include "code\modules\client\preference\character.dm"
#include "code\modules\client\preference\link_processing.dm"
@@ -1479,7 +1481,6 @@
#include "code\modules\crafting\recipes.dm"
#include "code\modules\crafting\tailoring.dm"
#include "code\modules\customitems\item_defines.dm"
-#include "code\modules\customitems\item_spawning.dm"
#include "code\modules\detective_work\detective_work.dm"
#include "code\modules\detective_work\evidence.dm"
#include "code\modules\detective_work\footprints_and_rag.dm"
From 74b3d1e685d3e0a65fd7e8cafa8732eba36f6537 Mon Sep 17 00:00:00 2001
From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Date: Thu, 7 Oct 2021 13:29:15 +0100
Subject: [PATCH 2/5] Its been a whileok
---
code/controllers/subsystem/ticker.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 7e61d0d71fa..e157c7c518e 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -415,7 +415,7 @@ SUBSYSTEM_DEF(ticker)
if(!isnewplayer(M))
to_chat(M, "Captainship not forced on anyone.")
-/datum/controller/subsystem/ticker/proc/equip_cuis(var/mob/living/carbon/human/H)
+/datum/controller/subsystem/ticker/proc/equip_cuis(mob/living/carbon/human/H)
for(var/datum/custom_user_item/cui in H.client.cui_entries)
// Skip items with invalid character names
if(cui.characer_name != H.real_name)
From c1e6ea494d3581ff8df625c2527573b1d316e333 Mon Sep 17 00:00:00 2001
From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Date: Thu, 7 Oct 2021 15:55:34 +0100
Subject: [PATCH 3/5] Fixes named stuff
---
code/controllers/subsystem/ticker.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index e157c7c518e..768b5538e75 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -418,7 +418,7 @@ SUBSYSTEM_DEF(ticker)
/datum/controller/subsystem/ticker/proc/equip_cuis(mob/living/carbon/human/H)
for(var/datum/custom_user_item/cui in H.client.cui_entries)
// Skip items with invalid character names
- if(cui.characer_name != H.real_name)
+ if((cui.characer_name != H.real_name) && !cui.all_characters_allowed)
continue
var/ok = FALSE
From 3ff24ea7e13709e293d7cfc308a34535db554de4 Mon Sep 17 00:00:00 2001
From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Date: Sat, 9 Oct 2021 21:23:40 +0100
Subject: [PATCH 4/5] Client check
---
code/controllers/subsystem/ticker.dm | 2 ++
1 file changed, 2 insertions(+)
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 768b5538e75..db45cfec926 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -416,6 +416,8 @@ SUBSYSTEM_DEF(ticker)
to_chat(M, "Captainship not forced on anyone.")
/datum/controller/subsystem/ticker/proc/equip_cuis(mob/living/carbon/human/H)
+ if(!H.client)
+ return // If they are spawning without a client (somehow), they *cant* have a CUI list
for(var/datum/custom_user_item/cui in H.client.cui_entries)
// Skip items with invalid character names
if((cui.characer_name != H.real_name) && !cui.all_characters_allowed)
From 26a3dcd48b5b16cffa84eebb0a6125017805ec63 Mon Sep 17 00:00:00 2001
From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com>
Date: Sun, 17 Oct 2021 19:36:40 +0100
Subject: [PATCH 5/5] Tweaks
---
code/controllers/subsystem/ticker.dm | 17 ++++++++---------
code/datums/custom_user_item.dm | 4 ++--
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index db45cfec926..5bb1d0eb69f 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -437,26 +437,26 @@ SUBSYSTEM_DEF(ticker)
var/name_override = cui.item_name_override
var/desc_override = cui.item_desc_override
+ if(name_override)
+ I.name = name_override
+ if(desc_override)
+ I.desc = desc_override
+
if(istype(H.back, /obj/item/storage)) // Try to place it in something on the mob's back
var/obj/item/storage/S = H.back
- if(S.contents.len < S.storage_slots)
+ if(length(S.contents) < S.storage_slots)
I.forceMove(H.back)
ok = TRUE
to_chat(H, "Your [I.name] has been added to your [H.back.name].")
if(!ok)
for(var/obj/item/storage/S in H.contents) // Try to place it in any item that can store stuff, on the mob.
- if(S.contents.len < S.storage_slots)
+ if(length(S.contents) < S.storage_slots)
I.forceMove(S)
ok = TRUE
to_chat(H, "Your [I.name] has been added to your [S.name].")
break
- if(name_override)
- I.name = name_override
- if(desc_override)
- I.desc = desc_override
-
if(!ok) // Finally, since everything else failed, place it on the ground
var/turf/T = get_turf(H)
if(T)
@@ -464,8 +464,7 @@ SUBSYSTEM_DEF(ticker)
to_chat(H, "Your [I.name] is on the [T.name] below you.")
else
to_chat(H, "Your [I.name] couldnt spawn anywhere on you or even on the floor below you. Please file a bug report.")
-
- H.regenerate_icons()
+ qdel(I)
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
diff --git a/code/datums/custom_user_item.dm b/code/datums/custom_user_item.dm
index 4b666c39e9d..9680a990488 100644
--- a/code/datums/custom_user_item.dm
+++ b/code/datums/custom_user_item.dm
@@ -3,7 +3,7 @@
*
* Holder for CUIs
*
- * This datum is a older that is essentially a "model" of the `customuseritems`
+ * This datum is a holder that is essentially a "model" of the `customuseritems`
* database table, and is used for giving people their CUIs on spawn.
* It is instanced as part of the client data loading framework on the client.
*
@@ -16,7 +16,7 @@
/// Are all jobs allowed?
var/all_jobs_allowed = FALSE
/// List of allowed jobs
- var/allowed_jobs = list()
+ var/list/allowed_jobs = list()
/// Custom item typepath
var/object_typepath
/// Custom item name override