Assorted performance improvements (#25649)

* Improved efficiency of playsound.

* Improve performance of turf/Enter

* Improve performace of thrown objects.

* Improved performance of /atom/movable/CanPass.

* Improved pipeline destruction performance.

* Apply suggestions from code review

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com>
Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>

---------

Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>
Co-authored-by: FunnyMan3595 (Charlie Nolan) <funnyman@google.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com>
This commit is contained in:
Charlie Nolan
2024-07-16 03:12:13 -07:00
committed by GitHub
parent a5dd1a1bd3
commit fb93e5a74a
6 changed files with 75 additions and 60 deletions
+3 -7
View File
@@ -243,13 +243,9 @@ SUBSYSTEM_DEF(throwing)
return
thrownthing.throwing = null
if(!hit)
for(var/atom/movable/obstacle as anything in get_turf(thrownthing)) //looking for our target on the turf we land on.
if(obstacle == target)
hit = TRUE
thrownthing.throw_impact(obstacle, src)
if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing
return //deletion should already be handled by on_thrownthing_qdel()
break
if(get_turf(target) == get_turf(thrownthing))
hit = TRUE
thrownthing.throw_impact(target, src)
if(!hit)
thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground.
if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing
+3 -2
View File
@@ -529,9 +529,10 @@
return FALSE
/atom/movable/CanPass(atom/movable/mover, turf/target, height=1.5)
if(mover in buckled_mobs)
// This condition is copied from atom to avoid an extra parent call, because this is a very hot proc.
if(!density || !height)
return TRUE
return ..()
return LAZYIN(buckled_mobs, mover)
/atom/movable/proc/get_spacemove_backup()
var/atom/movable/dense_object_backup
+22 -15
View File
@@ -61,25 +61,32 @@ falloff_distance - Distance at which falloff begins. Sound is at peak volume (in
var/sound/S = sound(get_sfx(soundin))
var/maxdistance = SOUND_RANGE + extrarange
var/list/listeners = GLOB.player_list
if(!ignore_walls) //these sounds don't carry through walls
listeners = listeners & hearers(maxdistance, turf_source)
for(var/P in listeners)
var/mob/M = P
if(!M || !M.client)
var/list/possible_listeners = list()
var/list/desired_turfs = list()
for(var/mob/P as anything in GLOB.player_list)
if(isnull(P) || !P.client)
continue
var/turf/T = get_turf(P)
if(!T || T.z != turf_source.z || get_dist(T, turf_source) > maxdistance)
continue
var/turf/T = get_turf(M) // These checks need to be changed if z-levels are ever further refactored
if(!T)
continue
if(T.z != turf_source.z)
continue
possible_listeners += P
desired_turfs |= T
var/distance = get_dist(M, turf_source)
var/list/listeners = list()
if(ignore_walls)
listeners = possible_listeners
else if(length(possible_listeners))
var/list/turf_vis = list()
for(var/turf/T as anything in desired_turfs)
turf_vis[T] = inLineOfSight(T.x, T.y, turf_source.x, turf_source.y, T.z)
if(distance <= maxdistance)
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, 1, use_reverb)
for(var/mob/P in possible_listeners)
if(turf_vis[get_turf(P)])
listeners += P
for(var/mob/M as anything in listeners)
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, 1, use_reverb)
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff_exponent = SOUND_FALLOFF_EXPONENT, channel = 0, pressure_affected = TRUE, sound/S, max_distance, falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = 1, use_reverb = TRUE)
if(!client || !can_hear())
+18 -11
View File
@@ -195,16 +195,22 @@
// First, make sure it can leave its square
if(isturf(mover.loc))
// Nothing but border objects stop you from leaving a tile, only one loop is needed
for(var/obj/obstacle in mover.loc)
if(!obstacle.CheckExit(mover, src) && obstacle != mover && obstacle != forget)
// This as anything looks odd, since we check istype shortly after, but it's so we can save an istype check for items, which are far more common than other objects.
for(var/obj/obstacle as anything in mover.loc)
if(isitem(obstacle) || !istype(obstacle) || obstacle == mover || obstacle == forget)
continue
if(!obstacle.CheckExit(mover, src))
mover.Bump(obstacle, TRUE)
return FALSE
var/list/large_dense = list()
//Next, check objects to block entry that are on the border
for(var/atom/movable/border_obstacle in src)
// Next, check for border obstacles on this turf
// Everyting inside a turf is an atom/movable.
for(var/atom/movable/border_obstacle as anything in src)
if(isitem(border_obstacle) || border_obstacle == forget || isnull(border_obstacle))
continue
if(border_obstacle.flags & ON_BORDER)
if(!border_obstacle.CanPass(mover, mover.loc, 1) && (forget != border_obstacle))
if(!border_obstacle.CanPass(mover, mover.loc, 1))
mover.Bump(border_obstacle, TRUE)
return FALSE
else
@@ -215,14 +221,15 @@
mover.Bump(src, TRUE)
return FALSE
//Finally, check objects/mobs to block entry that are not on the border
// Finally, check objects/mobs that block entry and are not on the border
var/atom/movable/tompost_bump
var/top_layer = FALSE
for(var/atom/movable/obstacle in large_dense)
if(!obstacle.CanPass(mover, mover.loc, 1) && (forget != obstacle))
if(obstacle.layer > top_layer)
tompost_bump = obstacle
top_layer = obstacle.layer
for(var/atom/movable/obstacle as anything in large_dense)
if(obstacle.layer <= top_layer)
continue
if(!obstacle.CanPass(mover, mover.loc, 1))
tompost_bump = obstacle
top_layer = obstacle.layer
if(tompost_bump)
mover.Bump(tompost_bump, TRUE)
return FALSE
@@ -12,9 +12,14 @@
/datum/pipeline/Destroy()
SSair.pipenets -= src
var/datum/gas_mixture/ghost = null
if(air && air.volume)
temporarily_store_air()
ghost = air
air = null
for(var/obj/machinery/atmospherics/pipe/P in members)
if(QDELETED(P))
continue
P.ghost_pipeline = ghost
P.parent = null
for(var/obj/machinery/atmospherics/A in other_atmosmch)
A.nullifyPipenet(src)
@@ -28,13 +33,14 @@
/datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/base)
var/volume = 0
var/list/ghost_pipelines = list()
if(istype(base, /obj/machinery/atmospherics/pipe))
var/obj/machinery/atmospherics/pipe/E = base
volume = E.volume
members += E
if(E.air_temporary)
air = E.air_temporary
E.air_temporary = null
if(E.ghost_pipeline)
ghost_pipelines[E.ghost_pipeline] = E.volume
E.ghost_pipeline = null
else
addMachineryMember(base)
if(!air)
@@ -59,15 +65,26 @@
volume += item.volume
item.parent = src
if(item.air_temporary)
air.merge(item.air_temporary)
item.air_temporary = null
if(item.ghost_pipeline)
if(!ghost_pipelines[item.ghost_pipeline])
ghost_pipelines[item.ghost_pipeline] = item.volume
else
ghost_pipelines[item.ghost_pipeline] += item.volume
item.ghost_pipeline = null
else
P.setPipenet(src, borderline)
addMachineryMember(P)
possible_expansions -= borderline
for(var/datum/gas_mixture/ghost in ghost_pipelines)
var/collected_ghost_volume = ghost_pipelines[ghost]
var/collected_fraction = collected_ghost_volume / ghost.volume
var/datum/gas_mixture/ghost_copy = new()
ghost_copy.copy_from(ghost)
air.merge(ghost_copy.remove_ratio(collected_fraction))
air.volume = volume
/datum/pipeline/proc/addMachineryMember(obj/machinery/atmospherics/A)
@@ -114,22 +131,6 @@
/obj/machinery/atmospherics/pipe/addMember(obj/machinery/atmospherics/A)
parent.addMember(A, src)
/datum/pipeline/proc/temporarily_store_air()
//Update individual gas_mixtures by volume ratio
for(var/obj/machinery/atmospherics/pipe/member in members)
member.air_temporary = new
member.air_temporary.volume = member.volume
member.air_temporary.set_oxygen(air.oxygen() * member.volume / air.volume)
member.air_temporary.set_nitrogen(air.nitrogen() * member.volume / air.volume)
member.air_temporary.set_toxins(air.toxins() * member.volume / air.volume)
member.air_temporary.set_carbon_dioxide(air.carbon_dioxide() * member.volume / air.volume)
member.air_temporary.set_sleeping_agent(air.sleeping_agent() * member.volume / air.volume)
member.air_temporary.set_agent_b(air.agent_b() * member.volume / air.volume)
member.air_temporary.set_temperature(air.temperature())
/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity)
var/datum/milla_safe/pipeline_temperature_interact/milla = new()
milla.invoke_async(src, target, share_volume, thermal_conductivity)
@@ -1,5 +1,5 @@
/obj/machinery/atmospherics/pipe
var/datum/gas_mixture/air_temporary //used when reconstructing a pipeline that broke
var/datum/gas_mixture/ghost_pipeline // used when reconstructing a pipeline that broke
var/datum/pipeline/parent
var/volume = 0
force = 20
@@ -23,7 +23,10 @@
/obj/machinery/atmospherics/pipe/Destroy()
var/turf/T = get_turf(src)
T.blind_release_air(air_temporary)
if(ghost_pipeline)
var/datum/gas_mixture/ghost_copy = new()
ghost_copy.copy_from(ghost_pipeline)
T.blind_release_air(ghost_copy.remove(volume / ghost_pipeline.volume))
for(var/obj/machinery/atmospherics/meter/meter in T)
if(meter.target == src)