diff --git a/code/datums/cache/air_alarm.dm b/code/datums/cache/air_alarm.dm new file mode 100644 index 00000000000..07caea0f3ad --- /dev/null +++ b/code/datums/cache/air_alarm.dm @@ -0,0 +1,27 @@ +var/global/datum/repository/air_alarm/air_alarm_repository = new() + +/datum/repository/air_alarm/proc/air_alarm_data(var/list/monitored_alarms, var/refresh = 0, var/obj/machinery/alarm/passed_alarm) + var/alarms[0] + + var/datum/cache_entry/cache_entry = cache_data + if(!cache_entry) + cache_entry = new/datum/cache_entry + cache_data = cache_entry + + if(!refresh) + return cache_entry.data + + if(ticker && ticker.current_state < GAME_STATE_PLAYING && istype(passed_alarm)) // Generating the list for the first time as the game hasn't started - no need to run through the machines list everything every time + alarms[++alarms.len] = passed_alarm.get_nano_data_console() + else + for(var/obj/machinery/alarm/alarm in sortAtom((monitored_alarms ? monitored_alarms : machines))) + if(!monitored_alarms && alarm.z != ZLEVEL_STATION && alarm.z != ZLEVEL_ASTEROID) + continue + alarms[++alarms.len] = alarm.get_nano_data_console() + + cache_entry.timestamp = world.time //+ 10 SECONDS + cache_entry.data = alarms + return alarms + +/datum/repository/air_alarm/proc/update_cache(var/obj/machinery/alarm/alarm) + return air_alarm_data(refresh = 1, passed_alarm = alarm) \ No newline at end of file diff --git a/code/datums/cache/apc.dm b/code/datums/cache/apc.dm new file mode 100644 index 00000000000..e6dc996827b --- /dev/null +++ b/code/datums/cache/apc.dm @@ -0,0 +1,28 @@ +var/global/datum/repository/apc/apc_repository = new() + +/datum/repository/apc/proc/apc_data(var/obj/machinery/computer/monitor/powermonitor) + var/apcData[0] + + var/datum/cache_entry/cache_entry = cache_data + if(!cache_entry) + cache_entry = new/datum/cache_entry + cache_data = cache_entry + + if(world.time < cache_entry.timestamp) + return cache_entry.data + + if (powermonitor && !isnull(powermonitor.powernet)) + var/list/L = list() + for(var/obj/machinery/power/terminal/term in powermonitor.powernet.nodes) + if(istype(term.master, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/A = term.master + L += A + + var/list/Status = list(0,0,1,1) // Status: off, auto-off, on, auto-on + var/list/chg = list(0,1,1) // Charging: no, charging, full + for(var/obj/machinery/power/apc/A in L) + apcData[++apcData.len] = list("Name" = html_encode(A.area.name), "Equipment" = Status[A.equipment+1], "Lights" = Status[A.lighting+1], "Environment" = Status[A.environ+1], "CellPct" = A.cell ? round(A.cell.percent(),1) : -1, "CellStatus" = A.cell ? chg[A.charging+1] : 0) + + cache_entry.timestamp = world.time + 5 SECONDS + cache_entry.data = apcData + return apcData \ No newline at end of file diff --git a/code/datums/cache/cache.dm b/code/datums/cache/cache.dm new file mode 100644 index 00000000000..2502bb871b2 --- /dev/null +++ b/code/datums/cache/cache.dm @@ -0,0 +1,6 @@ +/datum/cache_entry + var/timestamp + var/data + +/datum/repository + var/cache_data \ No newline at end of file diff --git a/code/datums/cache/crew.dm b/code/datums/cache/crew.dm new file mode 100644 index 00000000000..0afb70a4404 --- /dev/null +++ b/code/datums/cache/crew.dm @@ -0,0 +1,67 @@ +var/global/datum/repository/crew/crew_repository = new() + +/datum/repository/crew/New() + cache_data = list() + ..() + +/datum/repository/crew/proc/health_data(var/turf/T) + var/list/crewmembers = list() + if(!T) + return crewmembers + + var/z_level = "[T.z]" + var/datum/cache_entry/cache_entry = cache_data[z_level] + if(!cache_entry) + cache_entry = new/datum/cache_entry + cache_data[z_level] = cache_entry + + if(world.time < cache_entry.timestamp) + return cache_entry.data + + var/tracked = scan() + for(var/obj/item/clothing/under/C in tracked) + var/turf/pos = get_turf(C) + if((C) && (C.has_sensor) && (pos) && (T && pos.z == T.z) && (C.sensor_mode != SUIT_SENSOR_OFF)) + if(istype(C.loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = C.loc + if(H.w_uniform != C) + continue + + var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1, "ref" = "\ref[H]") + + crewmemberData["sensor_type"] = C.sensor_mode + crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown") + crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job") + crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job") + + if(C.sensor_mode >= SUIT_SENSOR_BINARY) + crewmemberData["dead"] = H.stat > UNCONSCIOUS + + if(C.sensor_mode >= SUIT_SENSOR_VITAL) + crewmemberData["oxy"] = round(H.getOxyLoss(), 1) + crewmemberData["tox"] = round(H.getToxLoss(), 1) + crewmemberData["fire"] = round(H.getFireLoss(), 1) + crewmemberData["brute"] = round(H.getBruteLoss(), 1) + + if(C.sensor_mode >= SUIT_SENSOR_TRACKING) + var/area/A = get_area(H) + crewmemberData["area"] = sanitize(A.name) + crewmemberData["x"] = pos.x + crewmemberData["y"] = pos.y + + crewmembers[++crewmembers.len] = crewmemberData + + crewmembers = sortByKey(crewmembers, "name") + cache_entry.timestamp = world.time + 5 SECONDS + cache_entry.data = crewmembers + + return crewmembers + +/datum/repository/crew/proc/scan() + var/list/tracked = list() + for(var/mob/living/carbon/human/H in mob_list) + if(istype(H.w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/C = H.w_uniform + if (C.has_sensor) + tracked |= C + return tracked diff --git a/code/datums/cache/powermonitor.dm b/code/datums/cache/powermonitor.dm new file mode 100644 index 00000000000..a99b380a13d --- /dev/null +++ b/code/datums/cache/powermonitor.dm @@ -0,0 +1,24 @@ +var/global/datum/repository/powermonitor/powermonitor_repository = new() + +/datum/repository/powermonitor/proc/powermonitor_data(var/refresh = 0) + var/pMonData[0] + + var/datum/cache_entry/cache_entry = cache_data + if(!cache_entry) + cache_entry = new/datum/cache_entry + cache_data = cache_entry + + if(!refresh) + return cache_entry.data + + for(var/obj/machinery/computer/monitor/pMon in machines) + if( !(pMon.stat & (NOPOWER|BROKEN)) ) + pMonData[++pMonData.len] = list ("Name" = pMon.name, "ref" = "\ref[pMon]") + + cache_entry.timestamp = world.time //+ 30 SECONDS + cache_entry.data = pMonData + return pMonData + +/datum/repository/powermonitor/proc/update_cache() + return powermonitor_data(refresh = 1) + \ No newline at end of file diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 1a9dcca511e..7dafb778e7a 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -66,8 +66,10 @@ atmosalm = danger_level for (var/obj/machinery/alarm/AA in src) AA.update_icon() - + + air_alarm_repository.update_cache(src) return 1 + air_alarm_repository.update_cache(src) return 0 /area/proc/air_doors_close() diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index f5ef29300f8..824fd231180 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -204,6 +204,10 @@ /obj/machinery/alarm/Destroy() if(radio_controller) radio_controller.remove_object(src, frequency) + + if (src in machines) // So the cache can properly update + removeAtProcessing() + air_alarm_repository.update_cache(src) return ..() /obj/machinery/alarm/proc/first_run() @@ -212,6 +216,7 @@ if (name == "alarm") name = "[alarm_area.name] Air Alarm" apply_preset(1) // Don't cycle. + air_alarm_repository.update_cache(src) /obj/machinery/alarm/initialize() set_frequency(frequency) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 58fb54bdfde..cc192ec8c53 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -193,6 +193,7 @@ src.scan_mob(src.scanner.occupant) loading = 0 + nanomanager.update_uis(src) if(href_list["task"]) switch(href_list["task"]) @@ -245,10 +246,12 @@ if("load") if ((isnull(src.diskette)) || isnull(src.diskette.buf)) src.temp = "Error: The disk's data could not be read." + nanomanager.update_uis(src) return if (isnull(src.active_record)) src.temp = "Error: No active record was found." src.menu = 1 + nanomanager.update_uis(src) return src.active_record = src.diskette.buf diff --git a/code/game/machinery/computer/power.dm b/code/game/machinery/computer/power.dm index b37437e7c22..50a37483526 100644 --- a/code/game/machinery/computer/power.dm +++ b/code/game/machinery/computer/power.dm @@ -12,10 +12,20 @@ var/datum/nano_module/power_monitor/power_monitor /obj/machinery/computer/monitor/New() + ..() power_monitor = new(src) powernet = find_powernet() - + powermonitor_repository.update_cache() + +/obj/machinery/computer/monitor/Destroy() + if (src in machines) // So the cache can properly update + removeAtProcessing() + powermonitor_repository.update_cache() + return ..() + +/obj/machinery/computer/monitor/power_change() ..() + powermonitor_repository.update_cache() /obj/machinery/computer/monitor/process() if(!powernet) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 4e6c9c3f2ef..4b69fd2dd6d 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -282,32 +282,14 @@ /* Power Monitor (Mode: 43 / 433) */ - if(mode==43 || mode==433) - var/pMonData[0] - var/apcData[0] - for(var/obj/machinery/computer/monitor/pMon in world) - if(!(pMon.stat & (NOPOWER|BROKEN)) ) - pMonData[++pMonData.len] = list ("Name" = pMon.name, "ref" = "\ref[pMon]") - if(isnull(powmonitor)) powmonitor = pMon - - values["powermonitors"] = pMonData + if(mode==43 || mode==433) + values["powermonitors"] = powermonitor_repository.powermonitor_data() - if (!isnull(powmonitor.powernet)) + if (powmonitor && !isnull(powmonitor.powernet)) values["powerconnected"] = 1 values["poweravail"] = powmonitor.powernet.avail values["powerload"] = num2text(powmonitor.powernet.viewload,10) - var/list/L = list() - for(var/obj/machinery/power/terminal/term in powmonitor.powernet.nodes) - if(istype(term.master, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = term.master - L += A - - var/list/Status = list(0,0,1,1) // Status: off, auto-off, on, auto-on - var/list/chg = list(0,1,1) // Charging: nope, charging, full - for(var/obj/machinery/power/apc/A in L) - apcData[++apcData.len] = list("Name" = html_encode(A.area.name), "Equipment" = Status[A.equipment+1], "Lights" = Status[A.lighting+1], "Environment" = Status[A.environ+1], "CellPct" = A.cell ? round(A.cell.percent(),1) : -1, "CellStatus" = A.cell ? chg[A.charging+1] : 0) - - values["apcs"] = apcData + values["apcs"] = apc_repository.apc_data(powmonitor) else values["powerconnected"] = 0 diff --git a/code/modules/nano/modules/atmos_control.dm b/code/modules/nano/modules/atmos_control.dm index 1c5f3c9a932..5a12c4db8a3 100644 --- a/code/modules/nano/modules/atmos_control.dm +++ b/code/modules/nano/modules/atmos_control.dm @@ -31,14 +31,7 @@ /datum/nano_module/atmos_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) var/data[0] - var/alarms[0] - - // TODO: Move these to a cache, similar to cameras - for(var/obj/machinery/alarm/alarm in sortAtom((monitored_alarms.len ? monitored_alarms : machines))) - if(!monitored_alarms.len && alarm.z != ZLEVEL_STATION && alarm.z != ZLEVEL_ASTEROID) - continue - alarms[++alarms.len] = alarm.get_nano_data_console() - data["alarms"] = alarms + data["alarms"] = air_alarm_repository.air_alarm_data(monitored_alarms) ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if(!ui) diff --git a/code/modules/nano/modules/crew_monitor.dm b/code/modules/nano/modules/crew_monitor.dm index b43d84b04eb..6888702ea83 100644 --- a/code/modules/nano/modules/crew_monitor.dm +++ b/code/modules/nano/modules/crew_monitor.dm @@ -1,6 +1,5 @@ /datum/nano_module/crew_monitor name = "Crew monitor" - var/list/tracked = new /datum/nano_module/crew_monitor/Topic(href, href_list) if(..()) @@ -18,51 +17,12 @@ return 1 /datum/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - src.scan() var/data[0] var/turf/T = get_turf(nano_host()) - var/list/crewmembers = list() - for(var/obj/item/clothing/under/C in src.tracked) - - var/turf/pos = get_turf(C) - - if((C) && (C.has_sensor) && (pos) && (T && pos.z == T.z) && (C.sensor_mode != SUIT_SENSOR_OFF)) - if(istype(C.loc, /mob/living/carbon/human)) - - var/mob/living/carbon/human/H = C.loc - if(H.w_uniform != C) - continue - - var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1) - - crewmemberData["reference"] = "\ref[H]" - crewmemberData["sensor_type"] = C.sensor_mode - crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown") - crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job") - crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job") - - if(C.sensor_mode >= SUIT_SENSOR_BINARY) - crewmemberData["dead"] = H.stat > 1 - - if(C.sensor_mode >= SUIT_SENSOR_VITAL) - crewmemberData["oxy"] = round(H.getOxyLoss(), 1) - crewmemberData["tox"] = round(H.getToxLoss(), 1) - crewmemberData["fire"] = round(H.getFireLoss(), 1) - crewmemberData["brute"] = round(H.getBruteLoss(), 1) - - if(C.sensor_mode >= SUIT_SENSOR_TRACKING) - var/area/A = get_area(H) - crewmemberData["area"] = sanitize(A.name) - crewmemberData["x"] = pos.x - crewmemberData["y"] = pos.y - - crewmembers[++crewmembers.len] = crewmemberData - - crewmembers = sortByKey(crewmembers, "name") data["isAI"] = isAI(user) - data["crewmembers"] = crewmembers + data["crewmembers"] = crew_repository.health_data(T) ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if(!ui) @@ -78,11 +38,4 @@ // should make the UI auto-update; doesn't seem to? ui.set_auto_update(1) - -/datum/nano_module/crew_monitor/proc/scan() - for(var/mob/living/carbon/human/H in mob_list) - if(istype(H.w_uniform, /obj/item/clothing/under)) - var/obj/item/clothing/under/C = H.w_uniform - if (C.has_sensor) - tracked |= C - return 1 + \ No newline at end of file diff --git a/code/modules/nano/modules/power_monitor.dm b/code/modules/nano/modules/power_monitor.dm index af5f12fbba8..1bcf9bc2176 100644 --- a/code/modules/nano/modules/power_monitor.dm +++ b/code/modules/nano/modules/power_monitor.dm @@ -13,34 +13,20 @@ /datum/nano_module/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) var/data[0] - var/pMonData[0] - var/apcData[0] data["powermonitor"] = powermonitor if(select_monitor) data["select_monitor"] = 1 - for(var/obj/machinery/computer/monitor/pMon in world) - if( !(pMon.stat & (NOPOWER|BROKEN)) ) - pMonData[++pMonData.len] = list ("Name" = pMon.name, "ref" = "\ref[pMon]") + data["powermonitors"] = powermonitor_repository.powermonitor_data() - data["powermonitors"] = pMonData - - if (powermonitor && !isnull(powermonitor.powernet)) + if (powermonitor && !isnull(powermonitor.powernet)) + if(select_monitor && (powermonitor.stat & (NOPOWER|BROKEN))) + powermonitor = null + return data["poweravail"] = powermonitor.powernet.avail - data["powerload"] = num2text(powermonitor.powernet.viewload,10) - var/list/L = list() - for(var/obj/machinery/power/terminal/term in powermonitor.powernet.nodes) - if(istype(term.master, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = term.master - L += A - - var/list/Status = list(0,0,1,1) // Status: off, auto-off, on, auto-on - var/list/chg = list(0,1,1) // Charging: nope, charging, full - for(var/obj/machinery/power/apc/A in L) - apcData[++apcData.len] = list("Name" = html_encode(A.area.name), "Equipment" = Status[A.equipment+1], "Lights" = Status[A.lighting+1], "Environment" = Status[A.environ+1], "CellPct" = A.cell ? round(A.cell.percent(),1) : -1, "CellStatus" = A.cell ? chg[A.charging+1] : 0) - - data["apcs"] = apcData - + data["powerload"] = num2text(powermonitor.powernet.viewload,10) + data["apcs"] = apc_repository.apc_data(powermonitor) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "power_monitor.tmpl", "Power Monitoring Console", 800, 700, state = state) diff --git a/paradise.dme b/paradise.dme index 05bf2766401..e79ab1d4d08 100644 --- a/paradise.dme +++ b/paradise.dme @@ -187,6 +187,11 @@ #include "code\datums\spell.dm" #include "code\datums\supplypacks.dm" #include "code\datums\uplink_item.dm" +#include "code\datums\cache\air_alarm.dm" +#include "code\datums\cache\apc.dm" +#include "code\datums\cache\cache.dm" +#include "code\datums\cache\crew.dm" +#include "code\datums\cache\powermonitor.dm" #include "code\datums\helper_datums\construction_datum.dm" #include "code\datums\helper_datums\events.dm" #include "code\datums\helper_datums\global_iterator.dm"