Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimise ImmediateCalculateAdjacentTurfs and gravity #1125

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _maps/lambdastation.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"Up":1
},
{
"Down":-1
"Down":1
}
]
}
2 changes: 1 addition & 1 deletion _maps/layeniastation.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"Linkage": "Cross"
},
{
"Down": -1,
"Down": 1,
"Baseturf": "/turf/open/openspace",
"Linkage": "Cross"
}
Expand Down
4 changes: 2 additions & 2 deletions _maps/smexistation.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"Baseturf":"/turf/open/lava/plasma/ice_moon"
},
{
"Down":-1,
"Down":1,
"Up":1,
"Mining":true,
"Linkage":null,
Expand All @@ -34,7 +34,7 @@
"Baseturf":"/turf/open/openspace/icemoon"
},
{
"Down":-1,
"Down":1,
"Mining":true,
"Linkage":null,
"Gravity":true,
Expand Down
4 changes: 2 additions & 2 deletions _maps/snaxi.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"Baseturf":"/turf/open/lava/plasma/ice_moon"
},
{
"Down":-1,
"Down":1,
"Up":1,
"Station":0,
"Mining":true,
Expand All @@ -36,7 +36,7 @@
"Baseturf":"/turf/open/openspace/icemoon"
},
{
"Down":-1,
"Down":1,
"Mining":true,
"Linkage":null,
"Gravity":true,
Expand Down
2 changes: 1 addition & 1 deletion code/__DEFINES/maps.dm
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ require only minor tweaks.
// number - default gravity if there's no gravity generators or area overrides present
#define ZTRAIT_GRAVITY "Gravity"

// numeric offsets - e.g. {"Down": -1} means that chasms will fall to z - 1 rather than oblivion
// numeric offsets - e.g. {"Down": 1} means that chasms will fall to z - 1 rather than oblivion
#define ZTRAIT_UP "Up"
#define ZTRAIT_DOWN "Down"

Expand Down
49 changes: 48 additions & 1 deletion code/controllers/subsystem/mapping.dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,21 @@ SUBSYSTEM_DEF(mapping)
// Z-manager stuff
var/station_start // should only be used for maploading-related tasks
var/space_levels_so_far = 0
var/list/z_list
///list of all z level datums in the order of their z (z level 1 is at index 1, etc.)
var/list/datum/space_level/z_list
///list of all z level indices that form multiz connections and whether theyre linked up or down
///list of lists, inner lists are of the form: list("up or down link direction" = TRUE)
var/list/multiz_levels = list()
var/datum/space_level/transit
var/datum/space_level/empty_space
var/num_of_res_levels = 1
/// Lookup for zlevel to station z. text = num.
var/list/z_to_station_z_index

///shows the default gravity value for each z level. recalculated when gravity generators change.
///associative list of the form: list("[z level num]" = max generator gravity in that z level OR the gravity level trait)
var/list/gravity_by_z_level = list()

var/stat_map_name = "Loading..."

/// Lookup list for random generated IDs.
Expand Down Expand Up @@ -155,8 +163,46 @@ SUBSYSTEM_DEF(mapping)
setup_map_transitions()
generate_station_area_list()
initialize_reserved_level(transit.z_value)
generate_z_level_linkages()
calculate_default_z_level_gravities()
return ..()

/datum/controller/subsystem/mapping/proc/calculate_default_z_level_gravities()
for(var/z_level in 1 to length(z_list))
calculate_z_level_gravity(z_level)

/datum/controller/subsystem/mapping/proc/generate_z_level_linkages()
for(var/z_level in 1 to length(z_list))
generate_linkages_for_z_level(z_level)

/datum/controller/subsystem/mapping/proc/generate_linkages_for_z_level(z_level)
if(!isnum(z_level) || z_level <= 0)
return FALSE

if(multiz_levels.len < z_level)
multiz_levels.len = z_level

var/linked_down = level_trait(z_level, ZTRAIT_DOWN)
var/linked_up = level_trait(z_level, ZTRAIT_UP)
multiz_levels[z_level] = list()
if(linked_down)
multiz_levels[z_level]["[DOWN]"] = TRUE
if(linked_up)
multiz_levels[z_level]["[UP]"] = TRUE

/datum/controller/subsystem/mapping/proc/calculate_z_level_gravity(z_level_number)
if(!isnum(z_level_number) || z_level_number < 1)
return FALSE

var/max_gravity = 0

for(var/obj/machinery/gravity_generator/main/grav_gen as anything in GLOB.gravity_generators["[z_level_number]"])
max_gravity = max(grav_gen.setting, max_gravity)

max_gravity = max_gravity || level_trait(z_level_number, ZTRAIT_GRAVITY) || 0//just to make sure no nulls
gravity_by_z_level["[z_level_number]"] = max_gravity
return max_gravity

/* Nuke threats, for making the blue tiles on the station go RED
Used by the AI doomsday and the self destruct nuke.
*/
Expand Down Expand Up @@ -229,6 +275,7 @@ SUBSYSTEM_DEF(mapping)
clearing_reserved_turfs = SSmapping.clearing_reserved_turfs

z_list = SSmapping.z_list
multiz_levels = SSmapping.multiz_levels

/datum/controller/subsystem/mapping/proc/LoadGroup(list/errorList, name, path, files, list/traits, list/default_traits, silent = FALSE, orientation = SOUTH)
. = list()
Expand Down
43 changes: 18 additions & 25 deletions code/game/atoms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1425,6 +1425,8 @@
* Sends signals COMSIG_ATOM_HAS_GRAVITY and COMSIG_TURF_HAS_GRAVITY, both can force gravity with
* the forced gravity var
*
* micro-optimized to hell because this proc is very hot, being called several times per movement every movement.
*
* Gravity situations:
* * No gravity if you're not in a turf
* * No gravity if this atom is in is a space turf
Expand All @@ -1433,37 +1435,28 @@
* * Gravity if the Z level has an SSMappingTrait for ZTRAIT_GRAVITY
* * otherwise no gravity
*/
/atom/proc/has_gravity(turf/T)
if(!T || !isturf(T))
T = get_turf(src)
/atom/proc/has_gravity(turf/gravity_turf)
if(!isturf(gravity_turf))
gravity_turf = get_turf(src)

if(!T)
if(!gravity_turf)//no gravity in nullspace
return 0

var/list/forced_gravity = list()
SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, T, forced_gravity)
if(!forced_gravity.len)
SEND_SIGNAL(T, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity)
if(forced_gravity.len)
var/max_grav
for(var/i in forced_gravity)
//the list isnt created every time as this proc is very hot, its only accessed if anything is actually listening to the signal too
var/static/list/forced_gravity = list()
if(SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, gravity_turf, forced_gravity))
if(!length(forced_gravity))
SEND_SIGNAL(gravity_turf, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity)

