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).
This commit is contained in:
PsiOmegaDelta
2016-01-30 13:44:52 +01:00
committed by Datraen
parent 1a9d1e6f36
commit e7686dd3e7
12 changed files with 153 additions and 80 deletions
+34
View File
@@ -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
@@ -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
+4
View File
@@ -0,0 +1,4 @@
/datum/cache_entry
var/timestamp
var/data
+23 -17
View File
@@ -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("<span class='warning'>\The [user] slashes at [src]!</span>")
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("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", 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("<span class='notice'> [user] has deactivated [src]!</span>")
@@ -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."
+1 -1
View File
@@ -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
+49 -33
View File
@@ -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
@@ -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)
+2 -2
View File
@@ -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
+20 -9
View File
@@ -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})}}
<div style="float:left;">
<div class='item'>
<div class='itemLabel'>Current Camera:&nbsp;</div>
{{if data.current_camera}}
<div class='itemContent'><b>{{:data.current_camera.name}}</b></div>
{{else}}
<div class='itemContent'>None</div>
{{/if}}
</div>
</div>
<div class='item'>
<div class='itemLabel'>Current Camera: </div>
{{if data.current}}
<div class='itemContent'><b>{{:data.current.name}}</b></div>
{{else}}
<div class='itemContent'>None</div>
{{/if}}
<div class='itemLabel'>Networks:</div>
</div>
{{for data.networks}}
{{:helper.link(value, '', {'switch_network' : value}, null, data.current_network == value ? 'selected' : null)}}
{{/for}}
<div class='item'>
<div class='itemLabel'>Cameras:</div>
</div>
{{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}}
+2 -2
View File
@@ -6,11 +6,11 @@ Used In File(s): \code\game\machinery\computer\camera.dm
{{if value.z == 1}}
<div class="mapIcon mapIcon16" style="left: {{:(value.x)}}px; bottom: {{:(value.y - 1)}}px;">
{{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}}
<div class="tooltip hidden">
{{:value.name}}
+16 -9
View File
@@ -5,14 +5,14 @@ Used In File(s): \code\game\machinery\computer\camera.dm
{{:helper.link('Show Camera List', 'script', {'showMap' : 0})}}
{{:helper.link('Reset', 'refresh', {'reset' : 1})}}
<div style="float:left;">
<div class='item'>
<div class='itemLabel'>Current Camera:&nbsp;</div>
{{if data.current}}
<div class='itemContent'><b>{{:data.current.name}}</b></div>
{{else}}
<div class='itemContent'>None</div>
{{/if}}
</div>
<div class='item'>
<div class='itemLabel'>Current Camera:&nbsp;</div>
{{if data.current_camera}}
<div class='itemContent'><b>{{:data.current_camera.name}}</b></div>
{{else}}
<div class='itemContent'>None</div>
{{/if}}
</div>
</div>
<div style="float: right; width: 240px;">
<span style="float: left;">Zoom Level:&nbsp;</span>
@@ -20,4 +20,11 @@ Used In File(s): \code\game\machinery\computer\camera.dm
<div unselectable="on" class="link zoomLink" data-zoom-level="6">x1.5</div>
<div unselectable="on" class="link zoomLink" data-zoom-level="8">x2.0</div>
<div unselectable="on" class="link zoomLink" data-zoom-level="12">x2.5</div>
</div>
</div>
</div>
<div class='item'>
<div class='itemLabel'>Networks:</div>
</div>
{{for data.networks}}
{{:helper.link(value, '', {'switch_network' : value}, null, data.current_network == value ? 'selected' : null)}}
{{/for}}
-1
View File
@@ -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"