diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index adb9d60ab1f..8dae4a208a8 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -32,6 +32,8 @@ Pipelines + Other Objects -> Pipe network var/global/datum/pipe_icon_manager/icon_manager /obj/machinery/atmospherics/New() + ..() + if(!icon_manager) icon_manager = new() @@ -42,8 +44,6 @@ Pipelines + Other Objects -> Pipe network if(!pipe_color_check(pipe_color)) pipe_color = null - ..() - /obj/machinery/atmospherics/initialize() ..() diff --git a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm index 6fe6c646cf5..0b7092c1027 100644 --- a/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary_devices/vent_pump.dm @@ -60,13 +60,13 @@ icon_state = "map_vent_in" /obj/machinery/atmospherics/unary/vent_pump/New() + ..() icon = null initial_loc = get_area(loc) area_uid = initial_loc.uid if (!id_tag) assign_uid() id_tag = num2text(uid) - ..() /obj/machinery/atmospherics/unary/vent_pump/high_volume name = "large air vent" diff --git a/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm index d0b0c9eb693..30c603fb47d 100644 --- a/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary_devices/vent_scrubber.dm @@ -41,13 +41,13 @@ connect_types = list(1,3) //connects to regular and scrubber pipes /obj/machinery/atmospherics/unary/vent_scrubber/New() + ..() icon = null initial_loc = get_area(loc) area_uid = initial_loc.uid if (!id_tag) assign_uid() id_tag = num2text(uid) - ..() /obj/machinery/atmospherics/unary/vent_scrubber/Destroy() if(initial_loc && frequency == 1439) diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm index 858177a72ac..156d6ffa851 100644 --- a/code/ATMOSPHERICS/datum_pipeline.dm +++ b/code/ATMOSPHERICS/datum_pipeline.dm @@ -33,7 +33,6 @@ var/global/list/deferred_pipenet_rebuilds = list() var/pipenetwarnings = 10 -var/pipenets_made = 0 /datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/base) var/volume = 0 if(istype(base, /obj/machinery/atmospherics/pipe)) @@ -48,7 +47,6 @@ var/pipenets_made = 0 addMachineryMember(base) if(!air) air = new -// log_startup_progress("Making pipenet [pipenets_made++]") var/list/possible_expansions = list(base) while(possible_expansions.len>0) for(var/obj/machinery/atmospherics/borderline in possible_expansions) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 3ccd15c997b..4a422cf6d1b 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -20,10 +20,6 @@ var/auto_init = 1 -// This is used in the map loader to defer initialization once all entities -// are placed, so that pipes and window spawners correctly function -// when plunked down mid-game -var/list/dirty_z_levels = list() /atom/movable/New() . = ..() areaMaster = get_area_master(src) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 65332a1df72..4afe0bf776b 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -47,7 +47,7 @@ Class Variables: Currently unused. Class Procs: - New() 'game/machinery/machine.dm' + initialize() 'game/machinery/machine.dm' Destroy() 'game/machinery/machine.dm' diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index c531162e22b..a079df0a4b3 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -193,15 +193,15 @@ return W // I'm including `ignore_air` because BYOND lacks positional-only arguments -/turf/proc/AfterChange(ignore_air, but_its_not_the_saaaaaame = FALSE) //called after a turf has been replaced in ChangeTurf() +/turf/proc/AfterChange(ignore_air, keep_cabling = FALSE) //called after a turf has been replaced in ChangeTurf() levelupdate() CalculateAdjacentTurfs() - if(!but_its_not_the_saaaaaame && !can_have_cabling()) + if(!keep_cabling && !can_have_cabling()) for(var/obj/structure/cable/C in contents) qdel(C) -/turf/simulated/AfterChange(ignore_air, but_its_not_the_saaaaaame = FALSE) +/turf/simulated/AfterChange(ignore_air, keep_cabling = FALSE) ..() RemoveLattice() if(!ignore_air) diff --git a/code/modules/awaymissions/map_rng.dm b/code/modules/awaymissions/map_rng.dm index 469dffaca54..0f8ca13b7a6 100644 --- a/code/modules/awaymissions/map_rng.dm +++ b/code/modules/awaymissions/map_rng.dm @@ -9,30 +9,41 @@ var/template_name = null var/datum/map_template/template = null var/centered = 1 + var/loaded = 0 + var/delay_init = 0 -/obj/effect/landmark/map_loader/New(loc, tname) +/obj/effect/landmark/map_loader/New(turf/loc, tname) ..() + if(tname) template_name = tname if(template_name) template = map_templates[template_name] + +/obj/effect/landmark/map_loader/initialize() + ..() if(template) load(template) /obj/effect/landmark/map_loader/proc/load(datum/map_template/t) - spawn(1) - if(!t) - return - t.load(get_turf(src), centered = centered) - t.loaded++ - qdel(src) + if(!t) + return + if(loaded) + return + loaded = 1 + var/turf/pos = get_turf(src) + // Hop to nullspace so we don't get re-initialized by the map we're loading + loc = null + t.load(pos, centered = centered, delay_init = delay_init) + t.loaded++ + qdel(src) /obj/effect/landmark/map_loader/random var/template_list = "" -/obj/effect/landmark/map_loader/random/New() +/obj/effect/landmark/map_loader/random/initialize() ..() if(template_list) template_name = safepick(splittext(template_list, ";")) template = map_templates[template_name] - load(template) \ No newline at end of file + load(template) diff --git a/code/modules/awaymissions/maploader/reader.dm b/code/modules/awaymissions/maploader/reader.dm index e12282b6580..2ef9d79d994 100644 --- a/code/modules/awaymissions/maploader/reader.dm +++ b/code/modules/awaymissions/maploader/reader.dm @@ -8,6 +8,9 @@ var/global/use_preloader = FALSE var/global/dmm_suite/preloader/_preloader = new /dmm_suite + // These regexes are global - meaning that starting the maploader again mid-load will + // reset progress - which means we need to track our index per-map, or we'll + // eternally recurse // /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g var/static/regex/dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g") // /^[\s\n]+"?|"?[\s\n]+$|^"|"$/g @@ -35,7 +38,9 @@ var/global/dmm_suite/preloader/_preloader = new */ /dmm_suite/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num, delay_init as num) var/tfile = dmm_file//the map file we're creating + var/fname = "Lambda" if(isfile(tfile)) + fname = "[tfile]" tfile = file2text(tfile) if(!x_offset) @@ -49,14 +54,19 @@ var/global/dmm_suite/preloader/_preloader = new var/list/grid_models = list() var/key_len = 0 + + var/dmm_suite/loaded_map/LM = new if(measureOnly) delay_init = 0 // This try-catch is used as a budget "Finally" clause, as the dirt count // needs to be reset + var/watch = start_watch() + log_debug("[measureOnly ? "Measuring" : "Loading"] map: [fname]") try - dmmRegex.next = 1 - while(dmmRegex.Find(tfile, dmmRegex.next)) + LM.index = 1 + while(dmmRegex.Find(tfile, LM.index)) + LM.index = dmmRegex.next // "aa" = (/type{vars=blah}) if(dmmRegex.group[1]) // Model @@ -136,8 +146,10 @@ var/global/dmm_suite/preloader/_preloader = new if(xcrd >= 1) var/model_key = copytext(line, tpos, tpos + key_len) if(!grid_models[model_key]) - throw EXCEPTION("Undefined model key in DMM.") + throw EXCEPTION("Undefined model key in DMM: [model_key]. Map file: [fname].") parse_grid(grid_models[model_key], xcrd, ycrd, zcrd, LM) + // After this call, it is NOT safe to reference `dmmRegex` without another call to + // "Find" - we might've hit a map loader here and changed its state CHECK_TICK maxx = max(maxx, xcrd) @@ -148,14 +160,17 @@ var/global/dmm_suite/preloader/_preloader = new CHECK_TICK catch(var/exception/e) + _preloader.reset() if(delay_init) for(var/i in LM.touched_z_levels) zlevels.remove_dirt(i) throw e if(delay_init) + _preloader.reset() for(var/i in LM.touched_z_levels) zlevels.remove_dirt(i) + 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_debug("Min x: bounds[MAP_MINX]") @@ -166,10 +181,11 @@ var/global/dmm_suite/preloader/_preloader = new log_debug("Max z: bounds[MAP_MAXZ]") return null else - 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]))) - var/turf/T = t - //we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs - T.AfterChange(1,but_its_not_the_saaaaaame = TRUE) // are you happy now + 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]))) + var/turf/T = t + //we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs + T.AfterChange(1,keep_cabling = TRUE) return bounds /** @@ -204,7 +220,6 @@ var/global/dmm_suite/preloader/_preloader = new members = cached[1] members_attributes = cached[2] else - ///////////////////////////////////////////////////////// //Constructing members and corresponding variables lists //////////////////////////////////////////////////////// @@ -418,6 +433,7 @@ var/global/dmm_suite/preloader/_preloader = new //Preloader datum ////////////////// +// This ain't re-entrant, but we had this before the maploader update /dmm_suite/preloader parent_type = /datum var/list/attributes @@ -437,6 +453,12 @@ var/global/dmm_suite/preloader/_preloader = new what.vars[attribute] = value use_preloader = FALSE +// If the map loader fails, make this safe +/dmm_suite/preloader/proc/reset() + use_preloader = FALSE + attributes = list() + target_path = null + // A datum for use within the context of loading a single map, // so that one can have separate "unpowered" areas for ruins or whatever, // yet have a single area type for use of mapping, instead of creating @@ -445,6 +467,7 @@ var/global/dmm_suite/preloader/_preloader = new parent_type = /datum var/list/touched_z_levels = list() var/list/area_list = list() + var/index = 1 // To store the state of the regex /dmm_suite/loaded_map/proc/area_path_to_real_area(area/A) if(!ispath(A, /area)) diff --git a/code/modules/awaymissions/mission_code/spacehotel.dm b/code/modules/awaymissions/mission_code/spacehotel.dm index b5737ddcfd4..cebf5124d53 100644 --- a/code/modules/awaymissions/mission_code/spacehotel.dm +++ b/code/modules/awaymissions/mission_code/spacehotel.dm @@ -54,9 +54,8 @@ name = "space hotel pamphlet" info = "