diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 8464e373d5..d61adf4337 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -1,9 +1,12 @@ //wrapper macros for easier grepping #define DIRECT_OUTPUT(A, B) A << B +#define DIRECT_INPUT(A, B) A >> B #define SEND_IMAGE(target, image) DIRECT_OUTPUT(target, image) #define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound) #define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text) #define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text) +#define READ_FILE(file, text) DIRECT_INPUT(file, text) + #ifdef EXTOOLS_LOGGING // proc hooked, so we can just put in standard TRUE and FALSE #define WRITE_LOG(log, text) extools_log_write(log,text,TRUE) @@ -13,6 +16,7 @@ #define WRITE_LOG(log, text) rustg_log_write(log, text, "true") #define WRITE_LOG_NO_FORMAT(log, text) rustg_log_write(log, text, "false") #endif + //print a warning message to world.log #define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [UNLINT(src)] usr: [usr].") /proc/warning(msg) @@ -38,6 +42,12 @@ SEND_TEXT(world.log, text) #endif +#ifdef REFERENCE_TRACKING_LOG +#define log_reftracker(msg) log_world("## REF SEARCH [msg]") +#else +#define log_reftracker(msg) +#endif + /* Items with ADMINPRIVATE prefixed are stripped from public logs. */ /proc/log_admin(text) diff --git a/code/modules/admin/view_variables/reference_tracking.dm b/code/modules/admin/view_variables/reference_tracking.dm index 279654eec1..714b54cd45 100644 --- a/code/modules/admin/view_variables/reference_tracking.dm +++ b/code/modules/admin/view_variables/reference_tracking.dm @@ -1,4 +1,4 @@ -#ifdef REFERENCE_TRACKING +#ifdef EXTOOLS_REFERENCE_TRACKING GLOBAL_LIST_EMPTY(deletion_failures) @@ -102,29 +102,21 @@ GLOBAL_LIST_EMPTY(deletion_failures) #endif -#ifdef LEGACY_REFERENCE_TRACKING +#ifdef REFERENCE_TRACKING -/datum/verb/legacy_find_refs() - set category = "Debug" - set name = "Find References" - set src in world - - find_references_legacy(FALSE) - - -/datum/proc/find_references_legacy(skip_alert) +/datum/proc/find_references(skip_alert) running_find_references = type if(usr?.client) if(usr.client.running_find_references) - testing("CANCELLED search for references to a [usr.client.running_find_references].") + log_reftracker("CANCELLED search for references to a [usr.client.running_find_references].") usr.client.running_find_references = null running_find_references = null //restart the garbage collector SSgarbage.can_fire = TRUE - SSgarbage.next_fire = world.time + world.tick_lag + SSgarbage.update_nextfire(reset_time = TRUE) return - if(!skip_alert && alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") != "Yes") + if(!skip_alert && tgui_alert(usr,"Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", list("Yes", "No")) != "Yes") running_find_references = null return @@ -134,92 +126,122 @@ GLOBAL_LIST_EMPTY(deletion_failures) if(usr?.client) usr.client.running_find_references = type - testing("Beginning search for references to a [type].") - last_find_references = world.time + log_reftracker("Beginning search for references to a [type].") + + var/starting_time = world.time + + //Time to search the whole game for our ref + DoSearchVar(GLOB, "GLOB") //globals + log_reftracker("Finished searching globals") - DoSearchVar(GLOB) //globals for(var/datum/thing in world) //atoms (don't beleive its lies) - DoSearchVar(thing, "World -> [thing]") + DoSearchVar(thing, "World -> [thing.type]", search_time = starting_time) + log_reftracker("Finished searching atoms") for(var/datum/thing) //datums - DoSearchVar(thing, "World -> [thing]") + DoSearchVar(thing, "Datums -> [thing.type]", search_time = starting_time) + log_reftracker("Finished searching datums") + //Warning, attempting to search clients like this will cause crashes if done on live. Watch yourself for(var/client/thing) //clients - DoSearchVar(thing, "World -> [thing]") + DoSearchVar(thing, "Clients -> [thing.type]", search_time = starting_time) + log_reftracker("Finished searching clients") + + log_reftracker("Completed search for references to a [type].") - testing("Completed search for references to a [type].") if(usr?.client) usr.client.running_find_references = null running_find_references = null //restart the garbage collector SSgarbage.can_fire = TRUE - SSgarbage.next_fire = world.time + world.tick_lag + SSgarbage.update_nextfire(reset_time = TRUE) +/datum/proc/DoSearchVar(potential_container, container_name, recursive_limit = 64, search_time = world.time) + #ifdef REFERENCE_TRACKING_DEBUG + if(!found_refs && SSgarbage.should_save_refs) + found_refs = list() + #endif -/datum/verb/qdel_then_find_references() - set category = "Debug" - set name = "qdel() then Find References" - set src in world - - qdel(src, TRUE) //force a qdel - if(!running_find_references) - find_references_legacy(TRUE) - - -/datum/verb/qdel_then_if_fail_find_references() - set category = "Debug" - set name = "qdel() then Find References if GC failure" - set src in world - - qdel_and_find_ref_if_fail(src, TRUE) - - -/datum/proc/DoSearchVar(potential_container, container_name, recursive_limit = 64) if(usr?.client && !usr.client.running_find_references) return if(!recursive_limit) + log_reftracker("Recursion limit reached. [container_name]") return - if(istype(potential_container, /datum)) - var/datum/datum_container = potential_container - if(datum_container.last_find_references == last_find_references) - return - - datum_container.last_find_references = last_find_references - var/list/vars_list = datum_container.vars - - for(var/varname in vars_list) - if (varname == "vars") - continue - var/variable = vars_list[varname] - - if(variable == src) - testing("Found [type] \ref[src] in [datum_container.type]'s [varname] var. [container_name]") - - else if(islist(variable)) - DoSearchVar(variable, "[container_name] -> list", recursive_limit - 1) - - else if(islist(potential_container)) - var/normal = IS_NORMAL_LIST(potential_container) - for(var/element_in_list in potential_container) - if(element_in_list == src) - testing("Found [type] \ref[src] in list [container_name].") - - else if(element_in_list && !isnum(element_in_list) && normal && potential_container[element_in_list] == src) - testing("Found [type] \ref[src] in list [container_name]\[[element_in_list]\]") - - else if(islist(element_in_list)) - DoSearchVar(element_in_list, "[container_name] -> list", recursive_limit - 1) - + //Check each time you go down a layer. This makes it a bit slow, but it won't effect the rest of the game at all #ifndef FIND_REF_NO_CHECK_TICK CHECK_TICK #endif + if(istype(potential_container, /datum)) + var/datum/datum_container = potential_container + if(datum_container.last_find_references == search_time) + return + + datum_container.last_find_references = search_time + var/list/vars_list = datum_container.vars + + for(var/varname in vars_list) + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif + if (varname == "vars" || varname == "vis_locs") //Fun fact, vis_locs don't count for references + continue + var/variable = vars_list[varname] + + if(variable == src) + #ifdef REFERENCE_TRACKING_DEBUG + if(SSgarbage.should_save_refs) + found_refs[varname] = TRUE + #endif + log_reftracker("Found [type] \ref[src] in [datum_container.type]'s \ref[datum_container] [varname] var. [container_name]") + continue + + if(islist(variable)) + DoSearchVar(variable, "[container_name] \ref[datum_container] -> [varname] (list)", recursive_limit - 1, search_time) + + else if(islist(potential_container)) + var/normal = IS_NORMAL_LIST(potential_container) + var/list/potential_cache = potential_container + for(var/element_in_list in potential_cache) + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif + //Check normal entrys + if(element_in_list == src) + #ifdef REFERENCE_TRACKING_DEBUG + if(SSgarbage.should_save_refs) + found_refs[potential_cache] = TRUE + #endif + log_reftracker("Found [type] \ref[src] in list [container_name].") + continue + + var/assoc_val = null + if(!isnum(element_in_list) && normal) + assoc_val = potential_cache[element_in_list] + //Check assoc entrys + if(assoc_val == src) + #ifdef REFERENCE_TRACKING_DEBUG + if(SSgarbage.should_save_refs) + found_refs[potential_cache] = TRUE + #endif + log_reftracker("Found [type] \ref[src] in list [container_name]\[[element_in_list]\]") + continue + //We need to run both of these checks, since our object could be hiding in either of them + //Check normal sublists + if(islist(element_in_list)) + DoSearchVar(element_in_list, "[container_name] -> [element_in_list] (list)", recursive_limit - 1, search_time) + //Check assoc sublists + if(islist(assoc_val)) + DoSearchVar(potential_container[element_in_list], "[container_name]\[[element_in_list]\] -> [assoc_val] (list)", recursive_limit - 1, search_time) /proc/qdel_and_find_ref_if_fail(datum/thing_to_del, force = FALSE) - SSgarbage.reference_find_on_fail[REF(thing_to_del)] = TRUE - qdel(thing_to_del, force) + thing_to_del.qdel_and_find_ref_if_fail(force) + +/datum/proc/qdel_and_find_ref_if_fail(force = FALSE) + SSgarbage.reference_find_on_fail["\ref[src]"] = TRUE + qdel(src, force) #endif diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index 6a49addc13..0af024985e 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -3,21 +3,21 @@ /datum/asset/simple/tgui_common keep_local_name = TRUE assets = list( - "tgui-common.bundle.js" = 'tgui/public/tgui-common.bundle.js', + "tgui-common.bundle.js" = file("tgui/public/tgui-common.bundle.js"), ) /datum/asset/simple/tgui keep_local_name = TRUE assets = list( - "tgui.bundle.js" = 'tgui/public/tgui.bundle.js', - "tgui.bundle.css" = 'tgui/public/tgui.bundle.css', + "tgui.bundle.js" = file("tgui/public/tgui.bundle.js"), + "tgui.bundle.css" = file("tgui/public/tgui.bundle.css"), ) /datum/asset/simple/tgui_panel keep_local_name = TRUE assets = list( - "tgui-panel.bundle.js" = 'tgui/public/tgui-panel.bundle.js', - "tgui-panel.bundle.css" = 'tgui/public/tgui-panel.bundle.css', + "tgui-panel.bundle.js" = file("tgui/public/tgui-panel.bundle.js"), + "tgui-panel.bundle.css" = file("tgui/public/tgui-panel.bundle.css"), ) /datum/asset/simple/headers @@ -168,10 +168,12 @@ /datum/asset/simple/namespaced/tgfont assets = list( - "tgfont.eot" = 'tgui/packages/tgfont/dist/tgfont.eot', - "tgfont.woff2" = 'tgui/packages/tgfont/dist/tgfont.woff2', + "tgfont.eot" = file("tgui/packages/tgfont/dist/tgfont.eot"), + "tgfont.woff2" = file("tgui/packages/tgfont/dist/tgfont.woff2"), + ) + parents = list( + "tgfont.css" = file("tgui/packages/tgfont/dist/tgfont.css"), ) - parents = list("tgfont.css" = 'tgui/packages/tgfont/dist/tgfont.css') /datum/asset/spritesheet/chat name = "chat" diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 7f7c3a1fcc..706a7a3910 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -81,7 +81,7 @@ // #include "reagent_mod_procs.dm" #include "reagent_recipe_collisions.dm" #include "resist.dm" -#include "say.dm" +// #include "say.dm" // #include "security_officer_distribution.dm" // #include "serving_tray.dm" // #include "siunit.dm" diff --git a/code/modules/unit_tests/say.dm b/code/modules/unit_tests/say.dm deleted file mode 100644 index a7df5ad624..0000000000 --- a/code/modules/unit_tests/say.dm +++ /dev/null @@ -1,23 +0,0 @@ -/// Test to verify message mods are parsed correctly -/datum/unit_test/get_message_mods - var/mob/host_mob - -/datum/unit_test/get_message_mods/Run() - host_mob = allocate(/mob/living/carbon/human) - - test("Hello", "Hello", list()) - test(";HELP", "HELP", list(MODE_HEADSET = TRUE)) - test(";%Never gonna give you up", "Never gonna give you up", list(MODE_HEADSET = TRUE, MODE_SING = TRUE)) - test(".s Gun plz", "Gun plz", list(RADIO_KEY = RADIO_KEY_SECURITY, RADIO_EXTENSION = RADIO_CHANNEL_SECURITY)) - test("...What", "...What", list()) - -/datum/unit_test/get_message_mods/proc/test(message, expected_message, list/expected_mods) - var/list/mods = list() - TEST_ASSERT_EQUAL(host_mob.get_message_mods(message, mods), expected_message, "Chopped message was not what we expected. Message: [message]") - - for (var/mod_key in mods) - TEST_ASSERT_EQUAL(mods[mod_key], expected_mods[mod_key], "The value for [mod_key] was not what we expected. Message: [message]") - expected_mods -= mod_key - - if (expected_mods.len) - Fail("Some message mods were expected, but were not returned by get_message_mods: [json_encode(expected_mods)]. Message: [message]") diff --git a/code/modules/unit_tests/teleporters.dm b/code/modules/unit_tests/teleporters.dm index 0fc9bdb082..2cb047304f 100644 --- a/code/modules/unit_tests/teleporters.dm +++ b/code/modules/unit_tests/teleporters.dm @@ -1,8 +1,8 @@ /datum/unit_test/auto_teleporter_linking/Run() // Put down the teleporter machinery var/obj/machinery/teleport/hub/hub = allocate(/obj/machinery/teleport/hub) - var/obj/machinery/computer/teleporter/computer = allocate(/obj/machinery/computer/teleporter, locate(run_loc_bottom_left.x + 2, run_loc_bottom_left.y, run_loc_bottom_left.z)) - var/obj/machinery/teleport/station/station = allocate(/obj/machinery/teleport/station, locate(run_loc_bottom_left.x + 1, run_loc_bottom_left.y, run_loc_bottom_left.z)) + var/obj/machinery/teleport/station/station = allocate(/obj/machinery/teleport/station, locate(run_loc_floor_bottom_left.x + 1, run_loc_floor_bottom_left.y, run_loc_floor_bottom_left.z)) + var/obj/machinery/computer/teleporter/computer = allocate(/obj/machinery/computer/teleporter, locate(run_loc_floor_bottom_left.x + 2, run_loc_floor_bottom_left.y, run_loc_floor_bottom_left.z)) TEST_ASSERT_EQUAL(hub.power_station, station, "Hub didn't link to the station") TEST_ASSERT_EQUAL(station.teleporter_console, computer, "Station didn't link to the teleporter console")