Initialization deferral is now handled by the caller, but

is now also seamless
This commit is contained in:
Crazylemon64
2016-07-07 00:17:21 -07:00
parent 1745c71474
commit f0bac4c179
8 changed files with 110 additions and 53 deletions
+10 -2
View File
@@ -23,7 +23,7 @@
height = bounds[MAP_MAXY]
return bounds
/datum/map_template/proc/load(turf/T, centered = 0, delay_init = 0)
/datum/map_template/proc/load(turf/T, centered = 0)
var/turf/placement = T
var/min_x = placement.x
var/min_y = placement.y
@@ -43,7 +43,13 @@
// 1 bigger, to update the turf smoothing
var/turf/ST_bot_left = locate(max(1, min_x-1), max(1, min_y-1), placement.z)
var/turf/ST_top_right = locate(min(world.maxx, max_x+1), min(world.maxy, max_y+1), placement.z)
var/list/bounds = maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1, delay_init = delay_init)
// This is to place a freeze on initialization until the map's done loading
// otherwise atmos and stuff will start running mid-load
// This system will metaphorically snap in half (not postpone init everywhere)
// if given a multi-z template
// it might need to be adapted for that when that time comes
zlevels.add_dirt(placement.z)
var/list/bounds = maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1)
if(!bounds)
return 0
if(bot_left == null || top_right == null)
@@ -55,9 +61,11 @@
log_debug("One of the smoothing corners is bust")
else
log_debug("Tile smoothing from ([ST_bot_left.x],[ST_bot_left.y]) to ([ST_top_right.x],[ST_top_right.y])")
late_setup_level(
block(bot_left, top_right),
block(ST_bot_left, ST_top_right))
zlevels.remove_dirt(placement.z)
log_game("[name] loaded at [min_x],[min_y],[placement.z]")
return 1
+12 -3
View File
@@ -23,12 +23,11 @@
/atom/movable/New()
. = ..()
areaMaster = get_area_master(src)
var/turf/T = get_turf(src)
// If you're wondering what goofery this is, this is for things that need the environment
// around them set up - like `air_update_turf` and the like
if(auto_init && (ticker && ticker.current_state == GAME_STATE_PLAYING) && !(T && zlevels.is_zlevel_dirty(T.z)))
initialize()
if(auto_init && (ticker && ticker.current_state == GAME_STATE_PLAYING))
attempt_init()
/atom/movable/Destroy()
for(var/atom/movable/AM in contents)
@@ -40,6 +39,16 @@
pulledby = null
return ..()
// used to provide a good interface for the init delay system to step in
// and we don't need to call `get_turf` until the game's started
// at which point object creations are a fair toss more seldom
/atom/movable/proc/attempt_init()
var/turf/T = get_turf(src)
if (T && zlevels.is_zlevel_dirty(T.z))
zlevels.postpone_init(T.z, src)
else
initialize()
/atom/movable/proc/initialize()
return
@@ -19,10 +19,6 @@
to_chat(usr, "Map is too large to fit in bounds. Map's dimensions: ([template.width], [template.height])")
return
var/delay_init = 0
if(alert(usr,"Delay initialization? (Needed for large atmos-containing maps)","Delay","Yes","No") == "Yes")
delay_init = 1
var/list/preview = list()
for(var/S in template.get_affected_turfs(T,centered = TRUE))
preview += image('icons/turf/overlays.dmi',S,"greenOverlay")
@@ -30,7 +26,7 @@
if(alert(usr,"Confirm location.","Template Confirm","Yes","No") == "Yes")
var/timer = start_watch()
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has started to place the map template ([template.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a></span>")
if(template.load(T, centered = TRUE, delay_init = delay_init))
if(template.load(T, centered = TRUE))
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has placed a map template ([template.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a>. Took [stop_watch(timer)]s.</span>")
else
to_chat(usr, "Failed to place map")
+2 -3
View File
@@ -10,7 +10,6 @@
var/datum/map_template/template = null
var/centered = 1
var/loaded = 0
var/delay_init = 0
/obj/effect/landmark/map_loader/New(turf/loc, tname)
..()
@@ -28,13 +27,13 @@
/obj/effect/landmark/map_loader/proc/load(datum/map_template/t)
if(!t)
return
if(loaded)
if(loaded) // I wanna be super sure this loads only once
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.load(pos, centered = centered)
t.loaded++
qdel(src)
+7 -18
View File
@@ -31,12 +31,13 @@ var/global/dmm_suite/preloader/_preloader = new
* If `measureOnly` is set, then no atoms will be created, and all this will do
* is return the bounds after parsing the file
*
* If delay_init is set, then all initializations while the map is loading will
* be deferred until later
* You'll need it for large initializations like loading the cyberiad, where
* glass and similar can cause atmos to initialize before it's ready
* If you need to freeze init while you're working, you can use the spacial allocator's
* "add_dirt" and "remove_dirt" which will put initializations on hold until you say
* the word. This is important for loading large maps such as the cyberiad, where
* atmos will attempt to start before it's ready, causing runtimes galore if init is
* allowed to romp unchecked.
*/
/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)
/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)
var/tfile = dmm_file//the map file we're creating
var/fname = "Lambda"
if(isfile(tfile))
@@ -57,8 +58,6 @@ var/global/dmm_suite/preloader/_preloader = new
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()
@@ -91,9 +90,6 @@ var/global/dmm_suite/preloader/_preloader = new
var/xcrd
var/ycrd = text2num(dmmRegex.group[4]) + y_offset - 1
var/zcrd = text2num(dmmRegex.group[5]) + z_offset - 1
if(!measureOnly && delay_init)
zlevels.add_dirt(zcrd)
LM.touched_z_levels |= zcrd
if(zcrd > world.maxz)
if(cropMap)
@@ -161,15 +157,9 @@ 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)
_preloader.reset()
log_debug("Loaded map in [stop_watch(watch)]s.")
qdel(LM)
if(bounds[MAP_MINX] == 1.#INF) // Shouldn't need to check every item
@@ -465,7 +455,6 @@ var/global/dmm_suite/preloader/_preloader = new
// a new area type for each new ruin
/dmm_suite/loaded_map
parent_type = /datum
var/list/touched_z_levels = list()
var/list/area_list = list()
var/index = 1 // To store the state of the regex
+13 -17
View File
@@ -1,5 +1,7 @@
var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away_mission_config.txt")
// Call this before you remove the last dirt on a z level - that way, all objects
// will have proper atmos and other important enviro things
/proc/late_setup_level(turfs, smoothTurfs)
var/total_timer = start_watch()
var/subtimer = start_watch()
@@ -12,14 +14,10 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
log_debug("\tTook [stop_watch(subtimer)]s")
subtimer = start_watch()
log_debug("Initializing objects and lighting")
log_debug("Initializing lighting")
for(var/turf/T in turfs)
if(T.dynamic_lighting)
T.lighting_build_overlays()
for(var/obj/structure/cable/PC in T)
makepowernet_for(PC)
for(var/atom/movable/AM in T)
AM.initialize()
log_debug("\tTook [stop_watch(subtimer)]s")
subtimer = start_watch()
@@ -35,14 +33,6 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
var/turf/simulated/mineral/MT = T
MT.add_edges()
log_debug("\tTook [stop_watch(subtimer)]s")
log_debug("Initializing pipenets")
// We do this once we're finished initializing since otherwise the pipes
// won't have finished connecting
for(var/turf/T in turfs)
for(var/obj/machinery/atmospherics/machine in T)
machine.build_network()
log_debug("\tTook [stop_watch(subtimer)]s")
log_debug("Late setup finished - took [stop_watch(total_timer)]s")
/proc/createRandomZlevel()
@@ -56,8 +46,11 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
var/map = pick(potentialRandomZlevels)
var/file = file(map)
if(isfile(file))
maploader.load_map(file)
late_setup_level(block(locate(1, 1, world.maxz), locate(world.maxx, world.maxy, world.maxz)))
var/zlev = zlevels.add_new_zlevel()
zlevels.add_dirt(zlev)
maploader.load_map(file, z_offset = zlev)
late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev)))
zlevels.remove_dirt(zlev)
log_to_dd(" Away mission loaded: [map]")
//map_transition_config.Add(AWAY_MISSION_LIST)
@@ -85,8 +78,11 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
var/file = file(map)
if(isfile(file))
log_startup_progress("Loading away mission: [map]")
maploader.load_map(file)
late_setup_level(block(locate(1, 1, world.maxz), locate(world.maxx, world.maxy, world.maxz)))
var/zlev = zlevels.add_new_zlevel()
zlevels.add_dirt(zlev)
maploader.load_map(file, z_offset = zlev)
late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev)))
zlevels.remove_dirt(zlev)
log_to_dd(" Away mission loaded: [map]")
//map_transition_config.Add(AWAY_MISSION_LIST)
+42
View File
@@ -2,6 +2,48 @@
var/flags = 0
var/dirt_count = 0
var/zpos
var/list/init_list = list()
var/list/pipes = list()
var/list/cables = list()
/datum/zlevel/New(z)
zpos = z
/datum/zlevel/proc/resume_init()
if(dirt_count > 0)
throw EXCEPTION("Init told to resume when z-level still dirty. Z level: '[zpos]'")
log_debug("Releasing freeze on z-level '[zpos]'!")
log_debug("Beginning initialization!")
var/watch = start_watch()
for(var/schmoo in init_list)
var/atom/movable/AM = schmoo
if(AM) // to catch stuff like the nuke disk that no longer exists
AM.initialize()
if(istype(AM, /obj/machinery/atmospherics))
pipes.Add(AM)
else if(istype(AM, /obj/structure/cable))
cables.Add(AM)
log_debug("Primary initialization finished in [stop_watch(watch)]s.")
init_list.Cut()
do_pipes()
do_cables()
/datum/zlevel/proc/do_pipes()
var/watch = start_watch()
log_debug("Building pipenets on z-level '[zpos]'!")
for(var/schmoo in pipes)
var/obj/machinery/atmospherics/machine = schmoo
if(machine)
machine.build_network()
pipes.Cut()
log_debug("Took [stop_watch(watch)]s")
/datum/zlevel/proc/do_cables()
var/watch = start_watch()
log_debug("Building powernets on z-level '[zpos]'!")
for(var/schmoo in cables)
var/obj/structure/cable/C = schmoo
if(C)
makepowernet_for(C)
cables.Cut()
log_debug("Took [stop_watch(watch)]s")
@@ -12,6 +12,15 @@ var/global/datum/zlev_manager/zlevels = new
z_list[i] = new /datum/zlevel(i)
/datum/zlev_manager/proc/get_zlev(z)
if(z < 1)
throw EXCEPTION("Non-positive z level given!")
else if (z > z_list.len)
throw EXCEPTION("Untracked z level: '[z]'")
else
return z_list[z]
// For when you need the z-level to be at a certain point
/datum/zlev_manager/proc/increase_max_zlevel_to(new_maxz)
if(world.maxz>=new_maxz)
@@ -53,19 +62,28 @@ var/global/datum/zlev_manager/zlevels = new
// Returns whether the given z level has a freeze on initialization
/datum/zlev_manager/proc/is_zlevel_dirty(z)
if(z > z_list.len)
return 0 // It's not dirty if it's not being tracked
var/datum/zlevel/our_z = z_list[z]
var/datum/zlevel/our_z = get_zlev(z)
return (our_z.dirt_count > 0)
// Increases the dirt count on a z level
/datum/zlev_manager/proc/add_dirt(z)
var/datum/zlevel/our_z = z_list[z]
var/datum/zlevel/our_z = get_zlev(z)
if(our_z.dirt_count == 0)
log_debug("Placing an init freeze on z-level '[our_z.zpos]'!")
our_z.dirt_count++
// Decreases the dirt count on a z level
/datum/zlev_manager/proc/remove_dirt(z)
var/datum/zlevel/our_z = z_list[z]
var/datum/zlevel/our_z = get_zlev(z)
our_z.dirt_count--
if(our_z.dirt_count == 0)
our_z.resume_init()
if(our_z.dirt_count < 0)
log_debug("WARNING: Imbalanced dirt removal")
our_z.dirt_count = 0
/datum/zlev_manager/proc/postpone_init(z, thing)
var/datum/zlevel/our_z = get_zlev(z)
our_z.init_list.Add(thing)