[MIRROR] (i found some cigs) touches up cameranet code and makes it add only one vis_contents to all turfs for static (adding and removing when ai moves in/out of chunk gone) (#5785)

* Touches up cameranet code (#59165)

makes it add only one vis_contents to all turfs for static (adding and removing when ai moves in/out of chunk gone)

original pr: #58522
basically the same but ai's moving in/out of the chunk doesnt affect vis_contents anymore because that was really racking up tidi for some reason.
Why It's Good For The Game

less maptick because theres only 1 vis_contents added instead of 2 and general optimizations to cameranet code

* (i found some cigs) touches up cameranet code and makes it add only one vis_contents to all turfs for static (adding and removing when ai moves in/out of chunk gone)

Co-authored-by: Kylerace <kylerlumpkin1@gmail.com>
This commit is contained in:
SkyratBot
2021-05-19 14:17:25 +01:00
committed by GitHub
co-authored by Kylerace
parent 0c7315a7cd
commit 2c7daa751d
9 changed files with 94 additions and 141 deletions
+1 -1
View File
@@ -1021,7 +1021,7 @@
target_ai = src //cheat! just give... ourselves as the spawned AI, because that's technically correct
/mob/living/silicon/ai/proc/camera_visibility(mob/camera/ai_eye/moved_eye)
GLOB.cameranet.visibility(moved_eye, client, all_eyes, USE_STATIC_OPAQUE)
GLOB.cameranet.visibility(moved_eye, client, all_eyes, TRUE)
/mob/living/silicon/ai/forceMove(atom/destination)
. = ..()
@@ -18,26 +18,19 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
// The object used for the clickable stat() button.
var/obj/effect/statclick/statclick
// The objects used in vis_contents of obscured turfs
var/list/vis_contents_objects
///this object is the static that ais see on obscured turfs, added to the turfs vis_contents
var/obj/effect/overlay/camera_static/vis_contents_opaque
var/obj/effect/overlay/camera_static/vis_contents_transparent
// The image given to the effect in vis_contents on AI clients
///The image given to the effect in vis_contents on AI clients
var/image/obscured
var/image/obscured_transparent
/datum/cameranet/New()
vis_contents_opaque = new /obj/effect/overlay/camera_static()
vis_contents_transparent = new /obj/effect/overlay/camera_static/transparent()
vis_contents_objects = list(vis_contents_opaque, vis_contents_transparent)
obscured = new('icons/effects/cameravis.dmi', vis_contents_opaque, null)
obscured.plane = CAMERA_STATIC_PLANE
obscured_transparent = new('icons/effects/cameravis.dmi', vis_contents_transparent, null)
obscured_transparent.plane = CAMERA_STATIC_PLANE
// Checks if a chunk has been Generated in x, y, z.
/// Checks if a chunk has been Generated in x, y, z.
/datum/cameranet/proc/chunkGenerated(x, y, z)
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
@@ -53,9 +46,8 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
if(!.)
chunks[key] = . = new /datum/camerachunk(x, y, z)
// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
/datum/cameranet/proc/visibility(list/moved_eyes, client/C, list/other_eyes, use_static = USE_STATIC_OPAQUE)
/// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
/datum/cameranet/proc/visibility(list/moved_eyes, client/C, list/other_eyes, use_static = TRUE)
if(!islist(moved_eyes))
moved_eyes = moved_eyes ? list(moved_eyes) : list()
if(islist(other_eyes))
@@ -63,15 +55,10 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
else
other_eyes = list()
if(C)
switch(use_static)
if(USE_STATIC_TRANSPARENT)
C.images += obscured_transparent
if(USE_STATIC_OPAQUE)
C.images += obscured
if(C && use_static)
C.images += obscured
for(var/V in moved_eyes)
var/mob/camera/ai_eye/eye = V
for(var/mob/camera/ai_eye/eye as anything in moved_eyes)
var/list/visibleChunks = list()
if(eye.loc)
// 0xf = 15
@@ -89,25 +76,18 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
var/list/remove = eye.visibleCameraChunks - visibleChunks
var/list/add = visibleChunks - eye.visibleCameraChunks
for(var/chunk in remove)
var/datum/camerachunk/c = chunk
c.remove(eye, FALSE)
for(var/datum/camerachunk/chunk as anything in remove)
chunk.remove(eye, FALSE)
for(var/chunk in add)
var/datum/camerachunk/c = chunk
c.add(eye)
for(var/datum/camerachunk/chunk as anything in add)
chunk.add(eye)
if(!eye.visibleCameraChunks.len)
var/client/client = eye.GetViewerClient()
if(client)
switch(eye.use_static)
if(USE_STATIC_TRANSPARENT)
client.images -= GLOB.cameranet.obscured_transparent
if(USE_STATIC_OPAQUE)
client.images -= GLOB.cameranet.obscured
// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
if(client && eye.use_static)
client.images -= obscured
/// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
/datum/cameranet/proc/updateVisibility(atom/A, opacity_check = 1)
if(!SSticker || (opacity_check && !A.opacity))
return
@@ -119,29 +99,27 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
return
chunk.hasChanged()
// Removes a camera from a chunk.
/// Removes a camera from a chunk.
/datum/cameranet/proc/removeCamera(obj/machinery/camera/c)
majorChunkChange(c, 0)
// Add a camera to a chunk.
/// Add a camera to a chunk.
/datum/cameranet/proc/addCamera(obj/machinery/camera/c)
if(c.can_use())
majorChunkChange(c, 1)
// Used for Cyborg cameras. Since portable cameras can be in ANY chunk.
/// Used for Cyborg cameras. Since portable cameras can be in ANY chunk.
/datum/cameranet/proc/updatePortableCamera(obj/machinery/camera/c)
if(c.can_use())
majorChunkChange(c, 1)
// Never access this proc directly!!!!
// This will update the chunk and all the surrounding chunks.
// It will also add the atom to the cameras list if you set the choice to 1.
// Setting the choice to 0 will remove the camera from the chunks.
// If you want to update the chunks around an object, without adding/removing a camera, use choice 2.
/**
* Never access this proc directly!!!!
* This will update the chunk and all the surrounding chunks.
* It will also add the atom to the cameras list if you set the choice to 1.
* Setting the choice to 0 will remove the camera from the chunks.
* If you want to update the chunks around an object, without adding/removing a camera, use choice 2.
*/
/datum/cameranet/proc/majorChunkChange(atom/c, choice)
if(!c)
return
@@ -164,8 +142,7 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
chunk.cameras |= c
chunk.hasChanged()
// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0.
/// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0.
/datum/cameranet/proc/checkCameraVis(mob/living/target)
var/turf/position = get_turf(target)
return checkTurfVis(position)
@@ -177,8 +154,8 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
if(chunk.changed)
chunk.hasChanged(1) // Update now, no matter if it's visible or not.
if(chunk.visibleTurfs[position])
return 1
return 0
return TRUE
return FALSE
/obj/effect/overlay/camera_static
name = "static"
@@ -192,6 +169,3 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
invisibility = INVISIBILITY_ABSTRACT
plane = CAMERA_STATIC_PLANE
/obj/effect/overlay/camera_static/transparent
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
@@ -1,4 +1,4 @@
#define UPDATE_BUFFER 25 // 2.5 seconds
#define UPDATE_BUFFER_TIME (2.5 SECONDS)
// CAMERA CHUNK
//
@@ -6,100 +6,90 @@
// Allows the AI Eye to stream these chunks and know what it can and cannot see.
/datum/camerachunk
///turfs our cameras cant see but are inside our grid
var/list/obscuredTurfs = list()
///turfs our cameras can see inside our grid
var/list/visibleTurfs = list()
///cameras that can see into our grid
var/list/cameras = list()
///list of all turfs
var/list/turfs = list()
///camera mobs that can see turfs in our grid
var/list/seenby = list()
var/changed = 0
var/changed = FALSE
var/x = 0
var/y = 0
var/z = 0
// Add an AI eye to the chunk, then update if changed.
/// Add an AI eye to the chunk, then update if changed.
/datum/camerachunk/proc/add(mob/camera/ai_eye/eye)
eye.visibleCameraChunks += src
seenby += eye
if(changed)
update()
// Remove an AI eye from the chunk, then update if changed.
/// Remove an AI eye from the chunk, then update if changed.
/datum/camerachunk/proc/remove(mob/camera/ai_eye/eye, remove_static_with_last_chunk = TRUE)
eye.visibleCameraChunks -= src
seenby -= eye
if(remove_static_with_last_chunk && !eye.visibleCameraChunks.len)
var/client/client = eye.GetViewerClient()
if(client)
switch(eye.use_static)
if(USE_STATIC_TRANSPARENT)
client.images -= GLOB.cameranet.obscured_transparent
if(USE_STATIC_OPAQUE)
client.images -= GLOB.cameranet.obscured
// Called when a chunk has changed. I.E: A wall was deleted.
if(client && eye.use_static)
client.images -= GLOB.cameranet.obscured
/// Called when a chunk has changed. I.E: A wall was deleted.
/datum/camerachunk/proc/visibilityChanged(turf/loc)
if(!visibleTurfs[loc])
return
hasChanged()
// 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.
/**
* 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/camerachunk/proc/hasChanged(update_now = 0)
if(seenby.len || update_now)
addtimer(CALLBACK(src, .proc/update), UPDATE_BUFFER, TIMER_UNIQUE)
addtimer(CALLBACK(src, .proc/update), UPDATE_BUFFER_TIME, TIMER_UNIQUE)
else
changed = 1
// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists.
changed = TRUE
/// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists.
/datum/camerachunk/proc/update()
var/list/newVisibleTurfs = list()
for(var/camera in cameras)
var/obj/machinery/camera/c = camera
if(!c)
continue
if(!c.can_use())
for(var/obj/machinery/camera/current_camera as anything in cameras)
if(!current_camera || !current_camera.can_use())
continue
var/turf/point = locate(src.x + (CHUNK_SIZE / 2), src.y + (CHUNK_SIZE / 2), src.z)
if(get_dist(point, c) > CHUNK_SIZE + (CHUNK_SIZE / 2))
if(get_dist(point, current_camera) > CHUNK_SIZE + (CHUNK_SIZE / 2))
continue
for(var/turf/t in c.can_see())
// Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards.
// List associations use a tree or hashmap of some sort (alongside the list itself)
// so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing)
newVisibleTurfs[t] = t
// Removes turf that isn't in turfs.
newVisibleTurfs &= turfs
for(var/turf/vis_turf in current_camera.can_see())
if(turfs[vis_turf])
newVisibleTurfs[vis_turf] = vis_turf
//new turfs will be in visibleTurfs but werent last update
var/list/visAdded = newVisibleTurfs - visibleTurfs
//old turfs that will no longer be in visibleTurfs but were last update
var/list/visRemoved = visibleTurfs - newVisibleTurfs
visibleTurfs = newVisibleTurfs
//turfs that are included in the chunks normal turfs list minus the turfs the cameras CAN see
obscuredTurfs = turfs - newVisibleTurfs
for(var/turf in visAdded)
var/turf/t = turf
t.vis_contents -= GLOB.cameranet.vis_contents_objects
var/static/list/vis_contents_opaque = GLOB.cameranet.vis_contents_opaque //ba dum tsss
for(var/turf/added_turf as anything in visAdded)
added_turf.vis_contents -= vis_contents_opaque
for(var/turf in visRemoved)
var/turf/t = turf
if(obscuredTurfs[t] && !istype(t, /turf/open/ai_visible))
t.vis_contents += GLOB.cameranet.vis_contents_objects
for(var/turf/removed_turf as anything in visRemoved)
if(obscuredTurfs[removed_turf] && !istype(removed_turf, /turf/open/ai_visible))
removed_turf.vis_contents += vis_contents_opaque
changed = 0
// Create a new camera chunk, since the chunks are made as they are needed.
changed = FALSE
/// Create a new camera chunk, since the chunks are made as they are needed.
/datum/camerachunk/New(x, y, z)
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
@@ -108,39 +98,33 @@
src.y = y
src.z = z
for(var/obj/machinery/camera/c in urange(CHUNK_SIZE, locate(x + (CHUNK_SIZE / 2), y + (CHUNK_SIZE / 2), z)))
if(c.can_use())
cameras += c
for(var/obj/machinery/camera/camera in urange(CHUNK_SIZE, locate(x + (CHUNK_SIZE / 2), y + (CHUNK_SIZE / 2), z)))
if(camera.can_use())
cameras += camera
for(var/mob/living/silicon/sillycone in urange(CHUNK_SIZE, locate(x + (CHUNK_SIZE / 2), y + (CHUNK_SIZE / 2), z)))
if(sillycone.builtInCamera?.can_use())
cameras += sillycone.builtInCamera
for(var/turf/t in block(locate(max(x, 1), max(y, 1), z), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z)))
for(var/turf/t as anything in block(locate(max(x, 1), max(y, 1), z), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z)))
turfs[t] = t
for(var/camera in cameras)
var/obj/machinery/camera/c = camera
if(!c)
for(var/obj/machinery/camera/camera as anything in cameras)
if(!camera)
continue
if(!c.can_use())
if(!camera.can_use())
continue
for(var/turf/t in c.can_see())
// Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards.
// List associations use a tree or hashmap of some sort (alongside the list itself)
// so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing)
visibleTurfs[t] = t
// Removes turf that isn't in turfs.
visibleTurfs &= turfs
for(var/turf/vis_turf in camera.can_see())
if(turfs[vis_turf])
visibleTurfs[vis_turf] = vis_turf
obscuredTurfs = turfs - visibleTurfs
for(var/turf in obscuredTurfs)
var/turf/t = turf
t.vis_contents += GLOB.cameranet.vis_contents_objects
var/list/vis_contents_opaque = GLOB.cameranet.vis_contents_opaque
for(var/turf/obscured_turf as anything in obscuredTurfs)
obscured_turf.vis_contents += vis_contents_opaque
#undef UPDATE_BUFFER
#undef UPDATE_BUFFER_TIME
#undef CHUNK_SIZE
@@ -13,7 +13,7 @@
var/list/visibleCameraChunks = list()
var/mob/living/silicon/ai/ai = null
var/relay_speech = FALSE
var/use_static = USE_STATIC_OPAQUE
var/use_static = TRUE
var/static_visibility_range = 16
var/ai_detector_visible = TRUE
var/ai_detector_color = COLOR_RED
@@ -44,12 +44,12 @@
return
hud.remove_from_hud(src)
var/static/list/vis_contents_objects = list()
var/obj/effect/overlay/ai_detect_hud/hud_obj = vis_contents_objects[ai_detector_color]
var/static/list/vis_contents_opaque = list()
var/obj/effect/overlay/ai_detect_hud/hud_obj = vis_contents_opaque[ai_detector_color]
if(!hud_obj)
hud_obj = new /obj/effect/overlay/ai_detect_hud()
hud_obj.color = ai_detector_color
vis_contents_objects[ai_detector_color] = hud_obj
vis_contents_opaque[ai_detector_color] = hud_obj
var/list/new_images = list()
var/list/turfs = get_visible_turfs()
@@ -86,7 +86,7 @@
abstract_move(T)
else
moveToNullspace()
if(use_static != USE_STATIC_NONE)
if(use_static != FALSE)
ai.camera_visibility(src)
if(ai.client && !ai.multicam_on)
ai.client.eye = src