mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-19 00:46:37 +01:00
71 lines
2.2 KiB
Plaintext
71 lines
2.2 KiB
Plaintext
//* This file is explicitly licensed under the MIT license. *//
|
|
//* Copyright (c) 2024 Citadel Station Developers *//
|
|
|
|
/**
|
|
* registers a /movable in a spatial grid
|
|
*/
|
|
/datum/component/spatial_grid
|
|
dupe_mode = COMPONENT_DUPE_SELECTIVE
|
|
registered_type = /datum/component/spatial_grid
|
|
/// target spatial grid
|
|
var/datum/spatial_grid/grid
|
|
/// target grid width
|
|
var/grid_width
|
|
/// last grid index
|
|
var/current_index
|
|
|
|
/datum/component/spatial_grid/Initialize(datum/spatial_grid/grid)
|
|
. = ..()
|
|
if(. == COMPONENT_INCOMPATIBLE)
|
|
return
|
|
if(!ismovable(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
if(!grid)
|
|
CRASH("attempted to make a spatial grid component without a grid ref")
|
|
|
|
src.grid = grid
|
|
src.grid_width = grid.width
|
|
|
|
/datum/component/spatial_grid/RegisterWithParent()
|
|
construct()
|
|
|
|
/datum/component/spatial_grid/UnregisterFromParent()
|
|
teardown()
|
|
|
|
/datum/component/spatial_grid/CheckDupeComponent(datum/component/C, datum/spatial_grid/grid)
|
|
return grid != src.grid
|
|
|
|
/datum/component/spatial_grid/proc/construct(atom/root = parent)
|
|
while(ismovable(root))
|
|
RegisterSignal(root, COMSIG_MOVABLE_MOVED, PROC_REF(update))
|
|
root = root.loc
|
|
if(isturf(root))
|
|
var/idx = ceil(root.x / TURF_CHUNK_RESOLUTION) + grid_width * (ceil(root.y / TURF_CHUNK_RESOLUTION) - 1)
|
|
grid.direct_insert(parent, root.z, idx)
|
|
current_index = idx
|
|
|
|
/datum/component/spatial_grid/proc/teardown(atom/root = parent)
|
|
while(ismovable(root))
|
|
UnregisterSignal(root, COMSIG_MOVABLE_MOVED)
|
|
root = root.loc
|
|
if(isturf(root))
|
|
grid.direct_remove(parent, root.z, current_index)
|
|
current_index = null
|
|
|
|
/datum/component/spatial_grid/proc/update(atom/movable/source, atom/oldloc)
|
|
var/atom/newloc = source.loc
|
|
if(newloc == oldloc)
|
|
return
|
|
// turf --> turf, try to do an optimized, lazy update
|
|
if(isturf(oldloc) && isturf(newloc) && (oldloc.z == newloc.z))
|
|
var/new_index = ceil(newloc.x / TURF_CHUNK_RESOLUTION) + grid_width * (ceil(newloc.y / TURF_CHUNK_RESOLUTION) - 1)
|
|
var/z = oldloc.z
|
|
if(new_index != current_index)
|
|
grid.direct_remove(parent, z, current_index)
|
|
grid.direct_insert(parent, z, new_index)
|
|
current_index = new_index
|
|
// turf --> somewhere else or somewhere else --> turf or somewhere else --> somewhere else, do full cycle
|
|
else
|
|
teardown(oldloc)
|
|
construct(newloc)
|