Proximity sensing refactor (#26260)

* New proximity monitor datum

* Replace the old systems

* Fixes #26254

* Ports a New and spawn to Initialize

* Switch to Moved

* Remove unused var

* Speedup and fixes

* More speed

* qdel in movable

* Uneeded now

* Fix

* Use the faster RANGE_TURFS
This commit is contained in:
Cyberboss
2017-04-16 16:48:29 -04:00
committed by duncathan salt
parent 7dcfe586ea
commit 4f14ca7a49
12 changed files with 160 additions and 144 deletions

View File

@@ -1137,46 +1137,6 @@ B --><-- A
if(location == src) if(location == src)
return 1 return 1
/proc/add_to_proximity_list(atom/A, range)
var/turf/T = get_turf(A)
if(!T || !A.loc)
throw EXCEPTION("Someone adding a prox sensor in nullspace")
var/list/L = block(locate(T.x - range, T.y - range, T.z), locate(T.x + range, T.y + range, T.z))
for(var/B in L)
var/turf/C = B
LAZYINITLIST(C.proximity_checkers)
C.proximity_checkers[A] = TRUE
return L
/proc/remove_from_proximity_list(atom/A, range, oldloc = null)
var/turf/T = get_turf(oldloc ? oldloc : A)
var/list/L = block(locate(T.x - range, T.y - range, T.z), locate(T.x + range, T.y + range, T.z))
for(var/B in L)
var/turf/C = B
if (!C.proximity_checkers)
continue
C.proximity_checkers.Remove(A)
/proc/shift_proximity(atom/checker, atom/A, range, atom/B, newrange)
var/turf/T = get_turf(A)
var/turf/Q = get_turf(B)
if(T == Q && range == newrange)
return 0
var/list/L = block(locate(T.x - range, T.y - range, T.z), locate(T.x + range, T.y + range, T.z))
var/list/M = block(locate(Q.x - newrange, Q.y - newrange, Q.z), locate(Q.x + newrange, Q.y + newrange, Q.z))
var/list/N = L - M
var/list/O = M - L
for(var/C in N)
var/turf/D = C
if (!D.proximity_checkers)
continue
D.proximity_checkers.Remove(checker)
for(var/E in O)
var/turf/F = E
LAZYINITLIST(F.proximity_checkers)
F.proximity_checkers[checker] = TRUE
return 1
/proc/flick_overlay_static(image/I, atom/A, duration) /proc/flick_overlay_static(image/I, atom/A, duration)
set waitfor = 0 set waitfor = 0
if(!A || !I) if(!A || !I)

View File

@@ -28,6 +28,8 @@
var/list/our_overlays //our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate var/list/our_overlays //our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
var/datum/proximity_monitor/proximity_monitor
/atom/New(loc, ...) /atom/New(loc, ...)
//atom creation method that preloads variables at creation //atom creation method that preloads variables at creation
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New() if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()

View File

@@ -121,6 +121,10 @@
if(flags & CLEAN_ON_MOVE) if(flags & CLEAN_ON_MOVE)
clean_on_move() clean_on_move()
var/datum/proximity_monitor/pc = proximity_monitor
if(pc)
pc.HandleMove()
return 1 return 1
/atom/movable/proc/clean_on_move() /atom/movable/proc/clean_on_move()
@@ -171,6 +175,8 @@
if(stationloving && force) if(stationloving && force)
STOP_PROCESSING(SSinbounds, src) STOP_PROCESSING(SSinbounds, src)
QDEL_NULL(proximity_monitor)
. = ..() . = ..()
if(loc) if(loc)

View File

@@ -46,7 +46,8 @@
assembly.state = 4 assembly.state = 4
GLOB.cameranet.cameras += src GLOB.cameranet.cameras += src
GLOB.cameranet.addCamera(src) GLOB.cameranet.addCamera(src)
add_to_proximity_list(src, 1) //1 was default of everything proximity_monitor = new(src, 1)
/* // Use this to look for cameras that have the same c_tag. /* // Use this to look for cameras that have the same c_tag.
for(var/obj/machinery/camera/C in cameranet.cameras) for(var/obj/machinery/camera/C in cameranet.cameras)
var/list/tempnetwork = C.network&src.network var/list/tempnetwork = C.network&src.network
@@ -59,13 +60,8 @@
if(mapload && z == 1 && prob(3) && !start_active) if(mapload && z == 1 && prob(3) && !start_active)
toggle_cam() toggle_cam()
/obj/machinery/camera/Move()
remove_from_proximity_list(src, 1)
return ..()
/obj/machinery/camera/Destroy() /obj/machinery/camera/Destroy()
toggle_cam(null, 0) //kick anyone viewing out toggle_cam(null, 0) //kick anyone viewing out
remove_from_proximity_list(src, 1)
if(assembly) if(assembly)
qdel(assembly) qdel(assembly)
assembly = null assembly = null

View File

@@ -154,6 +154,10 @@
new /obj/item/stack/sheet/metal (loc, 2) new /obj/item/stack/sheet/metal (loc, 2)
qdel(src) qdel(src)
/obj/machinery/flasher/portable/Initialize()
. = ..()
proximity_monitor = new(src, 0)
/obj/machinery/flasher/portable/HasProximity(atom/movable/AM) /obj/machinery/flasher/portable/HasProximity(atom/movable/AM)
if (last_flash && world.time < last_flash + 150) if (last_flash && world.time < last_flash + 150)
return return
@@ -172,25 +176,17 @@
add_overlay("[base_state]-s") add_overlay("[base_state]-s")
anchored = 1 anchored = 1
power_change() power_change()
add_to_proximity_list(src, range) proximity_monitor.SetRange(range)
else else
to_chat(user, "<span class='notice'>[src] can now be moved.</span>") to_chat(user, "<span class='notice'>[src] can now be moved.</span>")
cut_overlays() cut_overlays()
anchored = 0 anchored = 0
power_change() power_change()
remove_from_proximity_list(src, range) proximity_monitor.SetRange(0)
else else
return ..() return ..()
/obj/machinery/flasher/portable/Destroy()
remove_from_proximity_list(src, range)
return ..()
/obj/machinery/flasher/portable/Moved(oldloc)
remove_from_proximity_list(oldloc, range)
return ..()
/obj/item/wallframe/flasher /obj/item/wallframe/flasher
name = "mounted flash frame" name = "mounted flash frame"
desc = "Used for building wall-mounted flashers." desc = "Used for building wall-mounted flashers."

View File

@@ -23,6 +23,12 @@
/obj/effect/blob_act() /obj/effect/blob_act()
return return
/obj/effect/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
return 0
/obj/effect/experience_pressure_difference()
return
/obj/effect/ex_act(severity, target) /obj/effect/ex_act(severity, target)
if(target == src) if(target == src)
qdel(src) qdel(src)
@@ -37,12 +43,15 @@
if(prob(25)) if(prob(25))
qdel(src) qdel(src)
/obj/effect/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
return 0
/obj/effect/experience_pressure_difference()
return
/obj/effect/singularity_act() /obj/effect/singularity_act()
qdel(src) qdel(src)
return 0 return 0
/obj/effect/abstract/ex_act(severity, target)
return
/obj/effect/abstract/singularity_pull()
return
/obj/effect/abstract/singularity_act()
return

View File

@@ -0,0 +1,97 @@
/datum/proximity_monitor
var/atom/host //the atom we are tracking
var/atom/last_host_loc
var/list/checkers //list of /obj/effect/abstract/proximity_checkers
var/current_range
var/ignore_if_not_on_turf //don't check turfs in range if the host's loc isn't a turf
/datum/proximity_monitor/New(atom/_host, range, _ignore_if_not_on_turf = TRUE)
host = _host
last_host_loc = _host.loc
ignore_if_not_on_turf = _ignore_if_not_on_turf
SetRange(range)
/datum/proximity_monitor/Destroy()
host = null
QDEL_LIST(checkers)
return ..()
/datum/proximity_monitor/proc/HandleMove()
var/atom/_host = host
var/atom/new_host_loc = _host.loc
if(last_host_loc != new_host_loc)
last_host_loc = new_host_loc //hopefully this won't cause GC issues with containers
var/curr_range = current_range
SetRange(curr_range, TRUE)
if(curr_range)
testing("HasProx: [host] -> [host]")
_host.HasProximity(host) //if we are processing, we're guaranteed to be a movable
/datum/proximity_monitor/proc/SetRange(range, force_rebuild = FALSE)
if(!force_rebuild && range == current_range)
return FALSE
. = TRUE
current_range = range
var/list/old_checkers = checkers
var/old_checkers_len = LAZYLEN(old_checkers)
var/atom/host_loc = host.loc
var/atom/loc_to_use = ignore_if_not_on_turf ? host_loc : get_turf(host)
if(!isturf(loc_to_use)) //only check the host's loc
if(range)
var/obj/effect/abstract/proximity_checker/pc
if(old_checkers_len)
pc = old_checkers[old_checkers_len]
--old_checkers.len
else
pc = new(host_loc, src)
checkers = list(pc) //only check the host's loc
return
var/list/turfs = RANGE_TURFS(range, loc_to_use)
var/old_checkers_used = min(turfs.len, old_checkers_len)
//reuse what we can
for(var/I in 1 to old_checkers_len)
if(I <= old_checkers_used)
var/obj/effect/abstract/proximity_checker/pc = old_checkers[I]
pc.loc = turfs[I]
else
qdel(old_checkers[I]) //delete the leftovers
LAZYCLEARLIST(old_checkers)
//create what we lack
var/list/checkers_local = list()
for(var/I in (old_checkers_used + 1) to turfs.len)
checkers_local += new /obj/effect/abstract/proximity_checker(turfs[I], src)
checkers = checkers_local
/obj/effect/abstract/proximity_checker
var/datum/proximity_monitor/monitor
/obj/effect/abstract/proximity_checker/Initialize(mapload, datum/proximity_monitor/_monitor)
. = ..()
if(_monitor)
monitor = _monitor
else
stack_trace("proximity_checker created without proximity_monitor")
qdel(src)
/obj/effect/abstract/proximity_checker/Destroy()
monitor = null
return ..()
/obj/effect/abstract/proximity_checker/Crossed(atom/movable/AM)
set waitfor = FALSE
var/datum/proximity_monitor/M = monitor
if(!M.current_range)
return
var/atom/H = M.host
testing("HasProx: [H] -> [AM]")
H.HasProximity(AM)

View File

@@ -227,7 +227,6 @@
layer = MOB_LAYER layer = MOB_LAYER
var/obj/item/clothing/mask/facehugger/child var/obj/item/clothing/mask/facehugger/child
/obj/structure/alien/egg/Initialize(mapload) /obj/structure/alien/egg/Initialize(mapload)
..() ..()
update_icon() update_icon()
@@ -235,15 +234,10 @@
child = new(src) child = new(src)
if(status == GROWING) if(status == GROWING)
addtimer(CALLBACK(src, .proc/Grow), rand(MIN_GROWTH_TIME, MAX_GROWTH_TIME)) addtimer(CALLBACK(src, .proc/Grow), rand(MIN_GROWTH_TIME, MAX_GROWTH_TIME))
if(status == GROWN) proximity_monitor = new(src, status == GROWN ? 1 : 0)
add_to_proximity_list(src, 1)
if(status == BURST) if(status == BURST)
obj_integrity = integrity_failure obj_integrity = integrity_failure
/obj/structure/alien/egg/Destroy()
remove_from_proximity_list(src, 1)
. = ..()
/obj/structure/alien/egg/update_icon() /obj/structure/alien/egg/update_icon()
..() ..()
switch(status) switch(status)
@@ -283,12 +277,12 @@
/obj/structure/alien/egg/proc/Grow() /obj/structure/alien/egg/proc/Grow()
status = GROWN status = GROWN
update_icon() update_icon()
add_to_proximity_list(src, 1) proximity_monitor.SetRange(1)
//drops and kills the hugger if any is remaining //drops and kills the hugger if any is remaining
/obj/structure/alien/egg/proc/Burst(kill = TRUE) /obj/structure/alien/egg/proc/Burst(kill = TRUE)
if(status == GROWN || status == GROWING) if(status == GROWN || status == GROWING)
remove_from_proximity_list(src, 1) proximity_monitor.SetRange(0)
status = BURST status = BURST
update_icon() update_icon()
flick("egg_opening", src) flick("egg_opening", src)
@@ -307,12 +301,6 @@
child.Attach(M) child.Attach(M)
break break
/obj/structure/alien/egg/Moved(oldloc)
remove_from_proximity_list(oldloc, 1)
if(status == GROWN)
add_to_proximity_list(src, 1)
return ..()
/obj/structure/alien/egg/obj_break(damage_flag) /obj/structure/alien/egg/obj_break(damage_flag)
if(!(flags & NODECONSTRUCT)) if(!(flags & NODECONSTRUCT))
if(status != BURST) if(status != BURST)

View File

@@ -13,8 +13,6 @@
flags = CAN_BE_DIRTY flags = CAN_BE_DIRTY
var/list/proximity_checkers
var/image/obscured //camerachunks var/image/obscured //camerachunks
var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes
@@ -156,10 +154,6 @@
return 1 //Nothing found to block so return success! return 1 //Nothing found to block so return success!
/turf/Entered(atom/movable/AM) /turf/Entered(atom/movable/AM)
for(var/A in proximity_checkers)
var/atom/B = A
B.HasProximity(AM)
if(explosion_level && AM.ex_check(explosion_id)) if(explosion_level && AM.ex_check(explosion_id))
AM.ex_act(explosion_level) AM.ex_act(explosion_level)

View File

@@ -10,8 +10,6 @@
var/timing = 0 var/timing = 0
var/time = 10 var/time = 10
var/sensitivity = 1 var/sensitivity = 1
var/atom/oldloc
var/list/turfs_around = list()
/obj/item/device/assembly/prox_sensor/proc/toggle_scan() /obj/item/device/assembly/prox_sensor/proc/toggle_scan()
@@ -19,22 +17,15 @@
/obj/item/device/assembly/prox_sensor/proc/sense() /obj/item/device/assembly/prox_sensor/proc/sense()
/obj/item/device/assembly/prox_sensor/New() /obj/item/device/assembly/prox_sensor/Initialize()
..() . = ..()
START_PROCESSING(SSobj, src) proximity_monitor = new(src, 0)
oldloc = loc
/obj/item/device/assembly/prox_sensor/describe() /obj/item/device/assembly/prox_sensor/describe()
if(timing) if(timing)
return "<span class='notice'>The proximity sensor is arming.</span>" return "<span class='notice'>The proximity sensor is arming.</span>"
return "The proximity sensor is [scanning?"armed":"disarmed"]." return "The proximity sensor is [scanning?"armed":"disarmed"]."
/obj/item/device/assembly/prox_sensor/on_attach(datum/wires/w)
handle_move(w.holder)
/obj/item/device/assembly/prox_sensor/on_detach(datum/wires/w)
handle_move(w.holder.loc)
/obj/item/device/assembly/prox_sensor/activate() /obj/item/device/assembly/prox_sensor/activate()
if(!..()) if(!..())
return 0//Cooldown check return 0//Cooldown check
@@ -42,12 +33,15 @@
update_icon() update_icon()
return 1 return 1
/obj/item/device/assembly/prox_sensor/toggle_secure() /obj/item/device/assembly/prox_sensor/toggle_secure()
secured = !secured secured = !secured
if(!secured) if(!secured)
scanning = 0 if(scanning)
toggle_scan()
proximity_monitor.host = src
timing = 0 timing = 0
else
proximity_monitor.host = loc
update_icon() update_icon()
return secured return secured
@@ -73,36 +67,19 @@
timing = 0 timing = 0
toggle_scan(1) toggle_scan(1)
time = initial(time) time = initial(time)
handle_move(loc)
/obj/item/device/assembly/prox_sensor/dropped()
..()
if(scanning)
INVOKE_ASYNC(src, .proc/sense)
/obj/item/device/assembly/prox_sensor/Destroy()
if(scanning)
remove_from_proximity_list(src, sensitivity, oldloc)
return ..()
/obj/item/device/assembly/prox_sensor/toggle_scan(scan) /obj/item/device/assembly/prox_sensor/toggle_scan(scan)
if(!secured) if(!secured)
return 0 return 0
scanning = scan scanning = scan
if(scanning) proximity_monitor.SetRange(scanning ? sensitivity : 0)
add_to_proximity_list(src, sensitivity)
else
remove_from_proximity_list(src, sensitivity)
oldloc = get_turf(loc)
update_icon() update_icon()
/obj/item/device/assembly/prox_sensor/proc/sensitivity_change(value) /obj/item/device/assembly/prox_sensor/proc/sensitivity_change(value)
var/sense = min(max(sensitivity + value, 0), 5) var/sense = min(max(sensitivity + value, 0), 5)
if(scanning)
if(shift_proximity(src, oldloc, sensitivity, loc, sense))
sense()
oldloc = loc
sensitivity = sense sensitivity = sense
if(scanning && proximity_monitor.SetRange(sense))
sense()
/obj/item/device/assembly/prox_sensor/update_icon() /obj/item/device/assembly/prox_sensor/update_icon()
cut_overlays() cut_overlays()
@@ -117,17 +94,6 @@
holder.update_icon() holder.update_icon()
return return
/obj/item/device/assembly/prox_sensor/proc/handle_move(atom/newloc)
if(scanning)
if(shift_proximity(src, oldloc, sensitivity, newloc, sensitivity) || newloc != oldloc)
sense()
oldloc = newloc
/obj/item/device/assembly/prox_sensor/Moved()
..()
handle_move(loc)
/obj/item/device/assembly/prox_sensor/interact(mob/user)//TODO: Change this to the wires thingy /obj/item/device/assembly/prox_sensor/interact(mob/user)//TODO: Change this to the wires thingy
if(is_secured(user)) if(is_secured(user))
var/second = time % 60 var/second = time % 60

View File

@@ -10,14 +10,13 @@
var/machinedir = SOUTHEAST var/machinedir = SOUTHEAST
speed_process = 1 speed_process = 1
/obj/machinery/mineral/stacking_unit_console/New() /obj/machinery/mineral/stacking_unit_console/Initialize()
..() . = ..()
spawn(7) machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
src.machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir)) if (machine)
if (machine) machine.CONSOLE = src
machine.CONSOLE = src else
else qdel(src)
qdel(src)
/obj/machinery/mineral/stacking_unit_console/attack_hand(mob/user) /obj/machinery/mineral/stacking_unit_console/attack_hand(mob/user)
@@ -71,6 +70,14 @@
input_dir = EAST input_dir = EAST
output_dir = WEST output_dir = WEST
/obj/machinery/mineral/stacking_machine/Initialize()
. = ..()
proximity_monitor = new(src, 1)
/obj/machinery/mineral/stacking_machine/HasProximity(atom/movable/AM)
if(istype(AM, /obj/item/stack/sheet) && AM.loc == get_step(src, input_dir))
process_sheet(AM)
/obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/inp) /obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/inp)
if(!(inp.type in stack_list)) //It's the first of this sheet added if(!(inp.type in stack_list)) //It's the first of this sheet added
var/obj/item/stack/sheet/s = new inp.type(src,0) var/obj/item/stack/sheet/s = new inp.type(src,0)
@@ -83,10 +90,4 @@
var/obj/item/stack/sheet/out = new inp.type() var/obj/item/stack/sheet/out = new inp.type()
out.amount = stack_amt out.amount = stack_amt
unload_mineral(out) unload_mineral(out)
storage.amount -= stack_amt storage.amount -= stack_amt
/obj/machinery/mineral/stacking_machine/process()
var/turf/T = get_step(src, input_dir)
if(T)
for(var/obj/item/stack/sheet/S in T)
process_sheet(S)

View File

@@ -656,6 +656,7 @@
#include "code\game\objects\effects\mines.dm" #include "code\game\objects\effects\mines.dm"
#include "code\game\objects\effects\misc.dm" #include "code\game\objects\effects\misc.dm"
#include "code\game\objects\effects\overlays.dm" #include "code\game\objects\effects\overlays.dm"
#include "code\game\objects\effects\proximity.dm"
#include "code\game\objects\effects\portals.dm" #include "code\game\objects\effects\portals.dm"
#include "code\game\objects\effects\spiders.dm" #include "code\game\objects\effects\spiders.dm"
#include "code\game\objects\effects\step_triggers.dm" #include "code\game\objects\effects\step_triggers.dm"