diff --git a/code/__HELPERS/stacktrace.dm b/code/__HELPERS/stacktrace.dm new file mode 100644 index 00000000000..66cd8ba75d0 --- /dev/null +++ b/code/__HELPERS/stacktrace.dm @@ -0,0 +1,14 @@ +// This file should contain only these two procs in order to make logging filtering easier +// DO NOT ADD ANYTHING ELSE TO THIS FILE FOR THE LOVE OF GOD +// DONT EVEN EXPAN THIS COMMENT, KEEP THE LINE NUMBERS THE SAME +// (The whitespace after this is for line consistency) + + + + + +/proc/stack_trace(msg) + CRASH(msg) + +/datum/proc/stack_trace(msg) + CRASH(msg) diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 7ce8d987722..8d304d8729f 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -411,7 +411,7 @@ var/index = findtext(text, char) var/keylength = length(char) while(index) - log_runtime(EXCEPTION("Bad string given to dmm encoder! [text]")) + stack_trace("Bad string given to dmm encoder! [text]") // Replace w/ underscore to prevent "{4;" from cheesing the radar // Should probably also use canon text replacing procs text = copytext(text, 1, index) + "_" + copytext(text, index+keylength) diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index a4b6f7cebfe..410cbf6ba25 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -100,7 +100,7 @@ if(4.0) return EAST if(8.0) return WEST else - log_runtime(EXCEPTION("UNKNOWN DIRECTION: [direction]")) + stack_trace("UNKNOWN DIRECTION: [direction]") /proc/dir2text(direction) switch(direction) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 954f9a4ec1a..a84489de1af 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1923,13 +1923,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) continue . += A -//gives us the stack trace from CRASH() without ending the current proc. -/proc/stack_trace(msg) - CRASH(msg) - -/datum/proc/stack_trace(msg) - CRASH(msg) - /proc/pass() return diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index a7000f0c760..a06f28c0db3 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -544,7 +544,7 @@ else if(isclient(D)) var/client/C = D href_list[paramname] = C.UID() - log_runtime(EXCEPTION("Found \\ref-based '[paramname]' param in VV topic for [datuminfo], should be UID: [href]")) + stack_trace("Found \\ref-based '[paramname]' param in VV topic for [datuminfo], should be UID: [href]") if(href_list["Vars"]) debug_variables(locateUID(href_list["Vars"])) diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm index 3b942850108..01d01dd1423 100644 --- a/code/datums/helper_datums/map_template.dm +++ b/code/datums/helper_datums/map_template.dm @@ -55,10 +55,10 @@ if(!bounds) return 0 if(bot_left == null || top_right == null) - log_runtime(EXCEPTION("One of the late setup corners is bust"), src) + stack_trace("One of the late setup corners is bust") if(ST_bot_left == null || ST_top_right == null) - log_runtime(EXCEPTION("One of the smoothing corners is bust"), src) + stack_trace("One of the smoothing corners is bust") GLOB.space_manager.remove_dirt(placement.z) late_setup_level( @@ -75,7 +75,7 @@ . = file(mappath) if(!.) - log_runtime(EXCEPTION(" The file of [src] appears to be empty/non-existent."), src) + stack_trace(" The file of [src] appears to be empty/non-existent.") /datum/map_template/proc/get_affected_turfs(turf/T, centered = 0) var/turf/placement = T diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 0d71c8d0e13..f31428fa802 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -120,7 +120,7 @@ var/datum/atom_hud/antag/hud_to_transfer = antag_hud //we need this because leave_hud() will clear this list var/mob/living/old_current = current if(!istype(new_character)) - log_runtime(EXCEPTION("transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob."), src) + stack_trace("transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob.") if(current) //remove ourself from our old body's mind variable current.mind = null leave_all_huds() //leave all the huds in the old body, so it won't get huds if somebody else enters it @@ -725,8 +725,7 @@ return var/datum/mind/targ = new_target if(!istype(targ)) - log_runtime(EXCEPTION("Invalid target for identity theft objective, cancelling"), src) - return + CRASH("Invalid target for identity theft objective, cancelling") new_objective = new /datum/objective/escape/escape_with_identity new_objective.owner = src new_objective.target = new_target diff --git a/code/datums/spawners_menu.dm b/code/datums/spawners_menu.dm index 0a69855638c..5383d20d1b0 100644 --- a/code/datums/spawners_menu.dm +++ b/code/datums/spawners_menu.dm @@ -44,8 +44,7 @@ var/list/possible_spawners = params2list(spawners) var/obj/effect/mob_spawn/MS = locate(pick(possible_spawners)) if(!MS || !istype(MS)) - log_runtime(EXCEPTION("A ghost tried to interact with an invalid spawner, or the spawner didn't exist.")) - return + CRASH("A ghost tried to interact with an invalid spawner, or the spawner didn't exist.") switch(action) if("jump") owner.forceMove(get_turf(MS)) diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm index a3291d61f77..882c3ffce94 100644 --- a/code/defines/procs/admin.dm +++ b/code/defines/procs/admin.dm @@ -7,7 +7,7 @@ /proc/key_name_helper(whom, include_name, include_link = FALSE, type = null) if(include_link != FALSE && include_link != TRUE) - log_runtime(EXCEPTION("Key_name was called with an incorrect include_link [include_link]")) + stack_trace("Key_name was called with an incorrect include_link [include_link]") var/mob/M var/client/C diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 5d6616d196c..464a230085f 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -241,8 +241,7 @@ /datum/dna/proc/head_traits_to_dna(mob/living/carbon/human/character, obj/item/organ/external/head/head_organ) if(!head_organ) - log_runtime(EXCEPTION("Attempting to reset DNA from a missing head!"), src) - return + CRASH("Attempting to reset DNA from a missing head!") if(!head_organ.h_style) head_organ.h_style = "Skinhead" var/hair = GLOB.hair_styles_full_list.Find(head_organ.h_style) diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index 7315b52b062..7e70e907ab2 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -148,6 +148,6 @@ picked_cult = new random_cult() if(!picked_cult) - log_runtime(EXCEPTION("Cult datum creation failed")) + stack_trace("Cult datum creation failed") //todo:add adminonly datum var, check for said var here... return picked_cult diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm index bf7312c25f1..1a845d39e8d 100644 --- a/code/game/gamemodes/wizard/raginmages.dm +++ b/code/game/gamemodes/wizard/raginmages.dm @@ -137,8 +137,8 @@ mages_made++ return TRUE else - log_runtime(EXCEPTION("The candidates list for ragin' mages contained non-observer entries!"), src) - return FALSE + . = FALSE + CRASH("The candidates list for ragin' mages contained non-observer entries!") // ripped from -tg-'s wizcode, because whee lets make a very general proc for a very specific gamemode // This probably wouldn't do half bad as a proc in __HELPERS diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index 70256099b9e..4ddb356d2fc 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -29,8 +29,8 @@ var/turf/T = loc if(!T.transparent_floor) hide(T.intact) - if(!codes || !codes.len) - log_runtime(EXCEPTION("Empty codes datum at ([x],[y],[z])"), src, list("codes_txt: '[codes_txt]'")) + if(!length(codes)) + stack_trace("Empty codes datum at ([x],[y],[z]) (codes_txt: [codes_txt])") if("patrol" in codes) if(!GLOB.navbeacons["[z]"]) GLOB.navbeacons["[z]"] = list() diff --git a/code/game/objects/effects/spawners/random_barrier.dm b/code/game/objects/effects/spawners/random_barrier.dm index 6de7e48b60f..40897a60bcd 100644 --- a/code/game/objects/effects/spawners/random_barrier.dm +++ b/code/game/objects/effects/spawners/random_barrier.dm @@ -17,14 +17,13 @@ . = ..() var/turf/T = get_turf(src) if(!T) - log_runtime(EXCEPTION("Barrier spawner placed in nullspace!"), src) - return + CRASH("Barrier spawner placed in nullspace!") var/thing_to_place = pickweight(result) if(ispath(thing_to_place, /turf)) T.ChangeTurf(thing_to_place) else new thing_to_place(T) - qdel(src) + return INITIALIZE_HINT_QDEL /obj/effect/spawner/random_barrier/wall_probably name = "probably a wall" diff --git a/code/game/objects/effects/spawners/random_spawners.dm b/code/game/objects/effects/spawners/random_spawners.dm index 69831545397..2dbe235c6cb 100644 --- a/code/game/objects/effects/spawners/random_spawners.dm +++ b/code/game/objects/effects/spawners/random_spawners.dm @@ -10,11 +10,12 @@ var/spawn_inside = null // This needs to use New() instead of Initialize() because the thing it creates might need to be initialized too +// AA 2022-08-11: The above comment doesnt even make sense. If extra atoms are loaded during SSatoms.Initialize(), they still get initialised! /obj/effect/spawner/random_spawners/New() . = ..() var/turf/T = get_turf(src) if(!T) - log_runtime(EXCEPTION("Spawner placed in nullspace!"), src) + stack_trace("Spawner placed in nullspace!") return randspawn(T) diff --git a/code/game/objects/effects/spawners/windowspawner.dm b/code/game/objects/effects/spawners/windowspawner.dm index ed4e7dcb48e..8d8654957cc 100644 --- a/code/game/objects/effects/spawners/windowspawner.dm +++ b/code/game/objects/effects/spawners/windowspawner.dm @@ -13,7 +13,7 @@ var/obj/structure/window/WI for(var/obj/structure/grille/G in get_turf(src)) // Complain noisily - log_runtime(EXCEPTION("Extra grille on turf: ([T.x],[T.y],[T.z])"), src) + stack_trace("Extra grille on turf: ([T.x],[T.y],[T.z])") qdel(G) //just in case mappers don't know what they are doing if(!useFull) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 629bae3407d..d282899d0ea 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -322,7 +322,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list( return ..() /mob/living/automatedannouncer/proc/autocleanup() - log_runtime(EXCEPTION("An announcer somehow managed to outlive the radio! Deleting!"), src, list("Message: '[message]'")) + stack_trace("An announcer somehow managed to outlive the radio! Deleting! (Message: [message])") qdel(src) // Interprets the message mode when talking into a radio, possibly returning a connection datum diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm index 3d0930b1dc0..5ee94588ffd 100644 --- a/code/game/objects/items/weapons/defib.dm +++ b/code/game/objects/items/weapons/defib.dm @@ -65,7 +65,7 @@ . += "[icon_state]-emagged" if(powered) . += "[icon_state]-powered" - if(powered && cell) + if(powered && cell) var/ratio = cell.charge / cell.maxcharge ratio = CEILING(ratio*4, 1) * 25 . += "[icon_state]-charge[ratio]" @@ -562,7 +562,7 @@ if(ghost && !ghost.client) // In case the ghost's not getting deleted for some reason H.key = ghost.key - log_runtime(EXCEPTION("Ghost of name [ghost.name] is bound to [H.real_name], but lacks a client. Deleting ghost."), H) + stack_trace("Ghost of name [ghost.name] is bound to [H.real_name], but lacks a client. Deleting ghost.") QDEL_NULL(ghost) var/tplus = world.time - H.timeofdeath diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index bfd45d88da8..a0409084346 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -77,7 +77,7 @@ H = M if(!buf) - log_runtime(EXCEPTION("[src] used by [user] on [M] failed to initialize properly."), src) + stack_trace("[src] used by [user] on [M] failed to initialize properly.") return spawn(0) //Some mutations have sleeps in them, like monkey diff --git a/code/game/objects/items/weapons/rpd.dm b/code/game/objects/items/weapons/rpd.dm index d1edf8560cc..7ef650799dd 100644 --- a/code/game/objects/items/weapons/rpd.dm +++ b/code/game/objects/items/weapons/rpd.dm @@ -95,8 +95,7 @@ /obj/item/rpd/proc/create_atmos_pipe(mob/user, turf/T) //Make an atmos pipe, meter, or gas sensor if(!can_dispense_pipe(whatpipe, RPD_ATMOS_MODE)) - log_runtime(EXCEPTION("Failed to spawn [get_pipe_name(whatpipe, PIPETYPE_ATMOS)] - possible tampering detected")) //Damn dirty apes -- I mean hackers - return + CRASH("Failed to spawn [get_pipe_name(whatpipe, PIPETYPE_ATMOS)] - possible tampering detected") //Damn dirty apes -- I mean hackers var/obj/item/pipe/P if(whatpipe == PIPE_GAS_SENSOR) P = new /obj/item/pipe_gsensor(T) @@ -117,8 +116,7 @@ /obj/item/rpd/proc/create_disposals_pipe(mob/user, turf/T) //Make a disposals pipe / construct if(!can_dispense_pipe(whatdpipe, RPD_DISPOSALS_MODE)) - log_runtime(EXCEPTION("Failed to spawn [get_pipe_name(whatdpipe, PIPETYPE_DISPOSAL)] - possible tampering detected")) - return + CRASH("Failed to spawn [get_pipe_name(whatdpipe, PIPETYPE_DISPOSAL)] - possible tampering detected") var/obj/structure/disposalconstruct/P = new(T, whatdpipe, iconrotation) if(!iconrotation) //Automatic rotation P.dir = user.dir @@ -287,7 +285,7 @@ playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE) to_chat(user, "ERROR: \The [T] is out of [src]'s range!") return - + T.rpd_act(user, src) #undef RPD_COOLDOWN_TIME diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 2fa5a0180c0..caaf888573c 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -708,9 +708,9 @@ if(islist(thing)) list_to_object(thing, src) else if(thing == null) - log_runtime(EXCEPTION("Null entry found in storage/deserialize."), src) + stack_trace("Null entry found in storage/deserialize.") else - log_runtime(EXCEPTION("Non-list thing found in storage/deserialize."), src, list("Thing: [thing]")) + stack_trace("Non-list thing found in storage/deserialize (Thing: [thing])") ..() /obj/item/storage/AllowDrop() diff --git a/code/modules/antagonists/vampire/vampire_powers/dantalion_powers.dm b/code/modules/antagonists/vampire/vampire_powers/dantalion_powers.dm index c46ee037fdf..0949add5841 100644 --- a/code/modules/antagonists/vampire/vampire_powers/dantalion_powers.dm +++ b/code/modules/antagonists/vampire/vampire_powers/dantalion_powers.dm @@ -39,28 +39,28 @@ to_chat(user, "You or your target moved.") /obj/effect/proc_holder/spell/vampire/enthrall/proc/can_enthrall(mob/living/user, mob/living/carbon/C) + . = FALSE if(!C) - log_runtime(EXCEPTION("target was null while trying to vampire enthrall, attacker is [user] [user.key] \ref[user]"), user) - return FALSE + CRASH("target was null while trying to vampire enthrall, attacker is [user] [user.key] \ref[user]") if(!user.mind.som) CRASH("Dantalion Thrall datum ended up null.") if(!ishuman(C)) to_chat(user, "You can only enthrall sentient humanoids!") - return FALSE + return if(!C.mind) to_chat(user, "[C.name]'s mind is not there for you to enthrall.") - return FALSE + return var/datum/antagonist/vampire/V = user.mind.has_antag_datum(/datum/antagonist/vampire) if(V.subclass.thrall_cap <= length(user.mind.som.serv)) to_chat(user, "You don't have enough power to enthrall any more people!") - return FALSE + return if(ismindshielded(C) || C.mind.has_antag_datum(/datum/antagonist/vampire) || C.mind.has_antag_datum(/datum/antagonist/mindslave)) C.visible_message("[C] seems to resist the takeover!", "You feel a familiar sensation in your skull that quickly dissipates.") - return FALSE + return if(C.mind.isholy) C.visible_message("[C] seems to resist the takeover!", "Your faith in [SSticker.Bible_deity_name] has kept your mind clear of all evil.") - return FALSE + return return TRUE /obj/effect/proc_holder/spell/vampire/enthrall/proc/handle_enthrall(mob/living/user, mob/living/carbon/human/H) diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index c9441c8d274..41e77fdc8d1 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -267,8 +267,8 @@ if(!alarm_area) alarm_area = get_area(src) if(!alarm_area) - log_runtime(EXCEPTION("Air alarm /obj/machinery/alarm lacks alarm_area vars during proc/master_is_operating()"), src) - return FALSE + . = FALSE + CRASH("Air alarm /obj/machinery/alarm lacks alarm_area vars during proc/master_is_operating()") return alarm_area.master_air_alarm && !(alarm_area.master_air_alarm.stat & (NOPOWER|BROKEN)) diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index ff9fb9a4ab1..1f4529c9e43 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -57,7 +57,7 @@ GLOBAL_VAR_INIT(pipenetwarnings, 10) if(!members.Find(item)) if(item.parent) - log_runtime(EXCEPTION("[item.type] \[\ref[item]] added to a pipenet while still having one ([item.parent]) (pipes leading to the same spot stacking in one turf). Nearby: [item.x], [item.y], [item.z].")) + stack_trace("[item.type] \[\ref[item]] added to a pipenet while still having one ([item.parent]) (pipes leading to the same spot stacking in one turf). Nearby: [item.x], [item.y], [item.z].") members += item possible_expansions += item diff --git a/code/modules/awaymissions/maploader/reader.dm b/code/modules/awaymissions/maploader/reader.dm index 2f807cb1db2..336c84b9655 100644 --- a/code/modules/awaymissions/maploader/reader.dm +++ b/code/modules/awaymissions/maploader/reader.dm @@ -156,14 +156,7 @@ GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new()) log_debug("Loaded map in [stop_watch(watch)]s.") qdel(LM) if(bounds[MAP_MINX] == 1.#INF) // Shouldn't need to check every item - log_runtime(EXCEPTION("Bad Map bounds in [fname]"), src, list( - "Min x: [bounds[MAP_MINX]]", - "Min y: [bounds[MAP_MINY]]", - "Min z: [bounds[MAP_MINZ]]", - "Max x: [bounds[MAP_MAXX]]", - "Max y: [bounds[MAP_MAXY]]", - "Max z: [bounds[MAP_MAXZ]]")) - return null + CRASH("Bad Map bounds in [fname], Min x: [bounds[MAP_MINX]], Min y: [bounds[MAP_MINY]], Min z: [bounds[MAP_MINZ]], Max x: [bounds[MAP_MAXX]], Max y: [bounds[MAP_MAXY]], Max z: [bounds[MAP_MAXZ]]") else if(!measureOnly) for(var/t in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]), locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ]))) @@ -227,7 +220,7 @@ GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new()) old_position = dpos + 1 if(!atom_def) // Skip the item if the path does not exist. Fix your crap, mappers! - log_runtime(EXCEPTION("Bad path: [atom_text]"), src, list("Source String: [model]", "dpos: [dpos]")) + stack_trace("Bad path: [atom_text] | Source String: [model] | dpos: [dpos]") continue members.Add(atom_def) @@ -453,7 +446,7 @@ GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new()) try A.deserialize(json_decode(json_data)) catch(var/exception/E) - log_runtime(EXCEPTION("Bad json data: '[json_data]'"), src) + stack_trace("Bad json data: '[json_data]'") throw E for(var/attribute in attributes) var/value = attributes[attribute] diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 117d3feb044..81583716b9a 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -47,14 +47,10 @@ hsrc = locate(href_list["src"]) if(hsrc) var/hsrc_info = datum_info_line(hsrc) || "[hsrc]" - log_runtime(EXCEPTION("Got \\ref-based src in topic from [src] for [hsrc_info], should be UID: [href]")) + stack_trace("Got \\ref-based src in topic from [src] for [hsrc_info], should be UID: [href]") - #if defined(TOPIC_DEBUGGING) - to_chat(world, "[src]'s Topic: [href] destined for [hsrc].") - #endif if(href_list["asset_cache_confirm_arrival"]) -// to_chat(src, "ASSET JOB [href_list["asset_cache_confirm_arrival"]] ARRIVED.") var/job = text2num(href_list["asset_cache_confirm_arrival"]) completed_asset_jobs += job return @@ -64,17 +60,19 @@ // Rate limiting var/mtl = 100 // 100 topics per minute - if (!holder) // Admins are allowed to spam click, deal with it. + if(!holder) // Admins are allowed to spam click, deal with it. var/minute = round(world.time, 600) - if (!topiclimiter) + if(!topiclimiter) topiclimiter = new(LIMITER_SIZE) - if (minute != topiclimiter[CURRENT_MINUTE]) + + if(minute != topiclimiter[CURRENT_MINUTE]) topiclimiter[CURRENT_MINUTE] = minute topiclimiter[MINUTE_COUNT] = 0 + topiclimiter[MINUTE_COUNT] += 1 - if (topiclimiter[MINUTE_COUNT] > mtl) + if(topiclimiter[MINUTE_COUNT] > mtl) var/msg = "Your previous action was ignored because you've done too many in a minute." - if (minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them) + if(minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them) topiclimiter[ADMINSWARNED_AT] = minute msg += " Administrators have been informed." log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute") @@ -83,22 +81,24 @@ return var/stl = 10 // 10 topics a second - if (!holder) // Admins are allowed to spam click, deal with it. + if(!holder) // Admins are allowed to spam click, deal with it. var/second = round(world.time, 10) - if (!topiclimiter) + if(!topiclimiter) topiclimiter = new(LIMITER_SIZE) - if (second != topiclimiter[CURRENT_SECOND]) + + if(second != topiclimiter[CURRENT_SECOND]) topiclimiter[CURRENT_SECOND] = second topiclimiter[SECOND_COUNT] = 0 + topiclimiter[SECOND_COUNT] += 1 - if (topiclimiter[SECOND_COUNT] > stl) + if(topiclimiter[SECOND_COUNT] > stl) to_chat(src, "Your previous action was ignored because you've done too many in a second") return //search the href for script injection - if( findtext(href,"SSD warning acknowledged.") return + if(href_list["link_forum_account"]) link_forum_account() return // prevents a recursive loop where the ..() 5 lines after this makes the proc endlessly re-call itself + if(href_list["withdraw_consent"]) var/choice = alert(usr, "Are you SURE you want to withdraw your consent to the Terms of Service?\nYou will be instantaneously removed from the server and will have to re-accept the Terms of Service.", "Warning", "Yes", "No") if(choice == "Yes") @@ -145,6 +145,7 @@ var/datum/db_query/query = SSdbcore.NewQuery("REPLACE INTO privacy (ckey, datetime, consent) VALUES (:ckey, Now(), 0)", list( "ckey" = ckey )) + if(!query.warn_execute()) to_chat(usr, "Well, this is embarassing. We tried to save your ToS withdrawal but the DB failed. Please contact the server host") return @@ -153,6 +154,7 @@ message_admins("[key_name_admin(usr)] was disconnected due to withdrawing their ToS consent.") to_chat(usr, "Your ToS consent has been withdrawn. You have been kicked from the server") qdel(src) + return if(href_list["__keydown"]) var/keycode = href_list["__keydown"] @@ -178,12 +180,6 @@ var/fakekey = holder?.fakekey return fakekey ? fakekey : key -/client/proc/is_content_unlocked() - if(!prefs.unlock_content) - to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. Click here to find out more.") - return 0 - return 1 - //Like for /atoms, but clients are their own snowflake FUCK /client/proc/setDir(newdir) dir = newdir @@ -195,25 +191,28 @@ to_chat(src, "You are sending messages to quickly. Please wait [wait_time] [wait_time == 1 ? "second" : "seconds"] before sending another message.") return 1 last_message_time = world.time + if(GLOB.configuration.general.enable_auto_mute && !check_rights(R_ADMIN, 0) && last_message == message) last_message_count++ if(last_message_count >= SPAM_TRIGGER_AUTOMUTE) to_chat(src, "You have exceeded the spam filter limit for identical messages. An auto-mute was applied.") cmd_admin_mute(mob, mute_type, 1) - return 1 + return TRUE + if(last_message_count >= SPAM_TRIGGER_WARNING) to_chat(src, "You are nearing the spam filter limit for identical messages.") - return 0 + return FALSE + else last_message = message last_message_count = 0 - return 0 + return FALSE //This stops files larger than UPLOAD_LIMIT being sent from client to server via input(), client.Import() etc. /client/AllowUpload(filename, filelength) if(filelength > UPLOAD_LIMIT) to_chat(src, "Error: AllowUpload(): File Upload too large. Upload Limit: [UPLOAD_LIMIT/1024]KiB.") - return 0 + return FALSE /* //Don't need this at the moment. But it's here if it's needed later. //Helps prevent multiple files being uploaded at once. Or right after eachother. var/time_to_wait = fileaccess_timer - world.time @@ -221,7 +220,7 @@ to_chat(src, "Error: AllowUpload(): Spam prevention. Please wait [round(time_to_wait/10)] seconds.") return 0 fileaccess_timer = world.time + FTPDELAY */ - return 1 + return TRUE /////////// @@ -234,14 +233,18 @@ if(connection != "seeker") //Invalid connection type. return null + if(byond_version < MIN_CLIENT_VERSION) // Too out of date to play at all. Unfortunately, we can't send them a message here. version_blocked = TRUE + if(byond_build < GLOB.configuration.general.minimum_client_build) version_blocked = TRUE var/show_update_prompt = FALSE + if(byond_version < SUGGESTED_CLIENT_VERSION) // Update is suggested, but not required. show_update_prompt = TRUE + else if(byond_version == SUGGESTED_CLIENT_VERSION && byond_build < SUGGESTED_CLIENT_BUILD) show_update_prompt = TRUE @@ -282,6 +285,7 @@ CLP.process_result(login_queries[CLP.type], src) QDEL_LIST_ASSOC_VAL(login_queries) // Clear out the used queries + else // Set vars here that need to be set if the DB is offline @@ -304,6 +308,7 @@ // Log alts if(length(related_accounts_ip)) log_admin("[key_name(src)] Alts by IP: [jointext(related_accounts_ip, " ")]") + if(length(related_accounts_cid)) log_admin("[key_name(src)] Alts by CID: [jointext(related_accounts_cid, " ")]") @@ -329,6 +334,7 @@ deadmin() verbs += /client/proc/readmin GLOB.deadmins += ckey + else on_holder_add() add_admin_verbs() @@ -361,6 +367,7 @@ if(prefs.toggles & PREFTOGGLE_UI_DARKMODE) // activates dark mode if its flagged. -AA07 activate_darkmode() + else // activate_darkmode() calls the CL update button proc, so we dont want it double called SSchangelog.UpdatePlayerChangelogButton(src) @@ -430,17 +437,21 @@ announce_leave() // Do not put this below SSdebugview.stop_processing(src) SSchangelog.startup_clients_open -= src + if(holder) holder.owner = null GLOB.admins -= src + GLOB.directory -= ckey GLOB.clients -= src SSinstancing.update_playercache() // Clear us out QDEL_NULL(chatOutput) QDEL_NULL(pai_save) + if(movingmob) movingmob.client_mobs_in_contents -= mob UNSETEMPTY(movingmob.client_mobs_in_contents) + SSambience.ambience_listening_clients -= src SSinput.processing -= src Master.UpdateTickRate() @@ -563,6 +574,7 @@ qdel(query_update) // After the regular update INVOKE_ASYNC(src, /client/.proc/get_byond_account_date, FALSE) // Async to avoid other procs in the client chain being delayed by a web request + else //New player!! Need to insert all the stuff var/datum/db_query/query_insert = SSdbcore.NewQuery("INSERT INTO player (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, :ckey, Now(), Now(), :ip, :cid, :rank)", list( @@ -623,24 +635,29 @@ /client/proc/check_forum_link() if(!GLOB.configuration.url.forum_link_url || !prefs || prefs.fuid) return + if(GLOB.configuration.jobs.enable_exp_tracking) var/living_hours = get_exp_type_num(EXP_TYPE_LIVING) / 60 if(living_hours < 20) return + to_chat(src, "You have no verified forum account. VERIFY FORUM ACCOUNT") /client/proc/create_oauth_token() var/datum/db_query/query_find_token = SSdbcore.NewQuery("SELECT token FROM oauth_tokens WHERE ckey=:ckey limit 1", list( "ckey" = ckey )) + // These queries have log_error=FALSE to avoid auth tokens being in plaintext logs if(!query_find_token.warn_execute(log_error=FALSE)) qdel(query_find_token) return + if(query_find_token.NextRow()) var/tkn = query_find_token.item[1] qdel(query_find_token) return tkn + qdel(query_find_token) var/tokenstr = md5("[rand(0,9999)][world.time][rand(0,9999)][ckey][rand(0,9999)][address][rand(0,9999)][computer_id][rand(0,9999)]") @@ -649,40 +666,49 @@ "ckey" = ckey, "tokenstr" = tokenstr, )) + // These queries have log_error=FALSE to avoid auth tokens being in plaintext logs - if(!query_insert_token.warn_execute(log_error=FALSE)) + if(!query_insert_token.warn_execute(log_error = FALSE)) qdel(query_insert_token) return + qdel(query_insert_token) return tokenstr /client/proc/link_forum_account(fromban) if(!GLOB.configuration.url.forum_link_url) return + if(IsGuestKey(key)) to_chat(src, "Guest keys cannot be linked.") return + if(prefs && prefs.fuid) if(!fromban) to_chat(src, "Your forum account is already set.") return + var/datum/db_query/query_find_link = SSdbcore.NewQuery("SELECT fuid FROM player WHERE ckey=:ckey LIMIT 1", list( "ckey" = ckey )) + if(!query_find_link.warn_execute()) qdel(query_find_link) return + if(query_find_link.NextRow()) if(query_find_link.item[1]) if(!fromban) to_chat(src, "Your forum account is already set. ([query_find_link.item[1]])") qdel(query_find_link) return + qdel(query_find_link) var/tokenid = create_oauth_token() if(!tokenid) to_chat(src, "link_forum_account: unable to create token") return + var/url = "[GLOB.configuration.url.forum_link_url][tokenid]" if(fromban) url += "&fwd=appeal" @@ -690,6 +716,7 @@ to_chat(src, "If you are screenshotting this screen for your ban appeal, please blur/draw over the token in the above link.") else to_chat(src, {"Now opening a window to verify your information with the forums. If the window does not load, please go to: [url]"}) + src << link(url) return @@ -701,11 +728,14 @@ /client/proc/check_randomizer(topic) set waitfor = FALSE // Yes I know this is already called from an async proc but someone may change that without thinking properly . = FALSE + if(connection != "seeker") //Invalid connection type. return null + topic = params2list(topic) if(!GLOB.configuration.general.enabled_cid_randomiser_buster) return + // Stash o' ckeys var/static/cidcheck = list() var/static/tokens = list() @@ -719,6 +749,7 @@ var/datum/db_query/query_cidcheck = SSdbcore.NewQuery("SELECT computerid FROM player WHERE ckey=:ckey", list( "ckey" = ckey )) + if(!query_cidcheck.warn_execute()) qdel(query_cidcheck) return @@ -726,6 +757,7 @@ var/lastcid = computer_id if(query_cidcheck.NextRow()) lastcid = query_cidcheck.item[1] + qdel(query_cidcheck) if(computer_id != lastcid) @@ -741,9 +773,10 @@ to_chat(src, "
you're a huge nerd. wakka wakka doodle doop nobody's ever gonna see this, the chat system shouldn't be online by this point
") qdel(src) return TRUE + else - if (!topic || !topic["token"] || !tokens[ckey] || topic["token"] != tokens[ckey]) - if (!cidcheck_spoofckeys[ckey]) + if(!topic || !topic["token"] || !tokens[ckey] || topic["token"] != tokens[ckey]) + if(!cidcheck_spoofckeys[ckey]) message_admins("[key_name(src)] appears to have attempted to spoof a cid randomizer check.") cidcheck_spoofckeys[ckey] = TRUE cidcheck[ckey] = computer_id @@ -752,6 +785,7 @@ sleep(10) //browse is queued, we don't want them to disconnect before getting the browse() command. qdel(src) return TRUE + // We DO have their cached CID handy - compare it, now if(oldcid != computer_id) // Change detected, they are randomizing @@ -770,6 +804,7 @@ qdel(src) return TRUE + else // don't shoot, I'm innocent if(cidcheck_failedckeys[ckey]) @@ -777,7 +812,8 @@ message_admins("[key_name_admin(src)] has been allowed to connect after showing they removed their cid randomizer") SSdiscord.send2discord_simple_noadmins("**\[Info]** [key_name(src)] has been allowed to connect after showing they removed their cid randomizer.") cidcheck_failedckeys -= ckey - if (cidcheck_spoofckeys[ckey]) + + if(cidcheck_spoofckeys[ckey]) message_admins("[key_name_admin(src)] has been allowed to connect after appearing to have attempted to spoof a cid randomizer check because it appears they aren't spoofing one this time") cidcheck_spoofckeys -= ckey cidcheck -= ckey @@ -790,33 +826,42 @@ "ckey" = ckey, "adminckey" = adminckey )) + if(!query_get_notes.warn_execute()) qdel(query_get_notes) return + if(query_get_notes.NextRow()) qdel(query_get_notes) return + qdel(query_get_notes) // Only add a note if their most recent note isn't from the randomizer blocker, either var/datum/db_query/query_get_note = SSdbcore.NewQuery("SELECT adminckey FROM notes WHERE ckey=:ckey ORDER BY timestamp DESC LIMIT 1", list( "ckey" = ckey )) + if(!query_get_note.warn_execute()) qdel(query_get_note) return + if(query_get_note.NextRow()) if(query_get_note.item[1] == adminckey) qdel(query_get_note) return + qdel(query_get_note) - add_note(ckey, "Detected as using a cid randomizer.", null, adminckey, logged = 0) + add_note(ckey, "Detected as using a cid randomizer.", null, adminckey, logged = FALSE) /client/proc/cid_check_reconnect() var/token = md5("[rand(0,9999)][world.time][rand(0,9999)][ckey][rand(0,9999)][address][rand(0,9999)][computer_id][rand(0,9999)]") . = token + log_adminwarn("Failed Login: [key] [computer_id] [address] - CID randomizer check") + var/url = winget(src, null, "url") + //special javascript to make them reconnect under a new window. src << browse("\ byond://[url]?token=[token]\ @@ -826,12 +871,12 @@ window.location=\"byond://winset?command=.quit\"\ ", "border=0;titlebar=0;size=1x1") + to_chat(src, "You will be automatically taken to the game, if not, click here to be taken manually. Except you can't, since the chat window doesn't exist yet.") -//checks if a client is afk -//3000 frames = 5 minutes -/client/proc/is_afk(duration=3000) - if(inactivity > duration) return inactivity +/client/proc/is_afk(duration = 5 MINUTES) + if(inactivity > duration) + return inactivity return 0 //Send resources to the client. @@ -839,13 +884,16 @@ // Change the way they should download resources. if(length(GLOB.configuration.url.rsc_urls)) preload_rsc = pick(GLOB.configuration.url.rsc_urls) + else preload_rsc = 1 // If config.resource_urls is not set, preload like normal. + // Most assets are now handled through global_cache.dm getFiles( 'html/search.js', // Used in various non-TGUI HTML windows for search functionality 'html/panels.css' // Used for styling certain panels, such as in the new player panel ) + spawn (10) //removing this spawn causes all clients to not get verbs. //Precache the client with all other assets slowly, so as to not block other browse() calls getFilesSlow(src, SSassets.preload, register_asset = FALSE) @@ -855,8 +903,10 @@ for(var/L in GLOB.all_languages) var/datum/language/lang = GLOB.all_languages[L] var/message = "[lang.name] : [lang.type]" + if(lang.flags & RESTRICTED) message += " (RESTRICTED)" + to_chat(world, "[message]") /client/proc/colour_transition(list/colour_to = null, time = 10) //Call this with no parameters to reset to default. @@ -950,10 +1000,13 @@ /client/proc/send_ssd_warning(mob/M) if(!GLOB.configuration.general.ssd_warning) return FALSE + if(ssd_warning_acknowledged) return FALSE - if(M && M.player_logged < SSD_WARNING_TIMER) + + if(M?.player_logged < SSD_WARNING_TIMER) return FALSE + to_chat(src, "Are you taking this person to cryo or giving them medical treatment? If you are, confirm that and proceed. Interacting with SSD players in other ways is against server rules unless you've ahelped first for permission.") return TRUE @@ -1009,13 +1062,16 @@ var/list/lines = splittext(http["CONTENT"], "\n") var/list/initial_data = list() var/current_index = "" + for(var/L in lines) if(L == "") continue + if(!findtext(L, "\t")) current_index = L initial_data[current_index] = list() continue + initial_data[current_index] += replacetext(replacetext(L, "\t", ""), "\"", "") var/list/parsed_data = list() @@ -1032,12 +1088,15 @@ // Main return is here return parsed_data + catch log_debug("Error parsing byond.com data for [ckey]. Please inform maintainers.") return null + else log_debug("Error retrieving data from byond.com for [ckey]. Invalid status code (Expected: 200 | Got: [status]).") return null + else log_debug("Failed to retrieve data from byond.com for [ckey]. Connection failed.") return null @@ -1056,6 +1115,7 @@ var/datum/db_query/query_date = SSdbcore.NewQuery("SELECT byond_date, DATEDIFF(Now(), byond_date) FROM player WHERE ckey=:ckey", list( "ckey" = ckey )) + if(!query_date.warn_execute()) qdel(query_date) return @@ -1083,21 +1143,25 @@ "date" = byondacc_date, "ckey" = ckey )) + if(!query_update.warn_execute()) qdel(query_update) return + qdel(query_update) // Now retrieve the age again because BYOND doesnt have native methods for this var/datum/db_query/query_age = SSdbcore.NewQuery("SELECT DATEDIFF(Now(), byond_date) FROM player WHERE ckey=:ckey", list( "ckey" = ckey )) + if(!query_age.warn_execute()) qdel(query_age) return while(query_age.NextRow()) byondacc_age = max(text2num(query_age.item[1]), 0) // Ensure account isnt negative days old + qdel(query_age) // Notify admins on new clients connecting, if the byond account age is less than a config value @@ -1111,7 +1175,9 @@ if(prefs.sound & SOUND_AMBIENCE) if(SSambience.ambience_listening_clients[src] > world.time) return // If already properly set we don't want to reset the timer. + SSambience.ambience_listening_clients[src] = world.time + 10 SECONDS //Just wait 10 seconds before the next one aight mate? cheers. + else SSambience.ambience_listening_clients -= src @@ -1124,12 +1190,11 @@ var/output = GLOB.join_tos output += "

