diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 7fdce20895d..a2cf5aab48f 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -853,6 +853,17 @@ GLOBAL_LIST_EMPTY(the_station_areas) /datum/controller/subsystem/mapping/proc/lazy_load_template(template_key, force = FALSE) RETURN_TYPE(/datum/turf_reservation) + var/static/lazy_loading = FALSE + UNTIL(!lazy_loading) + + lazy_loading = TRUE + . = _lazy_load_template(template_key, force) + lazy_loading = FALSE + return . + +/datum/controller/subsystem/mapping/proc/_lazy_load_template(template_key, force = FALSE) + PRIVATE_PROC(TRUE) + if(LAZYACCESS(loaded_lazy_templates, template_key) && !force) var/datum/lazy_template/template = GLOB.lazy_templates[template_key] return template.reservations[1] @@ -861,7 +872,6 @@ GLOBAL_LIST_EMPTY(the_station_areas) var/datum/lazy_template/target = GLOB.lazy_templates[template_key] if(!target) CRASH("Attempted to lazy load a template key that does not exist: '[template_key]'") - return target.lazy_load() /proc/generate_lighting_appearance_by_z(z_level) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index d8340d09a09..519a7ea53d7 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -502,6 +502,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) rule.acceptable(roundstart_pop_ready, threat_level) // Assigns some vars in the modes, running it here for consistency rule.candidates = candidates.Copy() rule.trim_candidates() + rule.load_templates() if (rule.ready(roundstart_pop_ready, TRUE)) var/cost = rule.cost var/scaled_times = 0 @@ -522,6 +523,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) if (rule.acceptable(roundstart_pop_ready, threat_level) && round_start_budget >= rule.cost) // If we got the population and threat required rule.candidates = candidates.Copy() rule.trim_candidates() + rule.load_templates() if (rule.ready(roundstart_pop_ready) && rule.candidates.len > 0) drafted_rules[rule] = rule.weight @@ -629,6 +631,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) var/population = GLOB.alive_player_list.len if((new_rule.acceptable(population, threat_level) && (ignore_cost || new_rule.cost <= mid_round_budget)) || forced) new_rule.trim_candidates() + new_rule.load_templates() if (new_rule.ready(forced)) if (!ignore_cost) spend_midround_budget(new_rule.cost, threat_log, "[worldtime2text()]: Forced rule [new_rule.name]") @@ -681,6 +684,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) if (forced_latejoin_rule) forced_latejoin_rule.candidates = list(newPlayer) forced_latejoin_rule.trim_candidates() + forced_latejoin_rule.load_templates() log_dynamic("Forcing ruleset [forced_latejoin_rule]") if (forced_latejoin_rule.ready(TRUE)) if (!forced_latejoin_rule.repeatable) @@ -703,6 +707,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) rule.candidates = list(newPlayer) rule.trim_candidates() + rule.load_templates() if (rule.ready()) drafted_rules[rule] = rule.get_weight() diff --git a/code/game/gamemodes/dynamic/dynamic_midround_rolling.dm b/code/game/gamemodes/dynamic/dynamic_midround_rolling.dm index bdbd301607a..5079035834b 100644 --- a/code/game/gamemodes/dynamic/dynamic_midround_rolling.dm +++ b/code/game/gamemodes/dynamic/dynamic_midround_rolling.dm @@ -62,6 +62,7 @@ continue ruleset.trim_candidates() + ruleset.load_templates() if (!ruleset.ready()) log_dynamic("FAIL: [ruleset] is not ready()") continue diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets.dm b/code/game/gamemodes/dynamic/dynamic_rulesets.dm index dc70c44977b..79d86637a31 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets.dm @@ -85,6 +85,9 @@ /// If written as a linear equation, will be in the form of `list("denominator" = denominator, "offset" = offset). var/antag_cap = 0 + /// A list, or null, of templates that the ruleset depends on to function correctly + var/list/ruleset_lazy_templates + /datum/dynamic_ruleset/New() // Rulesets can be instantiated more than once, such as when an admin clicks // "Execute Midround Ruleset". Thus, it would be wrong to perform any @@ -173,6 +176,11 @@ /datum/dynamic_ruleset/proc/ready(forced = 0) return check_candidates() +/// This should always be called before ready is, to ensure that the ruleset can locate map/template based landmarks as needed +/datum/dynamic_ruleset/proc/load_templates() + for(var/template in ruleset_lazy_templates) + SSmapping.lazy_load_template(template) + /// Runs from gamemode process() if ruleset fails to start, like delayed rulesets not getting valid candidates. /// This one only handles refunding the threat, override in ruleset to clean up the rest. /datum/dynamic_ruleset/proc/clean_up() diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 686bf1cd08a..a2933427ede 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -336,12 +336,12 @@ cost = 10 requirements = REQUIREMENTS_VERY_HIGH_THREAT_NEEDED flags = HIGH_IMPACT_RULESET + ruleset_lazy_templates = list(LAZY_TEMPLATE_KEY_WIZARDDEN) /datum/dynamic_ruleset/midround/from_ghosts/wizard/ready(forced = FALSE) - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN) - if (!check_candidates()) + if(!check_candidates()) return FALSE - if(GLOB.wizardstart.len == 0) + if(!length(GLOB.wizardstart)) log_admin("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.") message_admins("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.") return FALSE diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 1072a177c34..92748f1d6a4 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -273,10 +273,12 @@ weight = 2 cost = 20 requirements = list(90,90,90,80,60,40,30,20,10,10) + ruleset_lazy_templates = list(LAZY_TEMPLATE_KEY_WIZARDDEN) -/datum/dynamic_ruleset/roundstart/wizard/acceptable(population=0, threat=0) - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN) - if(GLOB.wizardstart.len == 0) +/datum/dynamic_ruleset/roundstart/wizard/ready(forced = FALSE) + if(!check_candidates()) + return FALSE + if(!length(GLOB.wizardstart)) log_admin("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.") message_admins("Cannot accept Wizard ruleset. Couldn't find any wizard spawn points.") return FALSE @@ -415,6 +417,7 @@ requirements = list(90,90,90,80,60,40,30,20,10,10) flags = HIGH_IMPACT_RULESET antag_cap = list("denominator" = 18, "offset" = 1) + ruleset_lazy_templates = list(LAZY_TEMPLATE_KEY_NUKIEBASE) var/required_role = ROLE_NUCLEAR_OPERATIVE var/datum/team/nuclear/nuke_team diff --git a/code/game/gamemodes/dynamic/dynamic_unfavorable_situation.dm b/code/game/gamemodes/dynamic/dynamic_unfavorable_situation.dm index 5e4105753bf..492ae7a3819 100644 --- a/code/game/gamemodes/dynamic/dynamic_unfavorable_situation.dm +++ b/code/game/gamemodes/dynamic/dynamic_unfavorable_situation.dm @@ -38,6 +38,7 @@ ruleset.trim_candidates() + ruleset.load_templates() if (!ruleset.ready()) continue diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm index 1a7b707ea75..0d2d0415061 100644 --- a/code/modules/antagonists/abductor/abductor.dm +++ b/code/modules/antagonists/abductor/abductor.dm @@ -17,6 +17,11 @@ /// Type path for the associated job datum. var/role_job = /datum/job/abductor_agent +/datum/antagonist/abductor/New() + // lets get the loading started now, but don't block waiting for it + INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_ABDUCTOR_SHIPS) + return ..() + /datum/antagonist/abductor/get_preview_icon() var/mob/living/carbon/human/dummy/consistent/scientist = new var/mob/living/carbon/human/dummy/consistent/agent = new @@ -99,6 +104,8 @@ H.real_name = "[team.name] [sub_role]" H.equipOutfit(outfit) + // We require that the template be loaded here, so call it in a blocking manner, if its already done loading, this won't block + SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_ABDUCTOR_SHIPS) //Teleport to ship for(var/obj/effect/landmark/abductor/LM in GLOB.landmarks_list) if(istype(LM, landmark_type) && LM.team_number == team.team_number) @@ -116,7 +123,6 @@ . = ..() /datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin) - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_ABDUCTOR_SHIPS) var/list/current_teams = list() for(var/datum/team/abductor_team/T in GLOB.antagonist_teams) current_teams[T.name] = T diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index eb48839047f..69fc8bc67e2 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -25,6 +25,11 @@ /// The amount of limited discounts that the team get var/discount_limited_amount = 10 +/datum/antagonist/nukeop/New() + if(send_to_spawnpoint) // lets get the loading started now, but don't block waiting for it + INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_NUKIEBASE) + return ..() + /datum/antagonist/nukeop/proc/equip_op() if(!ishuman(owner.current)) return @@ -118,6 +123,9 @@ objectives |= nuke_team.objectives /datum/antagonist/nukeop/proc/move_to_spawnpoint() + // Ensure that the nukiebase is loaded, and wait for it if required + SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE) + var/team_number = 1 if(nuke_team) team_number = nuke_team.members.Find(owner) @@ -127,7 +135,6 @@ owner.current.forceMove(pick(GLOB.nukeop_leader_start)) /datum/antagonist/nukeop/create_team(datum/team/nuclear/new_team) - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE) if(!new_team) if(!always_new_team) for(var/datum/antagonist/nukeop/N in GLOB.antagonists) diff --git a/code/modules/antagonists/nukeop/outfits.dm b/code/modules/antagonists/nukeop/outfits.dm index 693624bc82b..cb08771860f 100644 --- a/code/modules/antagonists/nukeop/outfits.dm +++ b/code/modules/antagonists/nukeop/outfits.dm @@ -28,7 +28,9 @@ /datum/outfit/syndicate/post_equip(mob/living/carbon/human/nukie, visualsOnly = FALSE) if(visualsOnly) return - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE) + + // We don't require the nukiebase be loaded to function, but lets go ahead and kick off loading just in case + INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_NUKIEBASE) var/obj/item/radio/radio = nukie.ears radio.set_frequency(FREQ_SYNDICATE) radio.freqlock = RADIO_FREQENCY_LOCKED diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index ec7f3aba08c..66a1d77ae42 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -21,6 +21,11 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key) var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */ show_to_ghosts = TRUE +/datum/antagonist/wizard/New() + if(move_to_lair) // kick off loading of your lair, if you want to be moved to it + INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_WIZARDDEN) + return ..() + /datum/antagonist/wizard_minion name = "Wizard Minion" antagpanel_category = "Wizard" @@ -92,7 +97,9 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key) wiz_team.master_wizard = src /datum/antagonist/wizard/proc/send_to_lair() + // And now we ensure that its loaded SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN) + if(!owner) CRASH("Antag datum with no owner.") if(!owner.current) diff --git a/code/modules/jobs/job_types/antagonists/nuclear_operative.dm b/code/modules/jobs/job_types/antagonists/nuclear_operative.dm index f727e37f6c7..6fbfdd50994 100644 --- a/code/modules/jobs/job_types/antagonists/nuclear_operative.dm +++ b/code/modules/jobs/job_types/antagonists/nuclear_operative.dm @@ -1,11 +1,8 @@ /datum/job/nuclear_operative title = ROLE_NUCLEAR_OPERATIVE - /datum/job/nuclear_operative/get_roundstart_spawn_point() - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE) return pick(GLOB.nukeop_start) /datum/job/nuclear_operative/get_latejoin_spawn_point() - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE) return pick(GLOB.nukeop_start) diff --git a/code/modules/jobs/job_types/antagonists/space_wizard.dm b/code/modules/jobs/job_types/antagonists/space_wizard.dm index e317cfb3276..fc0c2cdbf15 100644 --- a/code/modules/jobs/job_types/antagonists/space_wizard.dm +++ b/code/modules/jobs/job_types/antagonists/space_wizard.dm @@ -3,9 +3,7 @@ faction = ROLE_WIZARD /datum/job/space_wizard/get_roundstart_spawn_point() - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN) return pick(GLOB.wizardstart) /datum/job/space_wizard/get_latejoin_spawn_point() - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_WIZARDDEN) return pick(GLOB.wizardstart) diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 9d0529cb10f..0be34a3b8ac 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -181,8 +181,9 @@ /obj/machinery/computer/emergency_shuttle/proc/increase_hijack_stage() var/obj/docking_port/mobile/emergency/shuttle = SSshuttle.emergency - // Begin loading this early, otherwise we get an awkward 30 second delay on the - SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE) + // Begin loading this early, prevents a delay when the shuttle goes to land + INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, lazy_load_template), LAZY_TEMPLATE_KEY_NUKIEBASE) + shuttle.hijack_status++ if(hijack_announce) announce_hijack_stage() @@ -547,6 +548,8 @@ // unless the shuttle is "hijacked" var/destination_dock = "emergency_away" if(is_hijacked() || elimination_hijack()) + // just double check + SSmapping.lazy_load_template(LAZY_TEMPLATE_KEY_NUKIEBASE) destination_dock = "emergency_syndicate" minor_announce("Corruption detected in \ shuttle navigation protocols. Please contact your \