From e7686dd3e766ff0a67486a3cd5b82d023ffb8c83 Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Sat, 30 Jan 2016 13:44:52 +0100 Subject: [PATCH] Camera fixes and performance tweaks. Improves camera EMP handling. Now uses a var and processing to determine when the EMP should end, preventing inconsistent states when a camera is EMPd multiple times. Reduces the process and bandwidth need for cameras. * There is now a common camera repository, responsible for setting up cameras once for every invalidation. * Camera consoles now only updates when the camera cache is invalidated, not every second. * The console now only presents one network at a time, and only sends the data necessary to view that network (as opposed to sending the data for all cameras). --- code/datums/repositories/cameras.dm | 34 ++++++++ code/datums/{ => repositories}/crew.dm | 4 - code/datums/repositories/repository.dm | 4 + code/game/machinery/camera/camera.dm | 40 +++++---- code/game/machinery/camera/motion.dm | 2 +- code/game/machinery/computer/camera.dm | 82 +++++++++++-------- .../circuitboards/computer/camera_monitor.dm | 4 +- code/modules/alarm/alarm.dm | 4 +- nano/templates/sec_camera.tmpl | 29 +++++-- nano/templates/sec_camera_map_content.tmpl | 4 +- nano/templates/sec_camera_map_header.tmpl | 25 ++++-- polaris.dme | 1 - 12 files changed, 153 insertions(+), 80 deletions(-) create mode 100644 code/datums/repositories/cameras.dm rename code/datums/{ => repositories}/crew.dm (95%) create mode 100644 code/datums/repositories/repository.dm diff --git a/code/datums/repositories/cameras.dm b/code/datums/repositories/cameras.dm new file mode 100644 index 0000000000..7bac2a4634 --- /dev/null +++ b/code/datums/repositories/cameras.dm @@ -0,0 +1,34 @@ +var/global/datum/repository/cameras/camera_repository = new() + +/proc/invalidateCameraCache() + camera_repository.networks.Cut() + camera_repository.invalidated = 1 + camera_repository.camera_cache_id = (++camera_repository.camera_cache_id % 999999) + +/datum/repository/cameras + var/list/networks + var/invalidated = 1 + var/camera_cache_id = 1 + +/datum/repository/cameras/New() + networks = list() + ..() + +/datum/repository/cameras/proc/cameras_in_network(var/network) + setup_cache() + var/list/network_list = networks[network] + return network_list + +/datum/repository/cameras/proc/setup_cache() + if(!invalidated) + return + invalidated = 0 + + cameranet.process_sort() + for(var/obj/machinery/camera/C in cameranet.cameras) + var/cam = C.nano_structure() + for(var/network in C.network) + if(!networks[network]) + networks[network] = list() + var/list/netlist = networks[network] + netlist[++netlist.len] = cam diff --git a/code/datums/crew.dm b/code/datums/repositories/crew.dm similarity index 95% rename from code/datums/crew.dm rename to code/datums/repositories/crew.dm index d46a83846f..6fbe1863da 100644 --- a/code/datums/crew.dm +++ b/code/datums/repositories/crew.dm @@ -1,9 +1,5 @@ var/global/datum/repository/crew/crew_repository = new() -/datum/cache_entry - var/timestamp - var/data - /datum/repository/crew var/list/cache_data diff --git a/code/datums/repositories/repository.dm b/code/datums/repositories/repository.dm new file mode 100644 index 0000000000..6267099c93 --- /dev/null +++ b/code/datums/repositories/repository.dm @@ -0,0 +1,4 @@ +/datum/cache_entry + var/timestamp + var/data + diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index cb0d95c1df..291b985294 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -33,6 +33,8 @@ var/on_open_network = 0 + var/affected_by_emp_until = 0 + /obj/machinery/camera/New() wires = new(src) assembly = new(src) @@ -62,22 +64,29 @@ wires = null return ..() +/obj/machinery/camera/process() + if((stat & EMPED) && world.time >= affected_by_emp_until) + stat &= ~EMPED + cancelCameraAlarm() + update_icon() + update_coverage() + return internal_process() + +/obj/machinery/camera/proc/internal_process() + return + /obj/machinery/camera/emp_act(severity) - if(!isEmpProof()) - if(prob(100/severity)) + if(!isEmpProof() && prob(100/severity)) + if(!affected_by_emp_until || (world.time < affected_by_emp_until)) + affected_by_emp_until = max(affected_by_emp_until, world.time + (90 SECONDS / severity)) + else stat |= EMPED set_light(0) + triggerCameraAlarm() kick_viewers() - triggerCameraAlarm(30 / severity) update_icon() update_coverage() - - spawn(900) - stat &= ~EMPED - cancelCameraAlarm() - update_icon() - update_coverage() - ..() + processing_objects |= src /obj/machinery/camera/bullet_act(var/obj/item/projectile/P) take_damage(P.get_structure_damage()) @@ -105,7 +114,6 @@ cameranet.updateVisibility(src, 0) /obj/machinery/camera/attack_hand(mob/living/carbon/human/user as mob) - if(!istype(user)) return @@ -114,7 +122,6 @@ user.do_attack_animation(src) visible_message("\The [user] slashes at [src]!") playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) - icon_state = "[initial(icon_state)]1" add_hiddenprint(user) destroy() @@ -176,7 +183,7 @@ for(var/mob/O in player_list) if (istype(O.machine, /obj/machinery/computer/security)) var/obj/machinery/computer/security/S = O.machine - if (S.current == src) + if (S.current_camera == src) O << "[U] holds \a [itemname] up to one of the cameras ..." O << browse(text("[][]", itemname, info), text("window=[]", itemname)) @@ -214,8 +221,7 @@ //legacy support, if choice is != 1 then just kick viewers without changing status kick_viewers() else - update_coverage() - set_status( !src.status ) + set_status(!src.status) if (!(src.status)) if(user) visible_message(" [user] has deactivated [src]!") @@ -257,7 +263,7 @@ /obj/machinery/camera/proc/set_status(var/newstatus) if (status != newstatus) status = newstatus - invalidateCameraCache() + update_coverage() // now disconnect anyone using the camera //Apparently, this will disconnect anyone even if the camera was re-activated. //I guess that doesn't matter since they couldn't use it anyway? @@ -273,7 +279,7 @@ for(var/mob/O in player_list) if (istype(O.machine, /obj/machinery/computer/security)) var/obj/machinery/computer/security/S = O.machine - if (S.current == src) + if (S.current_camera == src) O.unset_machine() O.reset_view(null) O << "The screen bursts into static." diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm index 7821b27f26..eac1f89386 100644 --- a/code/game/machinery/camera/motion.dm +++ b/code/game/machinery/camera/motion.dm @@ -5,7 +5,7 @@ var/alarm_delay = 100 // Don't forget, there's another 10 seconds in queueAlarm() flags = PROXMOVE -/obj/machinery/camera/process() +/obj/machinery/camera/internal_process() // motion camera event loop if (stat & (EMPED|NOPOWER)) return diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index e1c6658ab4..e9aa439600 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -1,28 +1,25 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 -/var/camera_cache_id = 1 - -/proc/invalidateCameraCache() - camera_cache_id = (++camera_cache_id % 999999) - /obj/machinery/computer/security name = "security camera monitor" desc = "Used to access the various cameras on the station." icon_keyboard = "security_key" icon_screen = "cameras" light_color = "#a91515" - var/obj/machinery/camera/current = null + var/current_network = null + var/obj/machinery/camera/current_camera = null var/last_pic = 1.0 var/list/network var/mapping = 0//For the overview file, interesting bit of code. var/cache_id = 0 circuit = /obj/item/weapon/circuitboard/security - var/camera_cache = null New() if(!network) - network = station_networks + network = station_networks.Copy() ..() + if(network.len) + current_network = network[1] attack_ai(var/mob/user as mob) return attack_hand(user) @@ -30,9 +27,9 @@ check_eye(var/mob/user as mob) if (user.stat || ((get_dist(user, src) > 1 || !( user.canmove ) || user.blinded) && !istype(user, /mob/living/silicon))) //user can't see - not sure why canmove is here. return -1 - if(!current) + if(!current_camera) return 0 - var/viewflag = current.check_eye(user) + var/viewflag = current_camera.check_eye(user) if ( viewflag < 0 ) //camera doesn't work reset_current() return viewflag @@ -44,7 +41,11 @@ var/data[0] - data["current"] = null + data["current_camera"] = current_camera ? current_camera.nano_structure() : null + data["current_network"] = current_network + data["networks"] = network ? network : list() + if(current_network) + data["cameras"] = camera_repository.cameras_in_network(current_network) if(camera_cache_id != cache_id) cache_id = camera_cache_id @@ -75,22 +76,32 @@ ui.set_initial_data(data) ui.open() - ui.set_auto_update(1) Topic(href, href_list) - if(href_list["switchTo"]) + if(..()) + return 1 + if(href_list["switch_camera"]) if(src.z>6 || stat&(NOPOWER|BROKEN)) return if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return - var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.cameras - if(!C) return + var/obj/machinery/camera/C = locate(href_list["switch_camera"]) in cameranet.cameras + if(!C) + return + if(!(current_network in C.network)) + return switch_to_camera(usr, C) return 1 + else if(href_list["switch_network"]) + if(src.z>6 || stat&(NOPOWER|BROKEN)) return + if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return + if(href_list["switch_network"] in network) + current_network = href_list["switch_network"] + return 1 else if(href_list["reset"]) if(src.z>6 || stat&(NOPOWER|BROKEN)) return if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return reset_current() - usr.reset_view(current) + usr.reset_view(current_camera) return 1 else . = ..() @@ -105,12 +116,6 @@ user.set_machine(src) ui_interact(user) - proc/can_access_camera(var/obj/machinery/camera/C) - var/list/shared_networks = src.network & C.network - if(shared_networks.len) - return 1 - return 0 - proc/switch_to_camera(var/mob/user, var/obj/machinery/camera/C) //don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras. if(isAI(user)) @@ -126,7 +131,7 @@ if (!C.can_use() || user.stat || (get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) && !istype(user, /mob/living/silicon))) return 0 set_current(C) - user.reset_view(current) + user.reset_view(current_camera) check_eye(user) return 1 @@ -160,26 +165,37 @@ if(can_access_camera(jump_to)) switch_to_camera(user,jump_to) +/obj/machinery/computer/security/process() + if(cache_id != camera_repository.camera_cache_id) + cache_id = camera_repository.camera_cache_id + nanomanager.update_uis(src) + +/obj/machinery/computer/security/proc/can_access_camera(var/obj/machinery/camera/C) + var/list/shared_networks = src.network & C.network + if(shared_networks.len) + return 1 + return 0 + /obj/machinery/computer/security/proc/set_current(var/obj/machinery/camera/C) - if(current == C) + if(current_camera == C) return - if(current) + if(current_camera) reset_current() - src.current = C - if(current) + src.current_camera = C + if(current_camera) use_power = 2 - var/mob/living/L = current.loc + var/mob/living/L = current_camera.loc if(istype(L)) L.tracking_initiated() /obj/machinery/computer/security/proc/reset_current() - if(current) - var/mob/living/L = current.loc + if(current_camera) + var/mob/living/L = current_camera.loc if(istype(L)) L.tracking_cancelled() - current = null + current_camera = null use_power = 1 //Camera control: mouse. @@ -192,7 +208,7 @@ /mob/Move(n,direct) if(istype(machine,/obj/machinery/computer/security)) var/obj/machinery/computer/security/console = machine - var/turf/T = get_turf(console.current) + var/turf/T = get_turf(console.current_camera) for(var/i;i<10;i++) T = get_step(T,direct) console.jump_on_click(src,T) @@ -248,7 +264,7 @@ /obj/machinery/computer/security/engineering/New() if(!network) - network = engineering_networks + network = engineering_networks.Copy() ..() /obj/machinery/computer/security/nuclear diff --git a/code/game/objects/items/weapons/circuitboards/computer/camera_monitor.dm b/code/game/objects/items/weapons/circuitboards/computer/camera_monitor.dm index 61de25f44c..60f8bce268 100644 --- a/code/game/objects/items/weapons/circuitboards/computer/camera_monitor.dm +++ b/code/game/objects/items/weapons/circuitboards/computer/camera_monitor.dm @@ -31,11 +31,11 @@ /obj/item/weapon/circuitboard/security/construct(var/obj/machinery/computer/security/C) if (..(C)) - C.network = network + C.network = network.Copy() /obj/item/weapon/circuitboard/security/deconstruct(var/obj/machinery/computer/security/C) if (..(C)) - network = C.network + network = C.network.Copy() /obj/item/weapon/circuitboard/security/emag_act(var/remaining_charges, var/mob/user) if(emagged) diff --git a/code/modules/alarm/alarm.dm b/code/modules/alarm/alarm.dm index aa88e170bf..d0a6a8be4c 100644 --- a/code/modules/alarm/alarm.dm +++ b/code/modules/alarm/alarm.dm @@ -76,9 +76,9 @@ /datum/alarm/proc/cameras() // reset camera cache - if(camera_cache_id != cache_id) + if(camera_repository.camera_cache_id != cache_id) cameras = null - cache_id = camera_cache_id + cache_id = camera_repository.camera_cache_id // If the alarm origin has changed area, for example a borg containing an alarming camera, reset the list of cameras else if(cameras && (last_camera_area != alarm_area())) cameras = null diff --git a/nano/templates/sec_camera.tmpl b/nano/templates/sec_camera.tmpl index 13ec5ab229..356bad1df3 100644 --- a/nano/templates/sec_camera.tmpl +++ b/nano/templates/sec_camera.tmpl @@ -4,20 +4,31 @@ Used In File(s): \code\game\machinery\computer\camera.dm --> {{:helper.link('Show Map', 'pin-s', {'showMap' : 1})}} {{:helper.link('Reset', 'refresh', {'reset' : 1})}} +
+
+
Current Camera: 
+ {{if data.current_camera}} +
{{:data.current_camera.name}}
+ {{else}} +
None
+ {{/if}} +
+
-
Current Camera:
- {{if data.current}} -
{{:data.current.name}}
- {{else}} -
None
- {{/if}} +
Networks:
+
+{{for data.networks}} + {{:helper.link(value, '', {'switch_network' : value}, null, data.current_network == value ? 'selected' : null)}} +{{/for}} +
+
Cameras:
{{for data.cameras}} - {{if data.current && value.name == data.current.name}} - {{:helper.link(value.name, '', {'switchTo' : value.camera}, 'selected')}} + {{if data.current_camera && value.name == data.current_camera.name}} + {{:helper.link(value.name, '', {'switch_camera' : value.camera}, 'selected')}} {{else value.deact}} {{:helper.link(value.name + " (deactivated)", '', {}, 'inactive')}} {{else}} - {{:helper.link(value.name, '', {'switchTo' : value.camera})}} + {{:helper.link(value.name, '', {'switch_camera' : value.camera})}} {{/if}} {{/for}} diff --git a/nano/templates/sec_camera_map_content.tmpl b/nano/templates/sec_camera_map_content.tmpl index a2706d8c35..c78d85298d 100644 --- a/nano/templates/sec_camera_map_content.tmpl +++ b/nano/templates/sec_camera_map_content.tmpl @@ -6,11 +6,11 @@ Used In File(s): \code\game\machinery\computer\camera.dm {{if value.z == 1}}
{{if data.current && value.name == data.current.name}} - {{:helper.link("#", '', {'switchTo' : value.camera}, 'selected')}} + {{:helper.link("#", '', {'switch_camera' : value.camera}, 'selected')}} {{else value.deact}} {{:helper.link('#', '', {}, 'inactive')}} {{else}} - {{:helper.link("#", '', {'switchTo' : value.camera})}} + {{:helper.link("#", '', {'switch_camera' : value.camera})}} {{/if}} +
+
+
Networks:
+
+{{for data.networks}} + {{:helper.link(value, '', {'switch_network' : value}, null, data.current_network == value ? 'selected' : null)}} +{{/for}} \ No newline at end of file diff --git a/polaris.dme b/polaris.dme index e30cdd9ed5..d00febb517 100644 --- a/polaris.dme +++ b/polaris.dme @@ -154,7 +154,6 @@ #include "code\datums\browser.dm" #include "code\datums\category.dm" #include "code\datums\computerfiles.dm" -#include "code\datums\crew.dm" #include "code\datums\datacore.dm" #include "code\datums\EPv2.dm" #include "code\datums\mind.dm"