It's re-entrant now

This commit is contained in:
Crazylemon64
2016-07-04 14:52:19 -07:00
parent a44808f195
commit 27ee3c7247
10 changed files with 121 additions and 31 deletions
+3 -1
View File
@@ -41,11 +41,13 @@ var/global/pipe_processing_killed = 0
/datum/controller/game_controller/proc/setup()
world.tick_lag = config.Ticklag
zlevels.initialize()
preloadTemplates()
if(!config.disable_away_missions)
createRandomZlevel()
if(!config.disable_space_ruins)
seedRuins(7, rand(10, 13), /area/space, space_ruins_templates)
seedRuins(7, rand(0, 3), /area/space, space_ruins_templates)
setup_objects()
setupgenetics()
+2 -2
View File
@@ -23,7 +23,7 @@
height = bounds[MAP_MAXY]
return bounds
/datum/map_template/proc/load(turf/T, centered = 0)
/datum/map_template/proc/load(turf/T, centered = 0, delay_init = 0)
var/turf/placement = T
var/min_x = placement.x
var/min_y = placement.y
@@ -43,7 +43,7 @@
// 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)
var/list/bounds = maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1, delay_init = delay_init)
if(!bounds)
return 0
if(bot_left == null || top_right == null)
+1 -1
View File
@@ -31,7 +31,7 @@ var/list/dirty_z_levels = list()
// 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(!(T && T.z in dirty_z_levels) && auto_init && ticker && ticker.current_state == GAME_STATE_PLAYING)
if(!(T && zlevels.is_zlevel_dirty(T.z)) && auto_init && ticker && ticker.current_state == GAME_STATE_PLAYING)
initialize()
/atom/movable/Destroy()
+4 -3
View File
@@ -192,15 +192,16 @@
return W
/turf/proc/AfterChange() //called after a turf has been replaced in ChangeTurf()
// 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()
levelupdate()
CalculateAdjacentTurfs()
if(!can_have_cabling())
if(!but_its_not_the_saaaaaame && !can_have_cabling())
for(var/obj/structure/cable/C in contents)
qdel(C)
/turf/simulated/AfterChange(ignore_air)
/turf/simulated/AfterChange(ignore_air, but_its_not_the_saaaaaame = FALSE)
..()
RemoveLattice()
if(!ignore_air)
@@ -19,6 +19,10 @@
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")
@@ -26,7 +30,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))
if(template.load(T, centered = TRUE, delay_init = delay_init))
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")
+26 -21
View File
@@ -27,8 +27,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
*/
/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)
/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
if(isfile(tfile))
tfile = file2text(tfile)
@@ -43,14 +48,12 @@ var/global/dmm_suite/preloader/_preloader = new
var/list/bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF)
var/list/grid_models = list()
var/key_len = 0
// This ain't re-entrant
// Meaning - don't load more than one map at once, using `spawn` or whatever
var/list/old_dirty_z_levels = deepCopyList(dirty_z_levels)
var/list/touched_z_levels = list()
var/dmm_suite/loaded_map/LM = new
// This try-catch is used as a budget "Finally" clause, as the "touched_z_levels"
// var needs to be reset
// This try-catch is used as a budget "Finally" clause, as the dirt count
// needs to be reset
try
dmmRegex.next = 1
while(dmmRegex.Find(tfile, dmmRegex.next))
@@ -78,14 +81,15 @@ 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)
dirty_z_levels |= zcrd
if(!measureOnly && delay_init)
zlevels.add_dirt(zcrd)
touched_z_levels |= zcrd
if(zcrd > world.maxz)
if(cropMap)
continue
else
world.maxz = zcrd //create a new z_level if needed
zlevels.increase_max_zlevel_to(zcrd) //create a new z_level if needed
bounds[MAP_MINX] = min(bounds[MAP_MINX], xcrdStart)
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd)
@@ -144,27 +148,28 @@ var/global/dmm_suite/preloader/_preloader = new
CHECK_TICK
catch(var/exception/e)
if(!measureOnly)
dirty_z_levels = old_dirty_z_levels
if(!measureOnly && delay_init)
for(var/i in touched_z_levels)
zlevels.remove_dirt(i)
throw e
// This *might* leak memory? Whatever it's a trivial quantity
if(!measureOnly)
dirty_z_levels = old_dirty_z_levels
if(!measureOnly && delay_init)
for(var/i in touched_z_levels)
zlevels.remove_dirt(i)
qdel(LM)
if(bounds[MAP_MINX] == 1.#INF) // Shouldn't need to check every item
log_startup_progress("Min x: bounds[MAP_MINX]")
log_startup_progress("Min y: bounds[MAP_MINY]")
log_startup_progress("Min z: bounds[MAP_MINZ]")
log_startup_progress("Max x: bounds[MAP_MAXX]")
log_startup_progress("Max y: bounds[MAP_MAXY]")
log_startup_progress("Max z: bounds[MAP_MAXZ]")
log_debug("Min x: bounds[MAP_MINX]")
log_debug("Min y: bounds[MAP_MINY]")
log_debug("Min z: bounds[MAP_MINZ]")
log_debug("Max x: bounds[MAP_MAXX]")
log_debug("Max y: bounds[MAP_MAXY]")
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)
T.AfterChange(1,but_its_not_the_saaaaaame = TRUE) // are you happy now
return bounds
/**
@@ -326,7 +326,7 @@ swapmap
x2+=x1-1
y2+=y1-1
z2+=z1-1
world.maxz=max(z2,world.maxz) // stretch z if necessary
zlevels.increase_max_zlevel_to(z2) // stretch z if necessary
if(!ischunk)
swapmaps_loaded[src]=null
swapmaps_byname[id]=src
@@ -373,7 +373,7 @@ swapmap
mz=max(mz,M.z2)
world.maxx=mx
world.maxy=my
world.maxz=mz
zlevels.cut_levels_downto(mz)
// save and delete
proc/Unload()
+7
View File
@@ -0,0 +1,7 @@
/datum/zlevel
var/flags = 0
var/dirt_count = 0
var/zpos
/datum/zlevel/New(z)
zpos = z
@@ -0,0 +1,69 @@
var/global/datum/zlev_manager/zlevels = new
/datum/zlev_manager
// A list of z-levels
var/list/z_list = list()
// Populate our z level list
/datum/zlev_manager/proc/initialize()
for(var/i = 1, i < world.maxz, i++)
z_list.Add(new /datum/zlevel(i))
// 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)
return
while(world.maxz<new_maxz)
add_new_zlevel()
// Increments the max z-level by one
// For convenience's sake returns the z-level added
/datum/zlev_manager/proc/add_new_zlevel()
world.maxz++
var/our_z = world.maxz
z_list.Add(new /datum/zlevel(our_z))
return our_z
/datum/zlev_manager/proc/cut_levels_downto(new_maxz)
if(world.maxz <= new_maxz)
return
while(world.maxz>new_maxz)
kill_topmost_zlevel()
// Decrements the max z-level by one
// not normally used, but hey the swapmap loader wanted it
/datum/zlev_manager/proc/kill_topmost_zlevel()
var/our_z = world.maxz
qdel(z_list[our_z])
z_list.Remove(our_z)
world.maxz--
/*
* "Dirt" management
* "Dirt" is used to keep track of whether a z level should automatically have
* stuff on it initialize or not - the map loaders, when set to defer init, place
* a freeze on the z levels they touch so as to prevent atmos from exploding,
* among other things
*/
// 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]
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]
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]
our_z.dirt_count--
+2
View File
@@ -1990,6 +1990,8 @@
#include "code\modules\spacepods\parts.dm"
#include "code\modules\spacepods\pod_fabricator.dm"
#include "code\modules\spacepods\spacepod.dm"
#include "code\modules\spacial_allocator\zlevel.dm"
#include "code\modules\spacial_allocator\zlevel_manager.dm"
#include "code\modules\store\items.dm"
#include "code\modules\store\store.dm"
#include "code\modules\surgery\bones.dm"