By withdrawing your consent, you acknowledge that you will be instantaneously kicked from the server and will have to re-accept the Terms of Service. If you do not wish to withdraw your consent at this moment, feel free to close this window.

" output += "

Withdraw consent

" - src << browse(output,"window=privacy_consent;size=600x500") + var/datum/browser/popup = new(src, "privacy_consent", "
Privacy Consent
", 500, 400) + popup.set_content(output) popup.open(FALSE) - return - #undef LIMITER_SIZE #undef CURRENT_SECOND diff --git a/code/modules/client/preference/preferences_mysql.dm b/code/modules/client/preference/preferences_mysql.dm index c22e539650f..63b035f4273 100644 --- a/code/modules/client/preference/preferences_mysql.dm +++ b/code/modules/client/preference/preferences_mysql.dm @@ -54,7 +54,7 @@ // Might as well scrub out any malformed be_special list entries while we're here for(var/role in be_special) if(!(role in GLOB.special_roles)) - log_runtime(EXCEPTION("[C.key] had a malformed role entry: '[role]'. Removing!"), src) + stack_trace("[C.key] had a malformed role entry: '[role]'. Removing!") be_special -= role // We're saving volume_mixer here as well, so no point in keeping the timer running diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index 4995f798968..6c03a99495e 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -106,17 +106,3 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0) if(GLOB.error_cache) GLOB.error_cache.logError(e, desclines, e_src = e_src) #endif - -/proc/log_runtime(exception/e, datum/e_src, extra_info) - if(!istype(e)) - world.Error(e, e_src) - return - - if(extra_info) - // Adding extra info adds two newlines, because parsing runtimes is funky - if(islist(extra_info)) - e.desc = " [jointext(extra_info, "\n ")]\n\n" + e.desc - else - e.desc = " [extra_info]\n\n" + e.desc - - world.Error(e, e_src) diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm index 748d39f2080..ab53564c0fb 100644 --- a/code/modules/events/prison_break.dm +++ b/code/modules/events/prison_break.dm @@ -53,7 +53,7 @@ to_chat(A, "Malicious program detected in the [english_list(areaName)] lighting and airlock control systems by [my_department].") else - log_runtime("Could not initate grey-tide. Unable to find suitable containment area.", src) + stack_trace("Could not initate grey-tide. Unable to find suitable containment area.") kill() /datum/event/prison_break/tick() diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 539ab5e7573..bb0c335d183 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -378,14 +378,14 @@ for(var/i in 1 to seed.growthstages) if("[seed.icon_grow][i]" in states) continue - log_runtime("[seed.name] ([seed.type]) lacks the [seed.icon_grow][i] icon!") + stack_trace("[seed.name] ([seed.type]) lacks the [seed.icon_grow][i] icon!") if(!(seed.icon_dead in states)) - log_runtime("[seed.name] ([seed.type]) lacks the [seed.icon_dead] icon!") + stack_trace("[seed.name] ([seed.type]) lacks the [seed.icon_dead] icon!") if(seed.icon_harvest) // mushrooms have no grown sprites, same for items with no product if(!(seed.icon_harvest in states)) - log_runtime("[seed.name] ([seed.type]) lacks the [seed.icon_harvest] icon!") + stack_trace("[seed.name] ([seed.type]) lacks the [seed.icon_harvest] icon!") /obj/item/seeds/proc/randomize_stats() set_lifespan(rand(25, 60)) diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index 92e454d007f..8cf1657d19f 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -29,7 +29,7 @@ return template = GLOB.shelter_templates[template_id] if(!template) - log_runtime("Shelter template ([template_id]) not found!", src) + stack_trace("Shelter template ([template_id]) not found!") qdel(src) /obj/item/survivalcapsule/examine(mob/user) diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 3be309721ef..979595d0eda 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -43,8 +43,7 @@ return if(held_brain) to_chat(user, "Somehow, this MMI still has a brain in it. Report this to the bug tracker.") - log_runtime(EXCEPTION("[user] tried to stick a [O] into [src] in [get_area(src)], but the held brain variable wasn't cleared"), src) - return + CRASH("[user] tried to stick a [O] into [src] in [get_area(src)], but the held brain variable wasn't cleared") if(user.drop_item()) B.forceMove(src) if(!syndiemmi) @@ -157,7 +156,7 @@ //problem i was having with alien/nonalien brain drops. /obj/item/mmi/proc/dropbrain(turf/dropspot) if(isnull(held_brain)) - log_runtime(EXCEPTION("[src] at [loc] attempted to drop brain without a contained brain in [get_area(src)]."), src) + stack_trace("[src] at [loc] attempted to drop brain without a contained brain in [get_area(src)].") to_chat(brainmob, "Your MMI did not contain a brain! We'll make a new one for you, but you'd best report this to the bugtracker!") held_brain = new(dropspot) // Let's not ruin someone's round because of something dumb -- Crazylemon held_brain.dna = brainmob.dna.Clone() diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 4622858409a..455c4df8ccd 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -33,7 +33,7 @@ /obj/item/organ/internal/brain/proc/transfer_identity(mob/living/carbon/H) brainmob = new(src) if(isnull(dna)) // someone didn't set this right... - log_runtime(EXCEPTION("[src] at [loc] did not contain a dna datum at time of removal."), src) + stack_trace("[src] at [loc] did not contain a dna datum at time of removal.") dna = H.dna.Clone() name = "\the [dna.real_name]'s [initial(src.name)]" brainmob.dna = dna.Clone() // Silly baycode, what you do diff --git a/code/modules/mob/living/carbon/brain/robotic_brain.dm b/code/modules/mob/living/carbon/brain/robotic_brain.dm index 72a8ac5911b..5afd5d6c088 100644 --- a/code/modules/mob/living/carbon/brain/robotic_brain.dm +++ b/code/modules/mob/living/carbon/brain/robotic_brain.dm @@ -86,7 +86,7 @@ // This should not ever happen, but let's be safe /obj/item/mmi/robotic_brain/dropbrain(turf/dropspot) - log_runtime(EXCEPTION("[src] at [loc] attempted to drop brain without a contained brain."), src) + CRASH("[src] at [loc] attempted to drop brain without a contained brain.") /obj/item/mmi/robotic_brain/transfer_identity(mob/living/carbon/H) name = "[src] ([H])" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ad3824d474c..3cfe193aae1 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -8,13 +8,8 @@ deathgasp_on_death = TRUE throw_range = 4 -/mob/living/carbon/human/New(loc) - icon = null // This is now handled by overlays -- we just keep an icon for the sake of the map editor. - if(length(args) > 1) - log_runtime(EXCEPTION("human/New called with more than 1 argument (REPORT THIS ENTIRE RUNTIME TO A CODER)")) - . = ..() - /mob/living/carbon/human/Initialize(mapload, datum/species/new_species = /datum/species/human) + icon = null // This is now handled by overlays -- we just keep an icon for the sake of the map editor. create_dna() . = ..() diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index e5e2b4395fd..08dc06167bb 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -112,7 +112,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key) if(client) if(check_mute(client.ckey, MUTE_IC)) to_chat(src, "You cannot speak in IC (Muted).") - return + return FALSE if(sanitize) message = trim_strip_html_properly(message) @@ -120,7 +120,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key) if(stat) if(stat == DEAD) return say_dead(message) - return + return FALSE var/message_mode = parse_message_mode(message, "headset") @@ -150,8 +150,8 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key) if(!LAZYLEN(message_pieces)) - log_runtime(EXCEPTION("Message failed to generate pieces. [message] - [json_encode(message_pieces)]")) - return 0 + . = FALSE + CRASH("Message failed to generate pieces. [message] - [json_encode(message_pieces)]") if(message_mode == "cords") if(iscarbon(src)) @@ -160,7 +160,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key) if(V && V.can_speak_with()) C.say(V.handle_speech(message), sanitize = FALSE, ignore_speech_problems = TRUE, ignore_atmospherics = TRUE) V.speak_with(message) //words come before actions - return 1 + return TRUE var/datum/multilingual_say_piece/first_piece = message_pieces[1] verb = say_quote(message, first_piece.speaking) @@ -184,7 +184,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key) var/list/used_radios = list() if(handle_message_mode(message_mode, message_pieces, verb, used_radios)) - return 1 + return TRUE // Log of what we've said, plain message, no spans or junk // handle_message_mode should have logged this already if it handled it @@ -201,7 +201,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key) //speaking into radios if(used_radios.len) - italics = 1 + italics = TRUE message_range = 1 if(first_piece.speaking) message_range = first_piece.speaking.get_talkinto_msg_range(message) @@ -283,11 +283,11 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key) speech_bubble("[bubble_icon][speech_bubble_test]", src, speech_bubble_recipients) for(var/obj/O in listening_obj) - spawn(0) + spawn(0) // KILL THIS if(O) //It's possible that it could be deleted in the meantime. O.hear_talk(src, message_pieces, verb) - return 1 + return TRUE /obj/effect/speech_bubble var/mob/parent diff --git a/code/modules/mob/living/silicon/ai/latejoin.dm b/code/modules/mob/living/silicon/ai/latejoin.dm index 722b656d56d..7a578066df1 100644 --- a/code/modules/mob/living/silicon/ai/latejoin.dm +++ b/code/modules/mob/living/silicon/ai/latejoin.dm @@ -56,8 +56,7 @@ GLOBAL_LIST_EMPTY(empty_playable_ai_cores) // Before calling this, make sure an empty core exists, or this will no-op /mob/living/silicon/ai/proc/moveToEmptyCore() if(!GLOB.empty_playable_ai_cores.len) - log_runtime(EXCEPTION("moveToEmptyCore called without any available cores"), src) - return + CRASH("moveToEmptyCore called without any available cores") // IsJobAvailable for AI checks that there is an empty core available in this list var/obj/structure/AIcore/deactivated/C = GLOB.empty_playable_ai_cores[1] diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index b8b77d8749f..adc24e80b39 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -286,7 +286,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( else to_chat(src, "Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug.") ghostize() - log_runtime(EXCEPTION("A borg has been destroyed, but its MMI lacked a brainmob, so the mind could not be transferred. Player: [ckey]."), src) + stack_trace("A borg has been destroyed, but its MMI lacked a brainmob, so the mind could not be transferred. Player: [ckey].") mmi = null if(connected_ai) connected_ai.connected_robots -= src diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm index c5197468da8..bf4f7d73205 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm @@ -334,7 +334,7 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list) gib() else if(degenerate) - adjustToxLoss(rand(1,10)) + adjustToxLoss(rand(1, 10)) if(regen_points < regen_points_max) regen_points += regen_points_per_tick if(getBruteLoss() || getFireLoss()) @@ -345,7 +345,7 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list) else if(getFireLoss()) adjustFireLoss(-1) regen_points -= regen_points_per_hp - if(prob(5)) + if(prob(5)) // AA 2022-08-11 - This gives me prob(80) vibes. Should probably be refactored. CheckFaction() /mob/living/simple_animal/hostile/poison/terror_spider/proc/handle_dying() @@ -389,7 +389,7 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list) /mob/living/simple_animal/hostile/poison/terror_spider/proc/CheckFaction() if(faction.len != 2 || (!("terrorspiders" in faction)) || master_commander != null) to_chat(src, "Your connection to the hive mind has been severed!") - log_runtime(EXCEPTION("Terror spider with incorrect faction list at: [atom_loc_line(src)]")) + stack_trace("Terror spider with incorrect faction list at: [atom_loc_line(src)]") gib() /mob/living/simple_animal/hostile/poison/terror_spider/proc/try_open_airlock(obj/machinery/door/airlock/D) diff --git a/code/modules/mob/living/simple_animal/posessed_object.dm b/code/modules/mob/living/simple_animal/posessed_object.dm index 66ffa4be9ac..8000a029d67 100644 --- a/code/modules/mob/living/simple_animal/posessed_object.dm +++ b/code/modules/mob/living/simple_animal/posessed_object.dm @@ -83,13 +83,13 @@ if(!istype(loc, /obj/item)) // Some silly motherfucker spawned us directly via the game panel. message_admins("Posessed object improperly spawned, deleting.") // So silly admins with debug off will see the message too and not spam these things. - log_runtime(EXCEPTION("[src] spawned manually, no object to assign attributes to."), src) + stack_trace("[src] spawned manually, no object to assign attributes to.") qdel(src) var/turf/possessed_loc = get_turf(loc) if(!istype(possessed_loc)) // Will this ever happen? Who goddamn knows. message_admins("Posessed object could not find turf, deleting.") // So silly admins with debug off will see the message too and not spam these things. - log_runtime(EXCEPTION("[src] attempted to find a turf to spawn on, and could not."), src) + stack_trace("[src] attempted to find a turf to spawn on, and could not.") qdel(src) possessed_item = loc diff --git a/code/modules/mob/living/stat_states.dm b/code/modules/mob/living/stat_states.dm index 85602092349..d3e5be870eb 100644 --- a/code/modules/mob/living/stat_states.dm +++ b/code/modules/mob/living/stat_states.dm @@ -2,10 +2,12 @@ /mob/living/proc/KnockOut(updating = TRUE) if(stat == DEAD) - log_runtime(EXCEPTION("KnockOut called on a dead mob."), src) - return 0 + stack_trace("KnockOut called on a dead mob.") + return FALSE + else if(stat == UNCONSCIOUS) - return 0 + return FALSE + create_attack_log("Fallen unconscious at [atom_loc_line(get_turf(src))]") add_attack_logs(src, null, "Fallen unconscious", ATKLOG_ALL) log_game("[key_name(src)] fell unconscious at [atom_loc_line(get_turf(src))]") @@ -13,43 +15,53 @@ ADD_TRAIT(src, TRAIT_FLOORED, STAT_TRAIT) ADD_TRAIT(src, TRAIT_IMMOBILIZED, STAT_TRAIT) ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, STAT_TRAIT) + if(updating) update_sight() update_blind_effects() set_typing_indicator(FALSE) - return 1 + + return TRUE /mob/living/proc/WakeUp(updating = TRUE) if(stat == DEAD) - log_runtime(EXCEPTION("WakeUp called on a dead mob."), src) - return 0 + stack_trace("WakeUp called on a dead mob.") + return FALSE + else if(stat == CONSCIOUS) - return 0 + return FALSE + create_attack_log("Woken up at [atom_loc_line(get_turf(src))]") add_attack_logs(src, null, "Woken up", ATKLOG_ALL) log_game("[key_name(src)] woke up at [atom_loc_line(get_turf(src))]") set_stat(CONSCIOUS) REMOVE_TRAITS_IN(src, STAT_TRAIT) + if(updating) update_sight() update_blind_effects() - return 1 + + return TRUE // death() is used to make a mob die // handles revival through other means than cloning or adminbus (defib, IPC repair) /mob/living/proc/update_revive(updating = TRUE) if(stat != DEAD) - return 0 + return FALSE + create_attack_log("Came back to life at [atom_loc_line(get_turf(src))]") add_attack_logs(src, null, "Came back to life", ATKLOG_ALL) log_game("[key_name(src)] came back to life at [atom_loc_line(get_turf(src))]") set_stat(UNCONSCIOUS) // this is done as `WakeUp` early returns if they are `stat = DEAD` WakeUp() + GLOB.dead_mob_list -= src GLOB.alive_mob_list |= src + if(mind) remove_from_respawnable_list() + timeofdeath = null if(updating) update_blind_effects() @@ -64,7 +76,7 @@ var/obj/effect/proc_holder/spell/spell = S spell.updateButtonIcon() - return 1 + return TRUE /mob/living/proc/check_death_method() return TRUE diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index eec13cb594e..35d65524f9a 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -720,12 +720,13 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM newphrase+="[newletter]";counter-=1 return newphrase +// Why does this exist? /mob/proc/get_preference(toggleflag) if(!client) return FALSE if(!client.prefs) - log_runtime(EXCEPTION("Mob '[src]', ckey '[ckey]' is missing a prefs datum on the client!")) - return FALSE + . = FALSE + CRASH("Mob '[src]', ckey '[ckey]' is missing a prefs datum on the client!") // Cast to 1/0 return !!(client.prefs.toggles & toggleflag) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 5e145576a07..93e646114c0 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -561,14 +561,14 @@ chosen_species = GLOB.all_species[client.prefs.active_character.species] if(!(chosen_species && (is_species_whitelisted(chosen_species) || has_admin_rights()))) // Have to recheck admin due to no usr at roundstart. Latejoins are fine though. - log_runtime(EXCEPTION("[src] had species [client.prefs.active_character.species], though they weren't supposed to. Setting to Human."), src) + stack_trace("[src] had species [client.prefs.active_character.species], though they weren't supposed to. Setting to Human.") client.prefs.active_character.species = "Human" var/datum/language/chosen_language if(client.prefs.active_character.language) chosen_language = GLOB.all_languages[client.prefs.active_character.language] if((chosen_language == null && client.prefs.active_character.language != "None") || (chosen_language && chosen_language.flags & RESTRICTED)) - log_runtime(EXCEPTION("[src] had language [client.prefs.active_character.language], though they weren't supposed to. Setting to None."), src) + stack_trace("[src] had language [client.prefs.active_character.language], though they weren't supposed to. Setting to None.") client.prefs.active_character.language = "None" /mob/new_player/proc/ViewManifest() diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index f56a7e8d3b2..7c457a90dd0 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -298,7 +298,7 @@ if(overdose_results) // to protect against poorly-coded overdose procs update_flags |= overdose_results[REAGENT_OVERDOSE_FLAGS] else - log_runtime(EXCEPTION("Reagent '[R.name]' does not return an overdose info list!")) + stack_trace("Reagent '[R.name]' does not return an overdose info list!") for(var/AB in addiction_list) var/datum/reagent/R = AB diff --git a/code/modules/research/research.dm b/code/modules/research/research.dm index 0ff250714c0..68029031209 100644 --- a/code/modules/research/research.dm +++ b/code/modules/research/research.dm @@ -123,7 +123,7 @@ research holder datum. for(var/datum/design/PD in possible_designs) if(DesignHasReqs(PD)) if(!AddDesign2Known(PD)) - log_runtime(EXCEPTION("Game attempted to add a null design to list of known designs! Design: [PD] with ID: [PD.id]"), src) + stack_trace("Game attempted to add a null design to list of known designs! Design: [PD] with ID: [PD.id]") for(var/v in known_tech) var/datum/tech/T = known_tech[v] T.level = clamp(T.level, 0, 20) diff --git a/code/modules/surgery/organs/organ.dm b/code/modules/surgery/organs/organ.dm index ac79d34ac82..7cd174d2197 100644 --- a/code/modules/surgery/organs/organ.dm +++ b/code/modules/surgery/organs/organ.dm @@ -51,7 +51,7 @@ if(holder.dna) dna = holder.dna.Clone() else - log_runtime(EXCEPTION("[holder] spawned without a proper DNA."), holder) + stack_trace("[holder] spawned without a proper DNA.") var/mob/living/carbon/human/H = holder if(istype(H)) if(dna) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index e1f7e53e094..76dfcf16f5b 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -33,7 +33,7 @@ var/mob/living/carbon/human/H = M parent = H.get_organ(check_zone(parent_organ)) if(!istype(parent)) - log_runtime(EXCEPTION("[src] attempted to insert into a [parent_organ], but [parent_organ] wasn't an organ! [atom_loc_line(M)]"), src) + stack_trace("[src] attempted to insert into a [parent_organ], but [parent_organ] wasn't an organ! [atom_loc_line(M)]") else parent.internal_organs |= src loc = null @@ -49,7 +49,7 @@ // However, you MUST set the object's positiion yourself when you call this! /obj/item/organ/internal/remove(mob/living/carbon/M, special = 0) if(!owner) - log_runtime(EXCEPTION("\'remove\' called on [src] without an owner! Mob: [M], [atom_loc_line(M)]"), src) + stack_trace("\'remove\' called on [src] without an owner! Mob: [M], [atom_loc_line(M)]") owner = null if(M) M.internal_organs -= src @@ -63,7 +63,7 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/external/parent = H.get_organ(check_zone(parent_organ)) if(!istype(parent)) - log_runtime(EXCEPTION("[src] attempted to remove from a [parent_organ], but [parent_organ] didn't exist! [atom_loc_line(M)]"), src) + stack_trace("[src] attempted to remove from a [parent_organ], but [parent_organ] didn't exist! [atom_loc_line(M)]") else parent.internal_organs -= src H.update_int_organs() diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 6dd902b82f0..2e62b5d365c 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -236,8 +236,8 @@ user.visible_message("[user] begins to close and secure the hatch on [target]'s [affected.name] with \the [tool]." , \ "You begin to close and secure the hatch on [target]'s [affected.name] with \the [tool].") else - log_runtime(EXCEPTION("Invalid tool: '[implement_type]'"), src) - return -1 + . = -1 + CRASH("Invalid tool: '[implement_type]'") ..() /datum/surgery_step/robotics/external/repair/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) diff --git a/code/modules/tgui/modules/appearance_changer.dm b/code/modules/tgui/modules/appearance_changer.dm index 729b728c350..56ada27b12c 100644 --- a/code/modules/tgui/modules/appearance_changer.dm +++ b/code/modules/tgui/modules/appearance_changer.dm @@ -317,7 +317,7 @@ /datum/ui_module/appearance_changer/proc/can_change_head_accessory() if(!head_organ) - log_runtime(EXCEPTION("Missing head!"), owner) + stack_trace("[owner] Missing head!") return FALSE return owner && (flags & APPEARANCE_HEAD_ACCESSORY) && (head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY) diff --git a/paradise.dme b/paradise.dme index 574f609329c..f8eb488c522 100644 --- a/paradise.dme +++ b/paradise.dme @@ -128,6 +128,7 @@ #include "code\__HELPERS\qdel.dm" #include "code\__HELPERS\radiation.dm" #include "code\__HELPERS\sanitize_values.dm" +#include "code\__HELPERS\stacktrace.dm" #include "code\__HELPERS\string_assoc_lists.dm" #include "code\__HELPERS\text.dm" #include "code\__HELPERS\time.dm"