Files
4ab234f10c maploader / overmaps update - struct system, overmaps location bindings, misc backend improvements (#6403)
tl;dr level collections that can easily be logically restructured/moved
as necessary

will eventually be used for radio and overmaps location resolution.

this is the last part of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP/pull/4841
that has not yet been integrated.
this will be a draft for a while.

---------

Co-authored-by: LetterN <24603524+LetterN@users.noreply.github.com>
2025-11-06 17:49:23 -08:00

178 lines
5.9 KiB
Plaintext

//* This file is explicitly licensed under the MIT license. *//
//* Copyright (c) 2024 Citadel Station Developers *//
/**
* Contains loading / unloading logic.
*/
//* Loading *//
/**
* anything to do immediately on load
*
* called after level on_loaded_immediate's
*/
/datum/map/proc/on_loaded_immediate()
SHOULD_CALL_PARENT(TRUE)
loaded = TRUE
loaded_z_indices = list()
loaded_z_grid = list()
loaded_z_stacks = list()
loaded_z_planes = list()
var/struct_min_x = INFINITY
var/struct_min_y = INFINITY
var/struct_min_z = INFINITY
var/struct_max_x = -INFINITY
var/struct_max_y = -INFINITY
var/struct_max_z = -INFINITY
var/list/elevation_by_z_str = list()
// gather level data for loaded lists, and give levels virtual alignment here
for(var/idx in 1 to length(levels))
var/datum/map_level/level = levels[idx]
loaded_z_indices += level.z_index
if(!level.struct_active)
continue
loaded_z_grid["[level.struct_x],[level.struct_y],[level.struct_z]"] = level
struct_min_x = min(struct_min_x, level.struct_x)
struct_max_x = max(struct_max_x, level.struct_x)
struct_min_y = min(struct_min_y, level.struct_y)
struct_max_y = max(struct_max_y, level.struct_y)
struct_min_z = min(struct_min_z, level.struct_z)
struct_max_z = max(struct_max_z, level.struct_z)
var/x_y_str = "[level.struct_x],[level.struct_y]"
if(!loaded_z_stacks[x_y_str])
loaded_z_stacks[x_y_str] = list()
loaded_z_stacks[x_y_str] += level
var/z_str = "[level.struct_z]"
if(!loaded_z_planes[z_str])
loaded_z_planes[z_str] = list()
loaded_z_planes[z_str] += level
level.virtual_alignment_x = level.struct_x * (world.maxx - LEVEL_BORDER_WIDTH * 2) - LEVEL_BORDER_WIDTH
level.virtual_alignment_y = level.struct_y * (world.maxy - LEVEL_BORDER_WIDTH * 2) - LEVEL_BORDER_WIDTH
// sort z stacks
for(var/x_y_str in loaded_z_stacks)
var/list/datum/map_level/levels_in_stack = loaded_z_stacks[x_y_str]
tim_sort(levels_in_stack, /proc/cmp_map_level_struct_z_asc)
// sort z planes and gather elevations
for(var/z_str in loaded_z_planes)
var/list/datum/map_level/levels_in_plane = loaded_z_planes[z_str]
tim_sort(levels_in_plane, /proc/cmp_map_level_load_sequence)
elevation_by_z_str["[z_str]"] = levels_in_plane[1].ceiling_height || ceiling_height_default
// calculate loaded sparse size
loaded_sparse_size_x = struct_max_x - struct_min_x + 1
loaded_sparse_size_y = struct_max_y - struct_min_y + 1
loaded_sparse_size_z = struct_max_z - struct_min_z + 1
// sort elevations bottom to top
tim_sort(elevation_by_z_str, /proc/cmp_numeric_text_asc)
// convert elevations to lockstep
var/list/elevation_lockstep_indices = list()
var/list/elevation_lockstep_heights = list()
for(var/i in 1 to length(elevation_by_z_str))
var/z_str = elevation_by_z_str[i]
elevation_lockstep_indices += text2num(z_str)
elevation_lockstep_heights += elevation_by_z_str[z_str]
// compute and set elevations on levels
for(var/datum/map_level/level as anything in levels)
if(!level.struct_active)
continue
if(level.struct_z > 0)
var/index_of_first_nonnegative
var/total_height = 0
for(index_of_first_nonnegative in 1 to length(elevation_lockstep_indices))
if(elevation_lockstep_indices[index_of_first_nonnegative] >= 0)
break
var/last_virtual_z = 0
for(var/index in index_of_first_nonnegative to length(elevation_lockstep_indices))
var/virtual_z = elevation_lockstep_indices[index]
if(virtual_z != last_virtual_z)
total_height += ceiling_height_default * ((virtual_z - 1) - last_virtual_z)
// if it's on the level we're tallying to we ignore it as we don't tally ourselves
// because virtual_elevation is meters off the ground.. of the ground.
if(virtual_z == level.struct_z)
break
else if(virtual_z > level.struct_z)
CRASH("overshot level somehow?")
// tally current level
total_height += elevation_lockstep_heights[index]
// +1 to skip over the current level, which we already tallied
last_virtual_z = virtual_z + 1
level.virtual_elevation = total_height
else if(level.struct_z < 0)
var/index_of_first_negative
var/total_height = 0
for(index_of_first_negative in length(elevation_lockstep_indices) to 1 step -1)
if(elevation_lockstep_indices[index_of_first_negative] < 0)
break
var/last_virtual_z = 0
for(var/index in index_of_first_negative to 1 step -1)
var/virtual_z = elevation_lockstep_indices[index]
if(virtual_z != last_virtual_z)
total_height -= ceiling_height_default * (last_virtual_z - (virtual_z + 1))
// tally current level
total_height -= elevation_lockstep_heights[index]
// if we're on the level we're tallying to, we're done
if(virtual_z == level.struct_z)
break
// sanity check
else if(virtual_z < level.struct_z)
CRASH("overshot level somehow?")
level.virtual_elevation = total_height
if(overmap_initializer)
SSovermaps.initialize_entity(overmap_initializer, src)
/**
* anything to do after loading with any dependencies
*
* called after level on_loaded_finalize's
*/
/datum/map/proc/on_loaded_finalize()
SHOULD_CALL_PARENT(TRUE)
//* Unloading *//
/**
* TOOD: not hooked in yet
*
* Fired before zclear fires on the zlevels that consist of us
* * Levels have their on_unload_pre_zclear called before this.
*/
/datum/map/proc/on_unload_pre_zclear()
SHOULD_CALL_PARENT(TRUE)
/**
* TOOD: not hooked in yet
*
* Fired after zclear fires on the zlevels that consist of us
* * Levels have their on_unload_finalize called before this.
* * zlevels and then ourselves are un-referenced and/or garbage collected (if necessary) after.
*/
/datum/map/proc/on_unload_finalize()
SHOULD_CALL_PARENT(TRUE)
loaded = FALSE
loaded_z_indices = null
loaded_z_grid = null
loaded_sparse_size_x = null
loaded_sparse_size_y = null
loaded_sparse_size_z = null
loaded_z_planes = null
loaded_z_stacks = null
for(var/datum/map_level/level as anything in levels)
level.virtual_alignment_x = null
level.virtual_alignment_y = null
level.virtual_elevation = null