diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 0c16939a97f..289a67ca432 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -37,6 +37,8 @@
assembly.anchored = 1
assembly.update_icon()
+ invalidateCameraCache()
+
/* // Use this to look for cameras that have the same c_tag.
for(var/obj/machinery/camera/C in cameranet.cameras)
var/list/tempnetwork = C.network&src.network
@@ -50,6 +52,7 @@
deactivate()
/obj/machinery/camera/Destroy()
+ invalidateCameraCache()
deactivate(null, 0) //kick anyone viewing out
if(assembly)
qdel(assembly)
@@ -66,6 +69,7 @@
/obj/machinery/camera/emp_act(severity)
if(!isEmpProof())
if(prob(100/severity))
+ invalidateCameraCache()
icon_state = "[initial(icon_state)]emp"
var/list/previous_network = network
network = list()
@@ -85,6 +89,7 @@
if(can_use())
cameranet.addCamera(src)
emped = 0 //Resets the consecutive EMP count
+ invalidateCameraCache()
for(var/mob/O in mob_list)
if (O.client && O.client.eye == src)
O.unset_machine()
@@ -114,6 +119,7 @@
user.electrocute_act(10, src)
/obj/machinery/camera/attackby(W as obj, mob/living/user as mob, params)
+ invalidateCameraCache()
var/msg = "You attach [W] into the assembly inner circuits."
var/msg2 = "The camera already has that upgrade!"
@@ -221,6 +227,7 @@
/obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1)
if(choice==1)
+ invalidateCameraCache()
status = !( src.status )
if (!(src.status))
if(user)
@@ -331,3 +338,13 @@
return 1
busy = 0
return 0
+
+/obj/machinery/camera/proc/nano_structure()
+ var/cam[0]
+ cam["name"] = sanitize(c_tag)
+ cam["deact"] = !can_use()
+ cam["camera"] = "\ref[src]"
+ cam["x"] = x
+ cam["y"] = y
+ cam["z"] = z
+ return cam
\ No newline at end of file
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index bf616e8a859..7aec194ddac 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -1,8 +1,8 @@
-var/camera_cache_id = 1
+/var/camera_cache_id = 1
/proc/invalidateCameraCache()
camera_cache_id = (++camera_cache_id % 999999)
-
+
/obj/machinery/computer/security
name = "Camera Monitor"
desc = "Used to access the various cameras networks on the station."
@@ -79,32 +79,21 @@ var/camera_cache_id = 1
var/data[0]
-
data["current"] = null
- var/list/L = list()
- for (var/obj/machinery/camera/C in cameranet.cameras)
- if(can_access_camera(C))
- L.Add(C)
+ if(camera_cache_id != cache_id)
+ cache_id = camera_cache_id
+ cameranet.process_sort()
- cameranet.process_sort()
+ var/cameras[0]
+ for(var/obj/machinery/camera/C in cameranet.cameras)
+ if(!can_access_camera(C))
+ continue
- var/cameras[0]
- for(var/obj/machinery/camera/C in L)
- var/cam[0]
- cam["name"] = C.c_tag
- cam["deact"] = !C.can_use()
- cam["camera"] = "\ref[C]"
- cam["x"] = C.x
- cam["y"] = C.y
- cam["z"] = C.z
+ var/cam = C.nano_structure()
+ cameras[++cameras.len] = cam
- cameras[++cameras.len] = cam
-
- if(C == current)
- data["current"] = cam
-
- data["cameras"] = cameras
+ camera_cache=list2json(cameras)
tempnets.Cut()
if(emagged)
@@ -124,6 +113,10 @@ var/camera_cache_id = 1
break
if(tempnets.len)
data["networks"] = tempnets
+
+ if(current)
+ data["current"] = current.nano_structure()
+ data["cameras"] = list("__json_cache" = camera_cache)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
diff --git a/code/game/objects/effects/datacore-effect.dm b/code/game/objects/effects/datacore-effect.dm
index ac2ec220987..cd3dd60011f 100644
--- a/code/game/objects/effects/datacore-effect.dm
+++ b/code/game/objects/effects/datacore-effect.dm
@@ -132,10 +132,11 @@ using /obj/effect/datacore/proc/manifest_inject( ), or manifest_insert( )
*/
var/global/list/PDA_Manifest = list()
+var/global/ManifestJSON
/obj/effect/datacore/proc/get_manifest_json()
if(PDA_Manifest.len)
- return PDA_Manifest
+ return
var/heads[0]
var/sec[0]
var/eng[0]
@@ -206,5 +207,6 @@ var/global/list/PDA_Manifest = list()
"bot" = bot,\
"misc" = misc\
)
- return PDA_Manifest
+ ManifestJSON = list2json(PDA_Manifest)
+ return
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index ac5afb75b07..f7af05b808d 100755
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -467,7 +467,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
data["convo_job"] = sanitize(c["job"])
break
if(mode==41)
- data["manifest"] = data_core.get_manifest_json()
+ data_core.get_manifest_json()
if(mode==3)
@@ -499,12 +499,15 @@ var/global/list/obj/item/device/pda/PDAs = list()
data["aircontents"] = list("reading" = 0)
+ data["manifest"] = list("__json_cache" = ManifestJSON)
+
// update the ui if it exists, returns null if no ui is passed/found
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "pda.tmpl", title, 630, 600)
+
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm
index 877c6002dc6..14a3733154d 100644
--- a/code/modules/mob/living/silicon/pai/software_modules.dm
+++ b/code/modules/mob/living/silicon/pai/software_modules.dm
@@ -123,7 +123,7 @@
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
- data["manifest"] = data_core.get_manifest_json()
+ data["manifest"] = list("__json_cache" = ManifestJSON)
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
diff --git a/code/modules/nano/JSON Writer.dm b/code/modules/nano/JSON Writer.dm
index f4c74d35ebb..2b70239e7e6 100644
--- a/code/modules/nano/JSON Writer.dm
+++ b/code/modules/nano/JSON Writer.dm
@@ -1,7 +1,13 @@
json_writer
+ var
+ use_cache = 0
+
proc
WriteObject(list/L, cached_data = null)
+ if(use_cache && L["__json_cache"])
+ return L["__json_cache"]
+
. = "{"
var/i = 1
for(var/k in L)
@@ -9,13 +15,11 @@ json_writer
. += {"\"[k]\":[write(val)]"}
if(i++ < L.len)
. += ","
- if(cached_data)
- . = copytext(., 1, lentext(.)) + ",\"cached\":[cached_data]}"
- .+= "}"
+ . += "}"
write(val)
if(isnum(val))
- return num2text(val, 100)
+ return num2text(val)
else if(isnull(val))
return "null"
else if(istype(val, /list))
@@ -35,27 +39,21 @@ json_writer
. += "]"
write_string(txt)
- var/static/list/json_escape = list("\\", "\"", "'", "\n")
+ var/static/list/json_escape = list("\\" = "\\\\", "\"" = "\\\"", "\n" = "\\n")
for(var/targ in json_escape)
var/start = 1
while(start <= lentext(txt))
var/i = findtext(txt, targ, start)
if(!i)
break
- if(targ == "\n")
- txt = copytext(txt, 1, i) + "\\n" + copytext(txt, i+2)
- start = i + 1 // 1 character added
- if(targ == "'")
- txt = copytext(txt, 1, i) + "`" + copytext(txt, i+1) // apostrophies fuck shit up...
- start = i + 1 // 1 character added
- else
- txt = copytext(txt, 1, i) + "\\" + copytext(txt, i)
- start = i + 2 // 2 characters added
+ var/lrep = length(json_escape[targ])
+ txt = copytext(txt, 1, i) + json_escape[targ] + copytext(txt, i + length(targ))
+ start = i + lrep
return {""[txt]""}
is_associative(list/L)
for(var/key in L)
// if the key is a list that means it's actually an array of lists (stupid Byond...)
- if(!isnum(key) && !istype(key, /list))
+ if(!isnum(key) && !isnull(L[key]) && !istype(key, /list))
return TRUE
diff --git a/code/modules/nano/_JSON.dm b/code/modules/nano/_JSON.dm
index 554b21dafa3..95791899817 100644
--- a/code/modules/nano/_JSON.dm
+++ b/code/modules/nano/_JSON.dm
@@ -5,19 +5,13 @@ n_Json v11.3.21
proc
json2list(json)
var/static/json_reader/_jsonr = new()
- // N3X: Array support.
- if(dd_hasprefix(json,"\["))
- return _jsonr.ReadArray(_jsonr.ScanJson(json))
- else
- return _jsonr.ReadObject(_jsonr.ScanJson(json))
+ return _jsonr.ReadObject(_jsonr.ScanJson(json))
- list2json(list/L, var/cached_data = null)
+ list2json(list/L)
var/static/json_writer/_jsonw = new()
- // Detect if it's just a list of things, or an associative list
- // (Used to just assume associative, which broke things.)
- if(_jsonw.is_associative(L))
- return _jsonw.WriteObject(L, cached_data)
- else
- return _jsonw.write_array(L)
-
+ return _jsonw.write(L)
+ list2json_usecache(list/L)
+ var/static/json_writer/_jsonw = new()
+ _jsonw.use_cache = 1
+ return _jsonw.write(L)
diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm
index ad797db7d74..592644ba17b 100644
--- a/code/modules/nano/nanoui.dm
+++ b/code/modules/nano/nanoui.dm
@@ -57,8 +57,6 @@ nanoui is used to open and update nano browser uis
var/list/datum/nanoui/children = list()
var/datum/topic_state/custom_state = null
- var/cached_data = null
-
/**
* Create a new nanoui instance.
*
@@ -350,7 +348,7 @@ nanoui is used to open and update nano browser uis
template_data_json = list2json(templates)
var/list/send_data = get_send_data(initial_data)
- var/initial_data_json = list2json(send_data, cached_data)
+ var/initial_data_json = replacetext(list2json_usecache(send_data), "'", "'")
var/url_parameters_json = list2json(list("src" = "\ref[src]"))
@@ -432,19 +430,6 @@ nanoui is used to open and update nano browser uis
winset(user, window_id, "on-close=\"nanoclose [params]\"")
-/**
- * Appends already processed json txt to the list2json proc when setting initial-data and data pushes
- * Used for data that is fucking huge like manifests and camera lists that doesn't change often.
- * And we only want to process them when they change.
- * Fuck javascript
- *
- * @return nothing
- */
-/datum/nanoui/proc/load_cached_data(var/data)
- cached_data = data
- return
-
-
/**
* Push data to an already open UI window
*
@@ -458,7 +443,7 @@ nanoui is used to open and update nano browser uis
var/list/send_data = get_send_data(data)
//user << list2json(data) // used for debugging
- user << output(list2params(list(list2json(send_data,cached_data))),"[window_id].browser:receiveUpdateData")
+ user << output(list2params(list(list2json_usecache(send_data))),"[window_id].browser:receiveUpdateData")
/**
* This Topic() proc is called whenever a user clicks on a link within a Nano UI