diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 444549bfb6f..d50738621b3 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -463,7 +463,7 @@ All procs that are registered to listen for signals using `RegisterSignal()` mus ``` This is to ensure that it is clear the proc handles signals and turns on a lint to ensure it does not sleep. -There exists `SIGNAL_HANDLER_DOES_SLEEP`, but this is only for legacy signal handlers that still sleep, new/changed code should not use this. +Any sleeping behaviour that you need to perform inside a `SIGNAL_HANDLER` proc must be called asynchronously (e.g. with `INVOKE_ASYNC()`) or be redone to work asynchronously. ### Enforcing parent calling When adding new signals to root level procs, eg; diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm index a0080d7266e..2f6b7590f63 100644 --- a/code/__DEFINES/dcs/helpers.dm +++ b/code/__DEFINES/dcs/helpers.dm @@ -10,10 +10,6 @@ /// Every proc you pass to RegisterSignal must have this. #define SIGNAL_HANDLER SHOULD_NOT_SLEEP(TRUE) -/// Signifies that this proc is used to handle signals, but also sleeps. -/// Do not use this for new work. -#define SIGNAL_HANDLER_DOES_SLEEP - /// A wrapper for _AddElement that allows us to pretend we're using normal named arguments #define AddElement(arguments...) _AddElement(list(##arguments)) /// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index c2e5a24fcab..d1be5592eaf 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -316,14 +316,14 @@ if(!(C.datum_flags & DF_SIGNAL_ENABLED)) return NONE var/proctype = C.signal_procs[src][sigtype] - return NONE | CallAsync(C, proctype, arguments) + return NONE | call(C, proctype)(arglist(arguments)) . = NONE for(var/I in target) var/datum/C = I if(!(C.datum_flags & DF_SIGNAL_ENABLED)) continue var/proctype = C.signal_procs[src][sigtype] - . |= CallAsync(C, proctype, arguments) + . |= call(C, proctype)(arglist(arguments)) // The type arg is casted so initial works, you shouldn't be passing a real instance into this /** diff --git a/code/datums/components/construction.dm b/code/datums/components/construction.dm index 362cf3c0328..34fa7a0cd7c 100644 --- a/code/datums/components/construction.dm +++ b/code/datums/components/construction.dm @@ -32,9 +32,9 @@ update_parent(index) /datum/component/construction/proc/action(datum/source, obj/item/I, mob/living/user) - SIGNAL_HANDLER_DOES_SLEEP + SIGNAL_HANDLER - return check_step(I, user) + return INVOKE_ASYNC(src, .proc/check_step, I, user) /datum/component/construction/proc/update_index(diff) index += diff diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm index 150a9f914fc..c798a10e763 100644 --- a/code/datums/components/embedded.dm +++ b/code/datums/components/embedded.dm @@ -185,12 +185,16 @@ /// Called when a carbon with an object embedded/stuck to them inspects themselves and clicks the appropriate link to begin ripping the item out. This handles the ripping attempt, descriptors, and dealing damage, then calls safe_remove() /datum/component/embedded/proc/ripOut(datum/source, obj/item/I, obj/item/bodypart/limb) - SIGNAL_HANDLER_DOES_SLEEP + SIGNAL_HANDLER if(I != weapon || src.limb != limb) return var/mob/living/carbon/victim = parent var/time_taken = rip_time * weapon.w_class + INVOKE_ASYNC(src, .proc/complete_rip_out, victim, I, limb, time_taken) + +/// everything async that ripOut used to do +/datum/component/embedded/proc/complete_rip_out(mob/living/carbon/victim, obj/item/I, obj/item/bodypart/limb, time_taken) victim.visible_message("[victim] attempts to remove [weapon] from [victim.p_their()] [limb.name].","You attempt to remove [weapon] from your [limb.name]... (It will take [DisplayTimeText(time_taken)].)") if(!do_after(victim, time_taken, target = victim)) return diff --git a/code/datums/components/gunpoint.dm b/code/datums/components/gunpoint.dm index 9e2ba76c874..184d2f66f9e 100644 --- a/code/datums/components/gunpoint.dm +++ b/code/datums/components/gunpoint.dm @@ -117,8 +117,10 @@ ///Bang bang, we're firing a charged shot off /datum/component/gunpoint/proc/trigger_reaction() - SIGNAL_HANDLER_DOES_SLEEP + SIGNAL_HANDLER + INVOKE_ASYNC(src, .proc/async_trigger_reaction) +/datum/component/gunpoint/proc/async_trigger_reaction() var/mob/living/shooter = parent shooter.remove_status_effect(STATUS_EFFECT_HOLDUP) // try doing these before the trigger gets pulled since the target (or shooter even) may not exist after pulling the trigger, dig? target.remove_status_effect(STATUS_EFFECT_HELDUP, shooter) diff --git a/code/datums/components/omen.dm b/code/datums/components/omen.dm index 9b50b5d62df..539b19c4caf 100644 --- a/code/datums/components/omen.dm +++ b/code/datums/components/omen.dm @@ -51,7 +51,7 @@ * We do the prob() at the beginning to A. add some tension for /when/ it will strike, and B. (more importantly) ameliorate the fact that we're checking up to 5 turfs's contents each time */ /datum/component/omen/proc/check_accident(atom/movable/our_guy) - SIGNAL_HANDLER_DOES_SLEEP + SIGNAL_HANDLER if(!isliving(our_guy)) return @@ -66,7 +66,7 @@ to_chat(living_guy, "A malevolent force launches your body to the floor...") var/obj/machinery/door/airlock/darth_airlock = turf_content living_guy.apply_status_effect(STATUS_EFFECT_PARALYZED, 10) - darth_airlock.close(force_crush = TRUE) + INVOKE_ASYNC(darth_airlock, /obj/machinery/door/airlock.proc/close, TRUE) if(!permanent) qdel(src) return @@ -84,7 +84,7 @@ for(var/obj/machinery/vending/darth_vendor in the_turf) if(darth_vendor.tiltable) to_chat(living_guy, "A malevolent force tugs at the [darth_vendor]...") - darth_vendor.tilt(living_guy) + INVOKE_ASYNC(darth_vendor, /obj/machinery/vending.proc/tilt, living_guy) if(!permanent) qdel(src) return diff --git a/code/datums/components/storage/concrete/wallet.dm b/code/datums/components/storage/concrete/wallet.dm index c019bb0a596..03a95b50ca1 100644 --- a/code/datums/components/storage/concrete/wallet.dm +++ b/code/datums/components/storage/concrete/wallet.dm @@ -8,11 +8,6 @@ var/obj/item/storage/wallet/A = parent if(istype(A) && A.front_id && !issilicon(user) && !(A.item_flags & IN_STORAGE)) //if it's a wallet in storage seeing the full inventory is more useful var/obj/item/I = A.front_id - A.add_fingerprint(user) - remove_from_storage(I, get_turf(user)) - if(!user.put_in_hands(I)) - to_chat(user, "You fumble for [I] and it falls on the floor.") - return - user.visible_message("[user] draws [I] from [parent]!", "You draw [I] from [parent].") + INVOKE_ASYNC(src, .proc/attempt_put_in_hands, I, user) return - ..() + return ..() diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index fac59475e69..bc7d999cdcb 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -194,7 +194,7 @@ INVOKE_ASYNC(src, .proc/quick_empty, M) /datum/component/storage/proc/preattack_intercept(datum/source, obj/O, mob/M, params) - SIGNAL_HANDLER_DOES_SLEEP + SIGNAL_HANDLER if(!isitem(O) || !click_gather || SEND_SIGNAL(O, COMSIG_CONTAINS_STORAGE)) return FALSE @@ -209,19 +209,23 @@ return if(!isturf(I.loc)) return - var/list/things = I.loc.contents.Copy() + INVOKE_ASYNC(src, .proc/async_preattack_intercept, I, M) + +///async functionality from preattack_intercept +/datum/component/storage/proc/async_preattack_intercept(obj/item/attack_item, mob/pre_attack_mob) + var/list/things = attack_item.loc.contents.Copy() if(collection_mode == COLLECT_SAME) - things = typecache_filter_list(things, typecacheof(I.type)) + things = typecache_filter_list(things, typecacheof(attack_item.type)) var/len = length(things) if(!len) - to_chat(M, "You failed to pick up anything with [parent]!") + to_chat(pre_attack_mob, "You failed to pick up anything with [parent]!") return - var/datum/progressbar/progress = new(M, len, I.loc) + var/datum/progressbar/progress = new(pre_attack_mob, len, attack_item.loc) var/list/rejections = list() - while(do_after(M, 1 SECONDS, parent, NONE, FALSE, CALLBACK(src, .proc/handle_mass_pickup, things, I.loc, rejections, progress))) + while(do_after(pre_attack_mob, 1 SECONDS, parent, NONE, FALSE, CALLBACK(src, .proc/handle_mass_pickup, things, attack_item.loc, rejections, progress))) stoplag(1) progress.end_progress() - to_chat(M, "You put everything you could [insert_preposition] [parent].") + to_chat(pre_attack_mob, "You put everything you could [insert_preposition] [parent].") /datum/component/storage/proc/handle_mass_item_insertion(list/things, datum/component/storage/src_object, mob/user, datum/progressbar/progress) var/atom/source_real_location = src_object.real_location() @@ -758,7 +762,7 @@ return max(0, max_items - real_location.contents.len) /datum/component/storage/proc/signal_fill_type(datum/source, type, amount = 20, force = FALSE) - SIGNAL_HANDLER_DOES_SLEEP + SIGNAL_HANDLER var/atom/real_location = real_location() if(!force) @@ -766,9 +770,8 @@ for(var/i in 1 to amount) if(!handle_item_insertion(new type(real_location), TRUE)) return i > 1 //return TRUE only if at least one insertion has been successful. - if(CHECK_TICK) - if(QDELETED(src)) - return TRUE + if(QDELETED(src)) + return TRUE return TRUE @@ -833,7 +836,7 @@ return hide_from(target) /datum/component/storage/proc/on_alt_click(datum/source, mob/user) - SIGNAL_HANDLER_DOES_SLEEP + SIGNAL_HANDLER if(!isliving(user) || !user.CanReach(parent) || user.incapacitated()) return @@ -849,15 +852,22 @@ A.do_jiggle() //SKYRAT EDIT ADDITION - AESTHETICS return - var/obj/item/I = locate() in real_location() - if(!I) + var/obj/item/to_remove = locate() in real_location() + if(!to_remove) return - A.add_fingerprint(user) - remove_from_storage(I, get_turf(user)) - if(!user.put_in_hands(I)) - to_chat(user, "You fumble for [I] and it falls on the floor.") + + INVOKE_ASYNC(src, .proc/attempt_put_in_hands, to_remove, user) + +///attempt to put an item from contents into the users hands +/datum/component/storage/proc/attempt_put_in_hands(obj/item/to_remove, mob/user) + var/atom/parent_as_atom = parent + + parent_as_atom.add_fingerprint(user) + remove_from_storage(to_remove, get_turf(user)) + if(!user.put_in_hands(to_remove)) + to_chat(user, "You fumble for [to_remove] and it falls on the floor.") return - user.visible_message("[user] draws [I] from [parent]!", "You draw [I] from [parent].") + user.visible_message("[user] draws [to_remove] from [parent]!", "You draw [to_remove] from [parent].") /datum/component/storage/proc/action_trigger(datum/signal_source, datum/action/source) SIGNAL_HANDLER diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index 98239bcc48d..561e989d640 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -141,7 +141,7 @@ * Finally, we return a bitflag to [COMSIG_MOVABLE_IMPACT] that forces the hitpush to false so that we don't knock them away. */ /datum/component/tackler/proc/sack(mob/living/carbon/user, atom/hit) - SIGNAL_HANDLER_DOES_SLEEP + SIGNAL_HANDLER if(!tackling || !tackle) return @@ -149,7 +149,7 @@ user.toggle_throw_mode() if(!iscarbon(hit)) if(hit.density) - return splat(user, hit) + INVOKE_ASYNC(src, .proc/splat, user, hit) return var/mob/living/carbon/target = hit @@ -210,7 +210,7 @@ target.Paralyze(5) target.Knockdown(30) if(ishuman(target) && ishuman(user)) - S.dna.species.grab(S, T) + INVOKE_ASYNC(S.dna.species, /datum/species.proc/grab, S, T) S.setGrabState(GRAB_PASSIVE) if(5 to INFINITY) // absolutely BODIED @@ -224,7 +224,7 @@ target.Paralyze(5) target.Knockdown(30) if(ishuman(target) && ishuman(user)) - S.dna.species.grab(S, T) + INVOKE_ASYNC(S.dna.species, /datum/species.proc/grab, S, T) S.setGrabState(GRAB_AGGRESSIVE) diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index b7e923d7800..259f8029a9d 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -156,13 +156,13 @@ ///Handles stinging without verbs. /datum/antagonist/changeling/proc/stingAtom(mob/living/carbon/ling, atom/A) - SIGNAL_HANDLER_DOES_SLEEP + SIGNAL_HANDLER if(!chosen_sting || A == ling || !istype(ling) || ling.stat) return - if(!chosen_sting.try_to_sting(ling, A)) - return - ling.changeNext_move(CLICK_CD_MELEE) + + INVOKE_ASYNC(chosen_sting, /datum/action/changeling/sting.proc/try_to_sting, ling, A) + return COMSIG_MOB_CANCEL_CLICKON /datum/antagonist/changeling/proc/has_sting(datum/action/changeling/power) diff --git a/code/modules/antagonists/changeling/changeling_power.dm b/code/modules/antagonists/changeling/changeling_power.dm index 4fab82033f7..38ba611a079 100644 --- a/code/modules/antagonists/changeling/changeling_power.dm +++ b/code/modules/antagonists/changeling/changeling_power.dm @@ -53,6 +53,7 @@ the same goes for Remove(). if you override Remove(), call parent or else your p if(sting_action(user, target)) sting_feedback(user, target) c.chem_charges -= chemical_cost + user.changeNext_move(CLICK_CD_MELEE) return TRUE return FALSE diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index db55c297a73..f90ab14fcda 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -96,16 +96,6 @@ spreadFire(AM) /mob/living/carbon/human/Topic(href, href_list) - if(href_list["embedded_object"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERITY)) - var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts - if(!L) - return - var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects - if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore - return - SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L) - return - if(href_list["item"]) //canUseTopic check for this is handled by mob/Topic() var/slot = text2num(href_list["item"]) if(check_obscured_slots(TRUE) & slot) diff --git a/code/modules/vehicles/mecha/mecha_construction_paths.dm b/code/modules/vehicles/mecha/mecha_construction_paths.dm index 198ac970fab..b8476b9cd9e 100644 --- a/code/modules/vehicles/mecha/mecha_construction_paths.dm +++ b/code/modules/vehicles/mecha/mecha_construction_paths.dm @@ -421,7 +421,7 @@ outer_plating_amount=1 /datum/component/construction/mecha/gygax/action(datum/source, atom/used_atom, mob/user) - return check_step(used_atom,user) + return INVOKE_ASYNC(src, .proc/check_step, used_atom,user) /datum/component/construction/mecha/gygax/custom_action(obj/item/I, mob/living/user, diff) if(!..()) diff --git a/modular_skyrat/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm b/modular_skyrat/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm index 5072a084547..28aff04604c 100644 --- a/modular_skyrat/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm +++ b/modular_skyrat/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm @@ -181,8 +181,6 @@ component_type = /datum/component/storage/concrete/peacekeeper /datum/component/storage/concrete/peacekeeper/on_alt_click(datum/source, mob/user) - SIGNAL_HANDLER_DOES_SLEEP - if(!isliving(user) || !user.CanReach(parent) || user.incapacitated()) return if(locked) @@ -191,16 +189,14 @@ var/atom/A = parent - var/obj/item/gun/ballistic/automatic/pistol/P = locate() in real_location() - if(!P) - return + var/obj/item/gun/ballistic/automatic/pistol/gun_to_draw = locate() in real_location() + if(!gun_to_draw) + return ..() A.add_fingerprint(user) - remove_from_storage(P, get_turf(user)) + remove_from_storage(gun_to_draw, get_turf(user)) playsound(parent, 'modular_skyrat/modules/sec_haul/sound/holsterout.ogg', 50, TRUE, -5) - if(!user.put_in_hands(P)) - to_chat(user, "You fumble for [P] and it falls on the floor.") - return - user.visible_message("[user] draws [P] from [parent]!", "You draw [P] from [parent].") + INVOKE_ASYNC(user, /mob/.proc/put_in_hands, gun_to_draw) + user.visible_message("[user] draws [gun_to_draw] from [parent]!", "You draw [gun_to_draw] from [parent].") /datum/component/storage/concrete/peacekeeper/mob_item_insertion_feedback(mob/user, mob/M, obj/item/I, override = FALSE) diff --git a/modular_skyrat/modules/server_overflow/code/chat_link.dm b/modular_skyrat/modules/server_overflow/code/chat_link.dm new file mode 100644 index 00000000000..64b7ddb4dbe --- /dev/null +++ b/modular_skyrat/modules/server_overflow/code/chat_link.dm @@ -0,0 +1,35 @@ + + +/proc/send_ooc_to_other_server(ckey, message) + if(!CONFIG_GET(flag/secondary_server_enabled)) + return + var/list/ooc_information = list() + ooc_information["server_name"] = CONFIG_GET(string/our_server_name) + ooc_information["expected_ckey"] = ckey(ckey) + ooc_information["message"] = message + var/second_server = CONFIG_GET(string/server_two_ip) + if(!second_server) + message_admins("SERVER CONTROL CRITICAL ERROR: No second server IP set in config!") + return + send2otherserver(station_name(), null, "incoming_ooc_message", second_server, ooc_information) + +/datum/world_topic/incoming_ooc_message + keyword = "incoming_ooc_message" + require_comms_key = TRUE + +/datum/world_topic/incoming_ooc_message/Run(list/input) + var/server_name = input["server_name"] + var/exp_ckey = ckey(input["expected_ckey"]) + var/message = input["message"] + + send_ooc_message("[server_name] - [exp_ckey]", message) + +/proc/send_ooc_message(sender_name, message) + if(!GLOB.ooc_allowed) + return + for(var/client/C in GLOB.clients) + if(C.prefs.chat_toggles & CHAT_OOC) + if(GLOB.OOC_COLOR) + to_chat(C, "OOC: [sender_name]: [message]") + else + to_chat(C, "OOC: [sender_name]: [message]")