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