mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 05:30:05 +01:00
Make NanoUI resistant to Topic spoofs
Move Topic() into a NanoUI-specific ui_act proc Update to @YotaXP's latest JSON code. Return focus to the mapwindow if a key is pressed in a NanoUI.
This commit is contained in:
@@ -149,22 +149,21 @@ Passive gate is similar to the regular pump except:
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/Topic(href, href_list)
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
if("pressure")
|
||||
switch(href_list["set"])
|
||||
switch(params["set"])
|
||||
if ("max")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
if ("custom")
|
||||
target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure)))
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
add_fingerprint(usr)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -157,22 +157,21 @@ Thus, the two variables affect pump operation are set in New():
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/pump/Topic(href,href_list)
|
||||
/obj/machinery/atmospherics/components/binary/pump/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
if("pressure")
|
||||
switch(href_list["set"])
|
||||
switch(params["set"])
|
||||
if ("max")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
if ("custom")
|
||||
target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure)))
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
add_fingerprint(usr)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -155,22 +155,21 @@ Thus, the two variables affect pump operation are set in New():
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/volume_pump/Topic(href,href_list)
|
||||
/obj/machinery/atmospherics/components/binary/volume_pump/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
if("transfer")
|
||||
switch(href_list["set"])
|
||||
switch(params)
|
||||
if ("max")
|
||||
transfer_rate = MAX_TRANSFER_RATE
|
||||
if ("custom")
|
||||
transfer_rate = max(0, min(MAX_TRANSFER_RATE, safe_input("Pressure control", "Enter new transfer rate (0-[MAX_TRANSFER_RATE] L/s)", transfer_rate)))
|
||||
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
|
||||
add_fingerprint(usr)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -137,10 +137,6 @@ Pipenet stuff; housekeeping
|
||||
T.assume_air(to_release)
|
||||
air_update_turf(1)
|
||||
|
||||
/*
|
||||
I think this is NanoUI?
|
||||
*/
|
||||
|
||||
/obj/machinery/atmospherics/components/proc/safe_input(var/title, var/text, var/default_set)
|
||||
var/new_value = input(usr,text,title,default_set) as num
|
||||
if(usr.canUseTopic(src))
|
||||
|
||||
@@ -182,23 +182,23 @@ Filter types:
|
||||
data["filter_type"] = filter_type
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/Topic(href, href_list)
|
||||
/obj/machinery/atmospherics/components/trinary/filter/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("power")
|
||||
on=!on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
if("pressure")
|
||||
switch(href_list["set"])
|
||||
switch(params["set"])
|
||||
if("max")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
if("custom")
|
||||
target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", target_pressure)))
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
if("filter")
|
||||
src.filter_type = text2num(href_list["mode"])
|
||||
src.filter_type = text2num(params["mode"])
|
||||
var/filtering_name = "nothing"
|
||||
switch(filter_type)
|
||||
if(FILTER_PLASMA)
|
||||
@@ -212,6 +212,5 @@ Filter types:
|
||||
if(FILTER_NITROUSOXIDE)
|
||||
filtering_name = "nitrous oxide"
|
||||
investigate_log("was set to filter [filtering_name] by [key_name(usr)]", "atmos")
|
||||
add_fingerprint(usr)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
@@ -147,31 +147,30 @@
|
||||
data["node2_concentration"] = round(node2_concentration*100)
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/Topic(href,href_list)
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
|
||||
if("pressure")
|
||||
switch(href_list["set"])
|
||||
switch(params["set"])
|
||||
if("max")
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
if("custom")
|
||||
target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", target_pressure)))
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
|
||||
if("node1")
|
||||
var/value = text2num(href_list["concentration"])
|
||||
var/value = text2num(params["concentration"])
|
||||
src.node1_concentration = max(0, min(1, src.node1_concentration + value))
|
||||
src.node2_concentration = max(0, min(1, src.node2_concentration - value))
|
||||
investigate_log("was set to [node1_concentration] % on node 1 by [key_name(usr)]", "atmos")
|
||||
if("node2")
|
||||
var/value = text2num(href_list["concentration"])
|
||||
var/value = text2num(params["concentration"])
|
||||
src.node2_concentration = max(0, min(1, src.node2_concentration + value))
|
||||
src.node1_concentration = max(0, min(1, src.node1_concentration - value))
|
||||
investigate_log("was set to [node2_concentration] % on node 2 by [key_name(usr)]", "atmos")
|
||||
add_fingerprint(usr)
|
||||
update_icon()
|
||||
return 1
|
||||
@@ -166,11 +166,11 @@
|
||||
data["beakerContents"] = beakerContents
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/Topic(href, href_list)
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("open")
|
||||
open_machine()
|
||||
if("close")
|
||||
@@ -186,7 +186,6 @@
|
||||
if(beaker)
|
||||
beaker.loc = get_step(loc, SOUTH)
|
||||
beaker = null
|
||||
add_fingerprint(usr)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#define writeJson(value) list2text(_jsonHelper.WriteValue(list(), (value)))
|
||||
@@ -387,7 +387,7 @@
|
||||
|
||||
data["thresholds"] = thresholds
|
||||
|
||||
/obj/machinery/alarm/Topic(href, href_list)
|
||||
/obj/machinery/alarm/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
@@ -400,17 +400,17 @@
|
||||
if (usr.has_unlimited_silicon_privilege && src.aidisabled)
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("toggleaccess")
|
||||
if(usr.has_unlimited_silicon_privilege && !wires.IsIndexCut(AALARM_WIRE_IDSCAN))
|
||||
locked = !locked
|
||||
if("adjust")
|
||||
var/device_id = href_list["id_tag"]
|
||||
switch(href_list["command"])
|
||||
var/device_id = params["id_tag"]
|
||||
switch(params["command"])
|
||||
if("set_external_pressure")
|
||||
var/input_pressure = input("Enter target pressure:", "Pressure Controls") as num|null
|
||||
if(isnum(input_pressure))
|
||||
send_signal(device_id, list(href_list["command"] = input_pressure))
|
||||
send_signal(device_id, list(params["command"] = input_pressure))
|
||||
if("reset_external_pressure")
|
||||
send_signal(device_id, list("set_external_pressure" = ONE_ATMOSPHERE))
|
||||
if(
|
||||
@@ -422,14 +422,14 @@
|
||||
"widenet",
|
||||
"scrubbing"
|
||||
)
|
||||
send_signal(device_id, list (href_list["command"] = text2num(href_list["val"])))
|
||||
send_signal(device_id, list (params["command"] = text2num(params["val"])))
|
||||
if ("excheck")
|
||||
send_signal(device_id, list ("checks" = text2num(href_list["val"])^1))
|
||||
send_signal(device_id, list ("checks" = text2num(params["val"])^1))
|
||||
if ("incheck")
|
||||
send_signal(device_id, list ("checks" = text2num(href_list["val"])^2))
|
||||
send_signal(device_id, list ("checks" = text2num(params["val"])^2))
|
||||
if("set_threshold")
|
||||
var/env = href_list["env"]
|
||||
var/varname = href_list["var"]
|
||||
var/env = params["env"]
|
||||
var/varname = params["var"]
|
||||
var/datum/tlv/tlv = TLV[env]
|
||||
var/newval = input("Enter [varname] for [env]:", "Alarm Triggers", tlv.vars[varname]) as num|null
|
||||
if (isnull(newval))
|
||||
@@ -446,16 +446,16 @@
|
||||
newval = round(newval,0.01)
|
||||
tlv.vars[varname] = newval
|
||||
if("screen")
|
||||
screen = text2num(href_list["screen"])
|
||||
screen = text2num(params["screen"])
|
||||
if("mode")
|
||||
mode = text2num(href_list["mode"])
|
||||
mode = text2num(params["mode"])
|
||||
apply_mode()
|
||||
if("alarm")
|
||||
if (alarm_area.atmosalert(2, src))
|
||||
if(alarm_area.atmosalert(2, src))
|
||||
post_alert(2)
|
||||
update_icon()
|
||||
if("reset")
|
||||
if (alarm_area.atmosalert(0, src))
|
||||
if(alarm_area.atmosalert(0, src))
|
||||
post_alert(0)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
@@ -298,11 +298,11 @@ update_flag
|
||||
data["holdingTank"]["tankPressure"] = round(holding.air_contents.return_pressure())
|
||||
return data
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/Topic(href, href_list)
|
||||
/obj/machinery/portable_atmospherics/canister/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("relabel")
|
||||
if (can_label)
|
||||
var/list/colors = list(\
|
||||
@@ -320,7 +320,7 @@ update_flag
|
||||
src.icon_state = colors[label]
|
||||
src.name = "canister: [label]"
|
||||
if("pressure")
|
||||
switch(href_list["set"])
|
||||
switch(params["set"])
|
||||
if("custom")
|
||||
var/custom = input(usr, "What rate do you set the regulator to? The dial reads from [CAN_MIN_RELEASE_PRESSURE] to [CAN_MAX_RELEASE_PRESSURE].") as null|num
|
||||
if(custom)
|
||||
|
||||
@@ -40,18 +40,18 @@
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/weapon/electronics/airlock/Topic(href, href_list)
|
||||
/obj/item/weapon/electronics/airlock/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("clear")
|
||||
accesses = list()
|
||||
one_access = 0
|
||||
if("one_access")
|
||||
one_access = !one_access
|
||||
if("set")
|
||||
var/access = text2num(href_list["access"])
|
||||
var/access = text2num(params["access"])
|
||||
if (!(access in accesses))
|
||||
accesses += access
|
||||
else
|
||||
|
||||
@@ -209,6 +209,13 @@ Class Procs:
|
||||
add_fingerprint(usr)
|
||||
return 0
|
||||
|
||||
/obj/machinery/ui_act(action, params)
|
||||
..()
|
||||
if(!can_be_used_by(usr))
|
||||
return 1
|
||||
add_fingerprint(usr)
|
||||
return 0
|
||||
|
||||
/obj/machinery/proc/can_be_used_by(mob/user)
|
||||
if(!interact_offline && stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
@@ -162,28 +162,28 @@
|
||||
ui = new(user, src, ui_key, "space_heater", name, 490, 340, state = physical_state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/space_heater/Topic(href, href_list)
|
||||
if(stat & BROKEN || ..())
|
||||
/obj/machinery/space_heater/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
mode = HEATER_MODE_STANDBY
|
||||
usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", "<span class='notice'>You switch [on ? "on" : "off"] \the [src].</span>")
|
||||
update_icon()
|
||||
if("mode")
|
||||
setMode = href_list["mode"]
|
||||
setMode = params["mode"]
|
||||
if("temp")
|
||||
if(panel_open)
|
||||
var/value
|
||||
if(href_list["set"] == "custom")
|
||||
if(params["set"] == "custom")
|
||||
value = input("Please input the target temperature", name) as num|null
|
||||
if(isnull(value))
|
||||
return
|
||||
value += T0C
|
||||
else
|
||||
value = targetTemperature + text2num(href_list["set"])
|
||||
value = targetTemperature + text2num(params["set"])
|
||||
|
||||
var/minTemp = max(settableTemperatureMedian - settableTemperatureRange, TCMB)
|
||||
var/maxTemp = settableTemperatureMedian + settableTemperatureRange
|
||||
|
||||
@@ -157,13 +157,13 @@
|
||||
data["maskConnected"] = 1
|
||||
return data
|
||||
|
||||
/obj/item/weapon/tank/Topic(href, href_list)
|
||||
/obj/item/weapon/tank/ui_act(action, params)
|
||||
if (..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("pressure")
|
||||
switch(href_list["set"])
|
||||
switch(params["set"])
|
||||
if("custom")
|
||||
var/custom = input(usr, "What rate do you set the regulator to? The dial reads from 0 to [TANK_MAX_RELEASE_PRESSURE].") as null|num
|
||||
if(isnum(custom))
|
||||
|
||||
@@ -173,6 +173,19 @@ You can set verify to TRUE if you want send() to sleep until the client has the
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
|
||||
|
||||
/datum/asset/simple/nanoui
|
||||
assets = list(
|
||||
"nanoui.lib.js" = 'nano/assets/nanoui.lib.js',
|
||||
"nanoui.main.js" = 'nano/assets/nanoui.main.js',
|
||||
"nanoui.templates.js" = 'nano/assets/nanoui.templates.js',
|
||||
"nanoui.lib.css" = 'nano/assets/nanoui.lib.css',
|
||||
"nanoui.common.css" = 'nano/assets/nanoui.common.css',
|
||||
"nanoui.generic.css" = 'nano/assets/nanoui.generic.css',
|
||||
"nanoui.nanotrasen.css" = 'nano/assets/nanoui.nanotrasen.css',
|
||||
"fontawesome-webfont.eot" = 'nano/assets/fontawesome-webfont.eot',
|
||||
"fontawesome-webfont.woff2" = 'nano/assets/fontawesome-webfont.woff2'
|
||||
)
|
||||
|
||||
/datum/asset/simple/pda
|
||||
assets = list(
|
||||
"pda_atmos.png" = 'icons/pda_icons/pda_atmos.png',
|
||||
@@ -219,18 +232,6 @@ You can set verify to TRUE if you want send() to sleep until the client has the
|
||||
"large_stamp-law.png" = 'icons/stamp_icons/large_stamp-law.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/nanoui
|
||||
assets = list(
|
||||
"nanoui.lib.js" = 'nano/assets/nanoui.lib.js',
|
||||
"nanoui.main.js" = 'nano/assets/nanoui.main.js',
|
||||
"nanoui.templates.js" = 'nano/assets/nanoui.templates.js',
|
||||
"nanoui.lib.css" = 'nano/assets/nanoui.lib.css',
|
||||
"nanoui.common.css" = 'nano/assets/nanoui.common.css',
|
||||
"nanoui.generic.css" = 'nano/assets/nanoui.generic.css',
|
||||
"nanoui.nanotrasen.css" = 'nano/assets/nanoui.nanotrasen.css',
|
||||
"fontawesome-webfont.eot" = 'nano/assets/fontawesome-webfont.eot',
|
||||
"fontawesome-webfont.woff2" = 'nano/assets/fontawesome-webfont.woff2'
|
||||
)
|
||||
|
||||
//Registers HTML Interface assets.
|
||||
/datum/asset/HTML_interface/register()
|
||||
|
||||
+201
-2
@@ -1,6 +1,14 @@
|
||||
/var/datum/jsonHelper/_jsonHelper = new // Solely as a namespace for procs.
|
||||
/* Usage:
|
||||
JSON.stringify(obj) - Converts lists and values into a JSON string.
|
||||
JSON.parse(json) - Converts a JSON string into lists and values.
|
||||
*/
|
||||
|
||||
/var/datum/jsonHelper/JSON = new // A namespace for procs.
|
||||
|
||||
// ************************************ WRITER ************************************
|
||||
/datum/jsonHelper/proc/stringify(value)
|
||||
return list2text(WriteValue(list(), value))
|
||||
|
||||
/datum/jsonHelper/proc/WriteValue(list/json, value)
|
||||
. = json
|
||||
if(isnum(value))
|
||||
@@ -82,4 +90,195 @@
|
||||
#undef Either
|
||||
#undef CannotBeFlat
|
||||
#undef CannotBeAssoc
|
||||
#undef BadList
|
||||
#undef BadList
|
||||
|
||||
// ************************************ READER ************************************
|
||||
#define aBackspace 0x08
|
||||
#define aTab 0x09
|
||||
#define aLineBreak 0x0A
|
||||
#define aVertTab 0x0B
|
||||
#define aFormFeed 0x0C
|
||||
#define aCarriageReturn 0x0D
|
||||
#define aSpace 0x20
|
||||
#define aZero 0x30
|
||||
#define aNonBreakSpace 0xA0
|
||||
|
||||
#define Advance if(++readPos > jsonLen) { curAscii = 0; curChar = "" } else { curAscii = text2ascii(json, readPos); curChar = ascii2text(curAscii) } // Deal with it.
|
||||
#define SkipWhitespace while(curAscii in whitespace) Advance
|
||||
#define AdvanceWS Advance; SkipWhitespace
|
||||
|
||||
/datum/jsonHelper/var
|
||||
readPos
|
||||
jsonLen
|
||||
json
|
||||
curAscii
|
||||
curChar
|
||||
static/list/whitespace = list(aTab, aLineBreak, aVertTab, aFormFeed, aCarriageReturn, aSpace, aNonBreakSpace)
|
||||
|
||||
/datum/jsonHelper/proc/parse(json)
|
||||
readPos = 0
|
||||
jsonLen = length(json)
|
||||
src.json = json
|
||||
curAscii = 0
|
||||
curChar = ""
|
||||
AdvanceWS
|
||||
var/value = ParseValue()
|
||||
if(readPos < jsonLen)
|
||||
throw EXCEPTION("Expected: End of JSON")
|
||||
return value
|
||||
|
||||
/datum/jsonHelper/proc/ParseValue()
|
||||
if(curChar == "\"")
|
||||
return ParseString()
|
||||
else if(curChar == "-" || (curAscii >= aZero && curAscii <= aZero + 9))
|
||||
return ParseNumber()
|
||||
else if(curChar == "{")
|
||||
return ParseObject()
|
||||
else if(curChar == "\[")
|
||||
return ParseArray()
|
||||
else if(curChar == "t")
|
||||
if(copytext(json, readPos, readPos+4) == "true")
|
||||
readPos += 3
|
||||
AdvanceWS
|
||||
return TRUE
|
||||
else
|
||||
throw EXCEPTION("Expected: 'true'")
|
||||
else if(curChar == "f")
|
||||
if(copytext(json, readPos, readPos+5) == "false")
|
||||
readPos += 4
|
||||
AdvanceWS
|
||||
return FALSE
|
||||
else
|
||||
throw EXCEPTION("Expected: 'false'")
|
||||
else if(curChar == "n")
|
||||
if(copytext(json, readPos, readPos+4) == "null")
|
||||
readPos += 3
|
||||
AdvanceWS
|
||||
return null
|
||||
else
|
||||
throw EXCEPTION("Expected: 'null'")
|
||||
else if(curChar == "")
|
||||
throw EXCEPTION("Unexpected: End of JSON")
|
||||
else
|
||||
throw EXCEPTION("Unexpected: '[curChar]'")
|
||||
|
||||
|
||||
|
||||
/datum/jsonHelper/proc/ParseString()
|
||||
ASSERT(curChar == "\"")
|
||||
Advance
|
||||
var/list/chars = list()
|
||||
while(readPos <= jsonLen)
|
||||
if(curChar == "\"")
|
||||
AdvanceWS
|
||||
return list2text(chars)
|
||||
else if(curChar == "\\")
|
||||
Advance
|
||||
switch(curChar)
|
||||
if("\"", "\\", "/")
|
||||
chars += ascii2text(curAscii)
|
||||
if("b")
|
||||
chars += ascii2text(aBackspace)
|
||||
if("f")
|
||||
chars += ascii2text(aFormFeed)
|
||||
if("n")
|
||||
chars += "\n"
|
||||
if("r")
|
||||
chars += ascii2text(aCarriageReturn) // Should we ignore these?
|
||||
if("t")
|
||||
chars += "\t"
|
||||
if("u")
|
||||
throw EXCEPTION("JSON \\uXXXX escape sequence not supported")
|
||||
else
|
||||
throw EXCEPTION("Invalid escape sequence")
|
||||
Advance
|
||||
else
|
||||
chars += ascii2text(curAscii)
|
||||
Advance
|
||||
throw EXCEPTION("Unterminated string")
|
||||
|
||||
/datum/jsonHelper/proc/ParseNumber()
|
||||
var/firstPos = readPos
|
||||
if(curChar == "-")
|
||||
Advance
|
||||
if(curAscii >= aZero + 1 && curAscii <= aZero + 9)
|
||||
do
|
||||
Advance
|
||||
while(curAscii >= aZero && curAscii <= aZero + 9)
|
||||
else if(curAscii == aZero)
|
||||
Advance
|
||||
else
|
||||
throw EXCEPTION("Expected: digit")
|
||||
|
||||
if(curChar == ".")
|
||||
Advance
|
||||
var/found = FALSE
|
||||
while(curAscii >= aZero && curAscii <= aZero + 9)
|
||||
found = TRUE
|
||||
Advance
|
||||
if(!found)
|
||||
throw EXCEPTION("Expected: digit")
|
||||
|
||||
if(curChar == "E" || curChar == "e")
|
||||
Advance
|
||||
var/found = FALSE
|
||||
if(curChar == "-")
|
||||
Advance
|
||||
else if(curChar == "+")
|
||||
Advance
|
||||
while(curAscii >= aZero && curAscii <= aZero + 9)
|
||||
found = TRUE
|
||||
Advance
|
||||
if(!found)
|
||||
throw EXCEPTION("Expected: digit")
|
||||
|
||||
SkipWhitespace
|
||||
return text2num(copytext(json, firstPos, readPos))
|
||||
|
||||
/datum/jsonHelper/proc/ParseObject()
|
||||
ASSERT(curChar == "{")
|
||||
var/list/object = list()
|
||||
AdvanceWS
|
||||
while(curChar == "\"")
|
||||
var/key = ParseString()
|
||||
if(curChar != ":")
|
||||
throw EXCEPTION("Expected: ':'")
|
||||
AdvanceWS
|
||||
object[key] = ParseValue()
|
||||
if(curChar == ",")
|
||||
AdvanceWS
|
||||
else
|
||||
break
|
||||
if(curChar != "}")
|
||||
throw EXCEPTION("Expected: string or '}'")
|
||||
AdvanceWS
|
||||
return object
|
||||
|
||||
/datum/jsonHelper/proc/ParseArray()
|
||||
ASSERT(curChar == "\[")
|
||||
var/list/array = list()
|
||||
AdvanceWS
|
||||
while(curChar != "]")
|
||||
array += list(ParseValue()) // Wrapped in a list in case ParseValue() returns a list.
|
||||
if(curChar == ",")
|
||||
AdvanceWS
|
||||
else
|
||||
break
|
||||
if(curChar != "]")
|
||||
throw EXCEPTION("Expected: ']'")
|
||||
AdvanceWS
|
||||
return array
|
||||
|
||||
#undef aBackspace
|
||||
#undef aTab
|
||||
#undef aLineBreak
|
||||
#undef aVertTab
|
||||
#undef aFormFeed
|
||||
#undef aCarriageReturn
|
||||
#undef aSpace
|
||||
#undef aZero
|
||||
#undef aNonBreakSpace
|
||||
|
||||
#undef Advance
|
||||
#undef SkipWhitespace
|
||||
#undef AdvanceWS
|
||||
@@ -27,6 +27,20 @@
|
||||
datum/topic_state/state = default_state)
|
||||
return -1 // Sorta implemented.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Called on a NanoUI when the UI receieves a href.
|
||||
* Think of this as Topic().
|
||||
*
|
||||
* required action string The action/button that has been invoked by the user.
|
||||
* required params list A list of parameters attached to the button.
|
||||
*
|
||||
* return bool If the UI should be updated or not.
|
||||
**/
|
||||
/atom/movable/proc/ui_act(action, list/params)
|
||||
return // Not implemented.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
|
||||
// Generate JSON.
|
||||
var/list/send_data = get_send_data(initial_data)
|
||||
var/initial_data_json = replacetext(writeJson(send_data), "'", "\\'")
|
||||
var/initial_data_json = replacetext(JSON.stringify(send_data), "'", "\\'")
|
||||
|
||||
// Generate the HTML document.
|
||||
return {"
|
||||
@@ -318,7 +318,7 @@
|
||||
var/list/send_data = get_send_data(data) // Get the data to send.
|
||||
|
||||
// Send the new data to the recieveUpdate() Javascript function.
|
||||
user << output(list2params(list(writeJson(send_data))), "[window_id].browser:receiveUpdate")
|
||||
user << output(list2params(list(JSON.stringify(send_data))), "[window_id].browser:receiveUpdate")
|
||||
|
||||
/**
|
||||
* private
|
||||
@@ -332,7 +332,10 @@
|
||||
if (status != NANO_INTERACTIVE || user != usr)
|
||||
return // If UI is not interactive or usr calling Topic is not the UI user.
|
||||
|
||||
var/update = src_object.Topic(href, href_list, 0, state) // Call Topic() on the src_object.
|
||||
var/action = href_list["nano"] // Pull the action out.
|
||||
href_list -= "nano"
|
||||
|
||||
var/update = src_object.ui_act(action, href_list, state) // Call Topic() on the src_object.
|
||||
|
||||
if (src_object && update)
|
||||
SSnano.update_uis(src_object) // If we have a src_object and its Topic() told us to update.
|
||||
|
||||
+10
-32
@@ -721,22 +721,8 @@
|
||||
|
||||
|
||||
/obj/machinery/power/apc/proc/can_use(mob/user, loud = 0) //used by attack_hand() and Topic()
|
||||
if (IsAdminGhost(user))
|
||||
if(IsAdminGhost(user))
|
||||
return 1
|
||||
if (user.stat)
|
||||
user << "<span class='warning'>You must be conscious to use [src]!</span>"
|
||||
return 0
|
||||
if(!user.client)
|
||||
return 0
|
||||
if(!user.IsAdvancedToolUser())
|
||||
user << "<span class='warning'>You don't have the dexterity to use [src]!</span>"
|
||||
return 0
|
||||
if(user.restrained())
|
||||
user << "<span class='warning'>You must have free hands to use [src].</span>"
|
||||
return 0
|
||||
if(user.lying)
|
||||
user << "<span class='warning'>You must stand to use [src]!</span>"
|
||||
return 0
|
||||
if(user.has_unlimited_silicon_privilege)
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
var/mob/living/silicon/robot/robot = user
|
||||
@@ -754,24 +740,16 @@
|
||||
else
|
||||
if ((!in_range(src, user) || !istype(src.loc, /turf)))
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = user
|
||||
if (istype(H))
|
||||
if(H.getBrainLoss() >= 60)
|
||||
H.visible_message("[H] stares cluelessly at [src] and drools.")
|
||||
return 0
|
||||
else if(prob(H.getBrainLoss()))
|
||||
user << "<span class='danger'>You momentarily forget how to use [src].</span>"
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/power/apc/Topic(href, href_list)
|
||||
/obj/machinery/power/apc/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!can_use(usr, 1))
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("lock")
|
||||
coverlocked = !coverlocked
|
||||
if ("breaker")
|
||||
@@ -782,18 +760,18 @@
|
||||
charging = 0
|
||||
update_icon()
|
||||
if("channel")
|
||||
if (href_list["eqp"])
|
||||
var/val = text2num(href_list["eqp"])
|
||||
if (params["eqp"])
|
||||
var/val = text2num(params["eqp"])
|
||||
equipment = setsubsystem(val)
|
||||
update_icon()
|
||||
update()
|
||||
else if (href_list["lgt"])
|
||||
var/val = text2num(href_list["lgt"])
|
||||
else if (params["lgt"])
|
||||
var/val = text2num(params["lgt"])
|
||||
lighting = setsubsystem(val)
|
||||
update_icon()
|
||||
update()
|
||||
else if (href_list["env"])
|
||||
var/val = text2num(href_list["env"])
|
||||
else if (params["env"])
|
||||
var/val = text2num(params["env"])
|
||||
environ = setsubsystem(val)
|
||||
update_icon()
|
||||
update()
|
||||
|
||||
@@ -350,11 +350,11 @@
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/machinery/power/smes/Topic(href, href_list)
|
||||
/obj/machinery/power/smes/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("tryinput")
|
||||
input_attempt = !input_attempt
|
||||
log_smes(usr.ckey)
|
||||
@@ -364,7 +364,7 @@
|
||||
log_smes(usr.ckey)
|
||||
update_icon()
|
||||
if("input")
|
||||
switch(href_list["set"])
|
||||
switch(params["set"])
|
||||
if("custom")
|
||||
var/custom = input(usr, "What rate would you like this SMES to attempt to charge at? Max is [input_level_max].") as null|num
|
||||
if(custom)
|
||||
@@ -380,7 +380,7 @@
|
||||
input_level = Clamp(input_level, 0, input_level_max)
|
||||
log_smes(usr.ckey)
|
||||
if("output")
|
||||
switch(href_list["set"])
|
||||
switch(params["set"])
|
||||
if("custom")
|
||||
var/custom = input(usr, "What rate would you like this SMES to attempt to output at? Max is [output_level_max].") as null|num
|
||||
if(custom)
|
||||
|
||||
@@ -437,24 +437,24 @@
|
||||
targetdir = (targetdir + trackrate/abs(trackrate) + 360) % 360 //... do it
|
||||
nexttime += 36000/abs(trackrate) //reset the counter for the next 1°
|
||||
|
||||
/obj/machinery/power/solar_control/Topic(href, href_list)
|
||||
/obj/machinery/power/solar_control/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("control")
|
||||
if(href_list["cdir"])
|
||||
src.cdir = dd_range(0,359,(360+src.cdir+text2num(href_list["cdir"]))%360)
|
||||
if(params["cdir"])
|
||||
src.cdir = dd_range(0,359,(360+src.cdir+text2num(params["cdir"]))%360)
|
||||
src.targetdir = src.cdir
|
||||
if(track == 2) //manual update, so losing auto-tracking
|
||||
track = 0
|
||||
spawn(1)
|
||||
set_panels(cdir)
|
||||
if(href_list["tdir"])
|
||||
src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(href_list["tdir"]))
|
||||
if(params["tdir"])
|
||||
src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(params["tdir"]))
|
||||
if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
|
||||
if("tracking")
|
||||
track = text2num(href_list["mode"])
|
||||
track = text2num(params["mode"])
|
||||
if(track == 2)
|
||||
if(connected_tracker)
|
||||
connected_tracker.set_angle(SSsun.angle)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
icon_state = "dispenser"
|
||||
use_power = 1
|
||||
idle_power_usage = 40
|
||||
interact_offline = 1
|
||||
var/energy = 100
|
||||
var/max_energy = 100
|
||||
var/amount = 30
|
||||
@@ -122,27 +123,27 @@
|
||||
data["chemicals"] = chemicals
|
||||
return data
|
||||
|
||||
/obj/machinery/chem_dispenser/Topic(href, href_list)
|
||||
/obj/machinery/chem_dispenser/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("amount")
|
||||
amount = round(text2num(href_list["set"]), 5) // round to nearest 5
|
||||
amount = round(text2num(params["set"]), 5) // round to nearest 5
|
||||
if (amount < 0) // Since the user can actually type the commands himself, some sanity checking
|
||||
amount = 0
|
||||
if (amount > 100)
|
||||
amount = 100
|
||||
if("dispense")
|
||||
if(beaker && dispensable_reagents.Find(href_list["reagent"]))
|
||||
if(beaker && dispensable_reagents.Find(params["reagent"]))
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
var/space = R.maximum_volume - R.total_volume
|
||||
|
||||
R.add_reagent(href_list["reagent"], min(amount, energy * 10, space))
|
||||
R.add_reagent(params["reagent"], min(amount, energy * 10, space))
|
||||
energy = max(energy - min(amount, energy * 10, space) / 10, 0)
|
||||
if("remove")
|
||||
if(beaker)
|
||||
var/amount = text2num(href_list["amount"])
|
||||
var/amount = text2num(params["amount"])
|
||||
if(isnum(amount) && (amount > 0) && (amount in beaker.possible_transfer_amounts))
|
||||
beaker.reagents.remove_all(amount)
|
||||
if("eject")
|
||||
@@ -150,7 +151,6 @@
|
||||
beaker.loc = loc
|
||||
beaker = null
|
||||
overlays.Cut()
|
||||
add_fingerprint(usr)
|
||||
return 1
|
||||
|
||||
/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/user, params)
|
||||
|
||||
@@ -77,18 +77,17 @@
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/chem_heater/Topic(href, href_list)
|
||||
/obj/machinery/chem_heater/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(href_list["nano"])
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
if("temperature")
|
||||
desired_temp = Clamp(input("Please input the target temperature", name) as num, 0, 1000)
|
||||
if("eject")
|
||||
eject_beaker()
|
||||
add_fingerprint(usr)
|
||||
return 1
|
||||
|
||||
/obj/machinery/chem_heater/interact(mob/user)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,34 +0,0 @@
|
||||
class @Handlers
|
||||
constructor: (@bus, @fragment = document) ->
|
||||
@bus.on "rendered", @updateStatus
|
||||
@bus.on "rendered", @updateLinks
|
||||
@bus.on "rendered", @attachLinks
|
||||
|
||||
updateStatus: (data) =>
|
||||
statusicons = @fragment.queryAll ".statusicon"
|
||||
statusicons.forEach (statusicon) ->
|
||||
statusicon.className = statusicon.className.replace /good|bad|average/g, ""
|
||||
switch data.config.status
|
||||
when NANO.INTERACTIVE
|
||||
klass = "good"
|
||||
when NANO.UPDATE
|
||||
klass = "average"
|
||||
else
|
||||
klass = "bad"
|
||||
statusicon.classList.add klass
|
||||
|
||||
updateLinks: (data) =>
|
||||
links = @fragment.queryAll ".link"
|
||||
if data.config.status isnt NANO.INTERACTIVE
|
||||
links.forEach (element) ->
|
||||
element.className = "link disabled"
|
||||
|
||||
attachLinks: (data) =>
|
||||
onClick = ->
|
||||
action = @data "action"
|
||||
params = JSON.parse @data "params"
|
||||
if action? and params? and data.config.status is NANO.INTERACTIVE
|
||||
nanoui.bycall action, params
|
||||
|
||||
@fragment.queryAll(".link.active").forEach (link) ->
|
||||
link.on "click", onClick
|
||||
@@ -2,7 +2,6 @@ document.when "ready", =>
|
||||
coderbus = {}
|
||||
|
||||
@nanoui = new @NanoUI coderbus, document
|
||||
@handlers = new @Handlers coderbus, document
|
||||
@nanowindow = new @Window coderbus, document
|
||||
|
||||
coderbus.emit "memes"
|
||||
|
||||
@@ -59,7 +59,7 @@ class @NanoUI
|
||||
@data = @initialData
|
||||
@bus.emit "initialized", data
|
||||
|
||||
bycall: (action, params = {}) =>
|
||||
act: (action, params = {}) =>
|
||||
params.src = @data.config.ref
|
||||
params.nano = action
|
||||
location.href = util.href null, params
|
||||
|
||||
@@ -12,6 +12,9 @@ class @Window
|
||||
@attachDrag()
|
||||
@attachResize()
|
||||
|
||||
@bus.on "rendered", @updateStatus
|
||||
@bus.on "rendered", @updateLinks
|
||||
@bus.on "rendered", @attachLinks
|
||||
@fragment.on "keydown", @focusMap # If we get input, return focus.
|
||||
|
||||
setPos: (x, y) ->
|
||||
@@ -86,3 +89,32 @@ class @Window
|
||||
|
||||
@xResize = event.screenX
|
||||
@yResize = event.screenY
|
||||
|
||||
updateStatus: (data) =>
|
||||
statusicons = @fragment.queryAll ".statusicon"
|
||||
statusicons.forEach (statusicon) ->
|
||||
statusicon.className = statusicon.className.replace /good|bad|average/g, ""
|
||||
switch data.config.status
|
||||
when NANO.INTERACTIVE
|
||||
klass = "good"
|
||||
when NANO.UPDATE
|
||||
klass = "average"
|
||||
else
|
||||
klass = "bad"
|
||||
statusicon.classList.add klass
|
||||
|
||||
updateLinks: (data) =>
|
||||
links = @fragment.queryAll ".link"
|
||||
if data.config.status isnt NANO.INTERACTIVE
|
||||
links.forEach (element) ->
|
||||
element.className = "link disabled"
|
||||
|
||||
attachLinks: (data) =>
|
||||
onClick = ->
|
||||
action = @data "action"
|
||||
params = JSON.parse @data "params"
|
||||
if action? and params? and data.config.status is NANO.INTERACTIVE
|
||||
nanoui.act action, params
|
||||
|
||||
@fragment.queryAll(".link.active").forEach (link) ->
|
||||
link.on "click", onClick
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "code\__DEFINES\genetics.dm"
|
||||
#include "code\__DEFINES\hud.dm"
|
||||
#include "code\__DEFINES\is_helpers.dm"
|
||||
#include "code\__DEFINES\json.dm"
|
||||
#include "code\__DEFINES\machines.dm"
|
||||
#include "code\__DEFINES\math.dm"
|
||||
#include "code\__DEFINES\misc.dm"
|
||||
|
||||
Reference in New Issue
Block a user