var/max_grav = 0
for(var/i in forced_gravity)//our gravity is the strongest return forced gravity we get
max_grav = max(max_grav, i)
forced_gravity.Cut()
//cut so we can reuse the list, this is ok since forced gravity movers are exceedingly rare compared to all other movement
return max_grav

if(isspaceturf(T)) // Turf never has gravity
return 0

var/area/A = get_area(T)
if(A.has_gravity) // Areas which always has gravity
return A.has_gravity
else
// There's a gravity generator on our z level
if(GLOB.gravity_generators["[T.z]"])
var/max_grav = 0
for(var/obj/machinery/gravity_generator/main/G in GLOB.gravity_generators["[T.z]"])
max_grav = max(G.setting,max_grav)
return max_grav
return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY)
var/area/turf_area = gravity_turf.loc
return !gravity_turf.force_no_gravity && (SSmapping.gravity_by_z_level["[gravity_turf.z]"] || turf_area.has_gravity)

/**
* Causes effects when the atom gets hit by a rust effect from heretics
Expand Down
5 changes: 4 additions & 1 deletion code/game/turfs/open.dm
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@
air.copy_from_turf(src)
update_air_ref(planetary_atmos ? 1 : 2)

ImmediateCalculateAdjacentTurfs()
if(times_fired)
init_immediate_calculate_adjacent_turfs()
else
ImmediateCalculateAdjacentTurfs()

/turf/open/proc/GetHeatCapacity()
. = air.heat_capacity()
Expand Down
3 changes: 3 additions & 0 deletions code/game/turfs/turf.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ GLOBAL_LIST_EMPTY(station_turfs)

var/tiled_dirt = FALSE // use smooth tiled dirt decal

///whether or not this turf forces movables on it to have no gravity (unless they themselves have forced gravity)
var/force_no_gravity = FALSE

/turf/vv_edit_var(var_name, new_value)
var/static/list/banned_edits = list("x", "y", "z")
if(var_name in banned_edits)
Expand Down
57 changes: 56 additions & 1 deletion code/modules/atmospherics/environmental/LINDA_system.dm
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,67 @@
/atom/movable/proc/BlockThermalConductivity() // Objects that don't let heat through.
return FALSE

/// This proc is a more deeply optimized version of immediate_calculate_adjacent_turfs
/// It contains dumbshit, and also stuff I just can't do at runtime
/// If you're not editing behavior, just read that proc. It's less bad
/turf/proc/init_immediate_calculate_adjacent_turfs()
//Basic optimization, if we can't share why bother asking other people ya feel?
// You know it's gonna be stupid when they include a unit test in the atmos code
// Yes, inlining the string concat does save 0.1 seconds
#ifdef UNIT_TESTS
ASSERT(UP == 16)
ASSERT(DOWN == 32)
#endif
LAZYINITLIST(src.atmos_adjacent_turfs)
var/list/atmos_adjacent_turfs = src.atmos_adjacent_turfs
var/blocks_air = src.blocks_air
var/canpass = CANATMOSPASS(src, src)
var/canvpass = CANVERTICALATMOSPASS(src, src)
// I am essentially inlineing two get_dir_multizs here, because they're way too slow on their own. I'm sorry brother
var/list/z_traits = SSmapping.multiz_levels[z]
for(var/direction in GLOB.cardinals_multiz)
// Yes this is a reimplementation of get_step_multiz. It's faster tho. fuck you
var/turf/current_turf = (direction & (UP|DOWN)) ? \
(direction & UP) ? \
(z_traits["16"]) ? \
(get_step(locate(x, y, z + z_traits["16"]), NONE)) : \
(null) : \
(z_traits["32"]) ? \
(get_step(locate(x, y, z + z_traits["32"]), NONE)) : \
(null) : \
(get_step(src, direction))

if(!isopenturf(current_turf)) // not interested in you brother
continue

//Can you and me form a deeper relationship, or is this just a passing wind
// (direction & (UP | DOWN)) is just "is this vertical" by the by
if((direction & (UP|DOWN) ? (canvpass && CANVERTICALATMOSPASS(current_turf, src)) : (canpass && CANATMOSPASS(current_turf, src))) && !(blocks_air || current_turf.blocks_air))
LAZYINITLIST(current_turf.atmos_adjacent_turfs)
atmos_adjacent_turfs[current_turf] = TRUE
current_turf.atmos_adjacent_turfs[src] = TRUE
else
atmos_adjacent_turfs -= current_turf
if (current_turf.atmos_adjacent_turfs)
current_turf.atmos_adjacent_turfs -= src
UNSETEMPTY(current_turf.atmos_adjacent_turfs)
current_turf.set_sleeping(current_turf.blocks_air)
// This was originally (isspaceturf(T.get_z_base_turf()), -1), but we don't have space, so
// we just pass FALSE to save time.
current_turf?.__update_auxtools_turf_adjacency_info(FALSE, -1)

UNSETEMPTY(atmos_adjacent_turfs)
src.atmos_adjacent_turfs = atmos_adjacent_turfs
set_sleeping(blocks_air)
__update_auxtools_turf_adjacency_info(FALSE)

/turf/proc/ImmediateCalculateAdjacentTurfs()
var/list/atmos_adjacent_turfs = src.atmos_adjacent_turfs // save ourselves a bunch of datum var accesses
var/canpass = CANATMOSPASS(src, src)
var/canvpass = CANVERTICALATMOSPASS(src, src)
for(var/direction in GLOB.cardinals_multiz)
var/turf/T = get_step_multiz(src, direction)
if(!istype(T))
if(!T)
continue
if(isopenturf(T) && !(blocks_air || T.blocks_air) && ((direction & (UP|DOWN))? (canvpass && CANVERTICALATMOSPASS(T, src)) : (canpass && CANATMOSPASS(T, src))) )
LAZYINITLIST(atmos_adjacent_turfs)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mapping/space_management/multiz_helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
var/other_z = center_z
var/offset
while((offset = SSmapping.level_trait(other_z, ZTRAIT_DOWN)))
other_z += offset
other_z -= offset
if(other_z in .)
break // no infinite loops
. += other_z
Expand Down
10 changes: 5 additions & 5 deletions code/modules/mapping/space_management/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,18 @@

// Attempt to get the turf below the provided one according to Z traits
/datum/controller/subsystem/mapping/proc/get_turf_below(turf/T)
if (!T)
if (!T || !initialized)
return
var/offset = level_trait(T.z, ZTRAIT_DOWN)
var/offset = multiz_levels[T.z]["[DOWN]"]
if (!offset)
return
return locate(T.x, T.y, T.z + offset)
return locate(T.x, T.y, T.z - offset)

// Attempt to get the turf above the provided one according to Z traits
/datum/controller/subsystem/mapping/proc/get_turf_above(turf/T)
if (!T)
if (!T || !initialized)
return
var/offset = level_trait(T.z, ZTRAIT_UP)
var/offset = multiz_levels[T.z]["[UP]"]
if (!offset)
return
return locate(T.x, T.y, T.z + offset)
Expand Down
2 changes: 2 additions & 0 deletions code/modules/mapping/space_management/zlevel_manager.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
// TODO: sleep here if the Z level needs to be cleared
var/datum/space_level/S = new z_type(new_z, name, traits)
z_list += S
generate_linkages_for_z_level(new_z)
calculate_z_level_gravity(new_z)
return S

/datum/controller/subsystem/mapping/proc/get_level(z)
Expand Down
1 change: 1 addition & 0 deletions code/modules/power/gravitygenerator.dm
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
GLOB.gravity_generators["[z]"] |= src
else
GLOB.gravity_generators["[z]"] -= src
SSmapping.calculate_z_level_gravity(z)

/obj/machinery/gravity_generator/main/proc/change_setting(value)
if(value != setting)
Expand Down
Loading