Files
Aurora.3/code/modules/mob/abstract/freelook/chunk.dm

192 lines
5.1 KiB
Plaintext

#define UPDATE_BUFFER 25 // 2.5 seconds
// CHUNK
//
// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed.
// Allows the Eye to stream these chunks and know what it can and cannot see.
/datum/obfuscation
var/icon = 'icons/effects/cameravis.dmi'
var/icon_state = "black"
var/list/obfuscation_images = list()
var/static/icon/obfuscation_underlay
// There is an exploit were clients can memory-edit their local version of the static images, allowing them to see everything. This is a minor attempt to make that more difficult.
/datum/obfuscation/Destroy()
obfuscation_images.Cut()
. = ..()
/datum/obfuscation/proc/has_obfuscation(var/turf/T)
return !isnull(obfuscation_images[T])
/datum/obfuscation/proc/get_obfuscation(var/turf/T)
var/image/obfuscation = obfuscation_images[T]
if(!obfuscation)
obfuscation = image(icon, T, icon_state)
obfuscation.layer = OBFUSCATION_LAYER
if(!obfuscation_underlay)
// Creating a new icon of a fairly common icon state, adding some random color to prevent address searching, and hoping being static kills memory locality
var/turf/floor = /turf/simulated/floor/tiled
obfuscation_underlay = icon(initial(floor.icon), initial(floor.icon_state))
obfuscation_underlay.Blend(rgb(rand(0,255),rand(0,255),rand(0,255)))
obfuscation.underlays += obfuscation_underlay
obfuscation_images[T] = obfuscation
return obfuscation
/datum/chunk
var/datum/visualnet/visualnet
var/list/obscuredTurfs = list()
var/list/visibleTurfs = list()
var/list/obscured = list()
var/list/turfs = list()
var/list/seenby = list()
var/list/sources = list()
var/dirty = FALSE
var/updating = FALSE
var/x = 0
var/y = 0
var/z = 0
var/datum/obfuscation/obfuscation = new()
// Create a new camera chunk, since the chunks are made as they are needed.
/datum/chunk/New(var/datum/visualnet/visualnet, x, y, z)
..()
src.visualnet = visualnet
// 0xf = 15
x &= ~0xf
y &= ~0xf
src.x = x
src.y = y
src.z = z
var/turf/center = locate(x + 8, y + 8, z)
for(var/turf/t in RANGE_TURFS(10, center))
if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16)
turfs[t] = t
add_sources(visualnet.sources)
acquire_visible_turfs(visibleTurfs)
// Removes turf that isn't in turfs.
visibleTurfs &= turfs
obscuredTurfs = turfs - visibleTurfs
for(var/turf in obscuredTurfs)
var/turf/t = turf
obscured += obfuscation.get_obfuscation(t)
/datum/chunk/Destroy()
visualnet = null
. = ..()
/datum/chunk/proc/add_sources(var/list/sources)
var/turf/center = locate(x + 8, y + 8, z)
for(var/entry in sources)
var/atom/A = entry
if(get_dist(get_turf(A), center) > 16)
continue
add_source(A)
// The visualnet checks if a source already exists or not, as appropriate, before calling add/remove_source on the chunk
/datum/chunk/proc/add_source(var/atom/source)
if(source in sources)
return FALSE
sources += source
visibility_changed()
return TRUE
/datum/chunk/proc/remove_source(var/atom/source)
if(sources.Remove(source))
visibility_changed()
return TRUE
return FALSE
// Visualnet adds and removes eyes.
/datum/chunk/proc/add_eye(mob/abstract/eye/eye)
seenby += eye
eye.visibleChunks += src
if(eye.owner && eye.owner.client)
eye.owner.client.images += obscured
/datum/chunk/proc/remove_eye(mob/abstract/eye/eye)
seenby -= eye
eye.visibleChunks -= src
if(eye.owner && eye.owner.client)
eye.owner.client.images -= obscured
// Updates the chunk, makes sure that it doesn't update too much. If the chunk isn't being watched it will
// instead be flagged to update the next time an AI Eye moves near it.
/datum/chunk/proc/visibility_changed(var/update_now = FALSE)
if(update_now)
update(TRUE)
return
if(updating)
return
if(seenby.len)
updating = TRUE
addtimer(CALLBACK(src, .proc/update), UPDATE_BUFFER)
else
dirty = TRUE
// The actual updating.
/datum/chunk/proc/update(var/forced = FALSE)
if(!updating && !forced)
return
var/list/newVisibleTurfs = new()
acquire_visible_turfs(newVisibleTurfs)
// Removes turf that isn't in turfs.
newVisibleTurfs &= turfs
var/list/visAdded = newVisibleTurfs - visibleTurfs
var/list/visRemoved = visibleTurfs - newVisibleTurfs
visibleTurfs = newVisibleTurfs
obscuredTurfs = turfs - newVisibleTurfs
for(var/turf in visAdded)
var/turf/t = turf
if(obfuscation.has_obfuscation(t))
var/image/obfuscation_image = obfuscation.get_obfuscation(t)
obscured -= obfuscation_image
for(var/eye in seenby)
var/mob/abstract/eye/m = eye
if (m && m.owner && m.owner.client)
m.owner.client.images -= obfuscation_image
for(var/turf in visRemoved)
var/turf/t = turf
if(obscuredTurfs[t])
var/image/obfuscation_image = obfuscation.get_obfuscation(t)
obscured += obfuscation_image
for(var/eye in seenby)
var/mob/abstract/eye/m = eye
if (m && m.owner && m.owner.client)
m.owner.client.images += obfuscation_image
dirty = FALSE
updating = FALSE
/datum/chunk/proc/acquire_visible_turfs(var/list/visible)
return
/proc/seen_turfs_in_range(var/source, var/range)
var/turf/pos = get_turf(source)
if(pos)
. = hear(range, pos)
else
. = list()
#undef UPDATE_BUFFER