diff --git a/code/ATMOSPHERICS/components/omni_devices/filter.dm b/code/ATMOSPHERICS/components/omni_devices/filter.dm new file mode 100644 index 00000000000..1d1d335cb8a --- /dev/null +++ b/code/ATMOSPHERICS/components/omni_devices/filter.dm @@ -0,0 +1,282 @@ +//-------------------------------------------- +// Gas filter - omni variant +//-------------------------------------------- +/obj/machinery/atmospherics/omni/filter + name = "omni gas filter" + icon_state = "map_filter" + + var/list/filters = new() + var/datum/omni_port/input + var/datum/omni_port/output + +/obj/machinery/atmospherics/omni/filter/Del() + input = null + output = null + filters.Cut() + ..() + +/obj/machinery/atmospherics/omni/filter/sort_ports() + for(var/datum/omni_port/P in ports) + if(P.update) + if(output == P) + output = null + if(input == P) + input = null + if(filters.Find(P)) + filters -= P + + P.air.volume = 200 + switch(P.mode) + if(ATM_INPUT) + input = P + if(ATM_OUTPUT) + output = P + if(ATM_O2 to ATM_N2O) + filters += P + +/obj/machinery/atmospherics/omni/filter/error_check() + if(!input || !output || !filters) + return 1 + if(filters.len < 1 || filters.len > 2) //requires 1 or 2 filters ~otherwise why are you using a filter? + return 1 + + return 0 + +/obj/machinery/atmospherics/omni/filter/process() + ..() + if(!on) + return 0 + + if(!input || !output) + return + + var/datum/gas_mixture/output_air = output.air //BYOND doesn't like referencing "output.air.return_pressure()" so we need to make a direct reference + var/datum/gas_mixture/input_air = input.air // it's completely happy with them if they're in a loop though i.e. "P.air.return_pressure()"... *shrug* + + var/output_pressure = output_air.return_pressure() + + if(output_pressure >= target_pressure) + return + for(var/datum/omni_port/P in filters) + if(P.air.return_pressure() >= target_pressure) + return + + var/pressure_delta = target_pressure - output_pressure + + if(input_air.return_temperature() > 0) + input.transfer_moles = pressure_delta * output_air.volume / (input_air.return_temperature() * R_IDEAL_GAS_EQUATION) + + if(input.transfer_moles > 0) + var/datum/gas_mixture/removed = input_air.remove(input.transfer_moles) + + if(!removed) + return + + for(var/datum/omni_port/P in filters) + var/datum/gas_mixture/filtered_out = new + filtered_out.temperature = removed.return_temperature() + + switch(P.mode) + if(ATM_O2) + filtered_out.oxygen = removed.oxygen + removed.oxygen = 0 + if(ATM_N2) + filtered_out.nitrogen = removed.nitrogen + removed.nitrogen = 0 + if(ATM_CO2) + filtered_out.carbon_dioxide = removed.carbon_dioxide + removed.carbon_dioxide = 0 + if(ATM_P) + filtered_out.phoron = removed.phoron + removed.phoron = 0 + if(ATM_N2O) + if(removed.trace_gases.len>0) + for(var/datum/gas/sleeping_agent/trace_gas in removed.trace_gases) + if(istype(trace_gas)) + removed.trace_gases -= trace_gas + filtered_out.trace_gases += trace_gas + else + filtered_out = null + + P.air.merge(filtered_out) + if(P.network) + P.network.update = 1 + + output_air.merge(removed) + if(output.network) + output.network.update = 1 + + input.transfer_moles = 0 + if(input.network) + input.network.update = 1 + + return + +/obj/machinery/atmospherics/omni/filter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + usr.set_machine(src) + + var/list/data = new() + + data = build_uidata() + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + + if (!ui) + ui = new(user, src, ui_key, "omni_filter.tmpl", "Omni Filter Control", 330, 330) + ui.set_initial_data(data) + + ui.open() + +/obj/machinery/atmospherics/omni/filter/proc/build_uidata() + var/list/data = new() + + data["power"] = on + data["config"] = configuring + + var/portData[0] + for(var/datum/omni_port/P in ports) + if(!configuring && P.mode == 0) + continue + + var/input = 0 + var/output = 0 + var/filter = 1 + var/f_type = null + switch(P.mode) + if(ATM_INPUT) + input = 1 + filter = 0 + if(ATM_OUTPUT) + output = 1 + filter = 0 + if(ATM_O2 to ATM_N2O) + f_type = mode_send_switch(P.mode) + + portData[++portData.len] = list("dir" = dir_name(P.dir, capitalize = 1), \ + "input" = input, \ + "output" = output, \ + "filter" = filter, \ + "f_type" = f_type) + + if(portData.len) + data["ports"] = portData + if(output) + data["pressure"] = target_pressure + + return data + +/obj/machinery/atmospherics/omni/filter/proc/mode_send_switch(var/mode = ATM_NONE) + switch(mode) + if(ATM_O2) + return "Oxygen" + if(ATM_N2) + return "Nitrogen" + if(ATM_CO2) + return "Carbon Dioxide" + if(ATM_P) + return "Phoron" //*cough* Plasma *cough* + if(ATM_N2O) + return "Nitrous Oxide" + else + return null + +/obj/machinery/atmospherics/omni/filter/Topic(href, href_list) + if(..()) return + switch(href_list["command"]) + if("power") + if(!configuring) + on = !on + else + on = 0 + if("configure") + configuring = !configuring + if(configuring) + on = 0 + + //only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on + if(configuring && !on) + switch(href_list["command"]) + if("set_pressure") + var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",target_pressure) as num + target_pressure = between(0, new_pressure, 4500) + if("switch_mode") + switch_mode(dir_flag(href_list["dir"]), mode_return_switch(href_list["mode"])) + if("switch_filter") + var/new_filter = input(usr,"Select filter mode:","Change filter",href_list["mode"]) in list("None", "Oxygen", "Nitrogen", "Carbon Dioxide", "Phoron", "Nitrous Oxide") + switch_filter(dir_flag(href_list["dir"]), mode_return_switch(new_filter)) + + update_icon() + nanomanager.update_uis(src) + return + +/obj/machinery/atmospherics/omni/filter/proc/mode_return_switch(var/mode) + switch(mode) + if("Oxygen") + return ATM_O2 + if("Nitrogen") + return ATM_N2 + if("Carbon Dioxide") + return ATM_CO2 + if("Phoron") + return ATM_P + if("Nitrous Oxide") + return ATM_N2O + if("in") + return ATM_INPUT + if("out") + return ATM_OUTPUT + if("None") + return ATM_NONE + else + return null + +/obj/machinery/atmospherics/omni/filter/proc/switch_filter(var/dir, var/mode) + //check they aren't trying to disable the input or output ~this can only happen if they hack the cached tmpl file + for(var/datum/omni_port/P in ports) + if(P.dir == dir) + if(P.mode == ATM_INPUT || P.mode == ATM_OUTPUT) + return + + switch_mode(dir, mode) + +/obj/machinery/atmospherics/omni/filter/proc/switch_mode(var/port, var/mode) + if(mode == null || !port) + return + var/datum/omni_port/target_port = null + var/list/other_ports = new() + + for(var/datum/omni_port/P in ports) + if(P.dir == port) + target_port = P + else + other_ports += P + + var/previous_mode = null + if(target_port) + previous_mode = target_port.mode + target_port.mode = mode + if(target_port.mode != previous_mode) + handle_port_change(target_port) + else + return + else + return + + for(var/datum/omni_port/P in other_ports) + if(P.mode == mode) + var/old_mode = P.mode + P.mode = previous_mode + if(P.mode != old_mode) + handle_port_change(P) + + update_ports() + +/obj/machinery/atmospherics/omni/filter/proc/handle_port_change(var/datum/omni_port/P) + switch(P.mode) + if(ATM_NONE) + initialize_directions &= ~P.dir + P.disconnect() + else + initialize_directions |= P.dir + P.connect() + P.update = 1 \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/omni_devices/mixer.dm b/code/ATMOSPHERICS/components/omni_devices/mixer.dm new file mode 100644 index 00000000000..3b5dd1780fe --- /dev/null +++ b/code/ATMOSPHERICS/components/omni_devices/mixer.dm @@ -0,0 +1,301 @@ +//-------------------------------------------- +// Gas mixer - omni variant +//-------------------------------------------- +/obj/machinery/atmospherics/omni/mixer + name = "omni gas mixer" + icon_state = "map_mixer" + + var/list/inputs = new() + var/datum/omni_port/output + + //setup tags for initial concentration values (must be decimal) + var/tag_north_con + var/tag_south_con + var/tag_east_con + var/tag_west_con + +/obj/machinery/atmospherics/omni/mixer/New() + ..() + if(mapper_set()) + var/con = 0 + for(var/datum/omni_port/P in ports) + switch(P.dir) + if(NORTH) + if(tag_north_con && tag_north == 1) + P.concentration = tag_north_con + con += max(0, tag_north_con) + if(SOUTH) + if(tag_south_con && tag_south == 1) + P.concentration = tag_south_con + con += max(0, tag_south_con) + if(EAST) + if(tag_east_con && tag_east == 1) + P.concentration = tag_east_con + con += max(0, tag_east_con) + if(WEST) + if(tag_west_con && tag_west == 1) + P.concentration = tag_west_con + con += max(0, tag_west_con) + + //mappers who are bad at maths will be punished (total concentration must be 100%) + if(con != 1) + tag_north_con = null + tag_south_con = null + tag_east_con = null + tag_west_con = null + +/obj/machinery/atmospherics/omni/mixer/Del() + inputs.Cut() + output = null + ..() + +/obj/machinery/atmospherics/omni/mixer/sort_ports() + for(var/datum/omni_port/P in ports) + if(P.update) + if(output == P) + output = null + if(inputs.Find(P)) + inputs -= P + + P.air.volume = 200 + switch(P.mode) + if(ATM_INPUT) + inputs += P + if(ATM_OUTPUT) + output = P + + if(!mapper_set()) + for(var/datum/omni_port/P in inputs) + P.concentration = 1 / max(1, inputs.len) + + if(output) + output.air.volume *= 0.75 * inputs.len + output.concentration = 1 + +/obj/machinery/atmospherics/omni/mixer/proc/mapper_set() + return (tag_north_con || tag_south_con || tag_east_con || tag_west_con) + +/obj/machinery/atmospherics/omni/mixer/error_check() + if(!output || !inputs) + return 1 + if(inputs.len < 2 || inputs.len > 3) //requires 2 or 3 inputs ~otherwise why are you using a mixer? + return 1 + + return 0 + +/obj/machinery/atmospherics/omni/mixer/process() + ..() + if(!on) + return 0 + + var/datum/gas_mixture/output_air = output.air + var/output_pressure = output_air.return_pressure() + + + if(output_pressure >= target_pressure * 0.999) + //No need to mix if target is already full! - 0.1% margin of error so we minimize processing minor gas volumes + return 1 + + //Calculate necessary moles to transfer using PV=nRT + + var/pressure_delta = target_pressure - output_pressure + + for(var/datum/omni_port/P in inputs) + if(P.air.return_temperature() > 0) + P.transfer_moles = (P.concentration * pressure_delta) * output_air.return_volume() / (P.air.return_temperature() * R_IDEAL_GAS_EQUATION) + + var/ratio_check = null + + for(var/datum/omni_port/P in inputs) + if(!P.transfer_moles) + return + if(P.air.total_moles() < P.transfer_moles) + ratio_check = 1 + continue + + if(ratio_check) + var/list/ratio_list = new() + for(var/datum/omni_port/P in inputs) + ratio_list.Add(P.air.total_moles() / P.transfer_moles) + + var/ratio = min(ratio_list) + + for(var/datum/omni_port/P in inputs) + P.transfer_moles *= ratio + + + + for(var/datum/omni_port/P in inputs) + if(P.transfer_moles > 0) + output_air.merge(P.air.remove(P.transfer_moles)) + if(P.network) + P.network.update = 1 + P.transfer_moles = 0 + + if(output.network) + output.network.update = 1 + + return 1 + +/obj/machinery/atmospherics/omni/mixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + usr.set_machine(src) + + var/list/data = new() + + data = build_uidata() + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + + if (!ui) + ui = new(user, src, ui_key, "omni_mixer.tmpl", "Omni Mixer Control", 360, 330) + ui.set_initial_data(data) + + ui.open() + +/obj/machinery/atmospherics/omni/mixer/proc/build_uidata() + var/list/data = new() + + data["power"] = on + data["config"] = configuring + + var/portData[0] + for(var/datum/omni_port/P in ports) + if(!configuring && P.mode == 0) + continue + + var/input = 0 + var/output = 0 + switch(P.mode) + if(ATM_INPUT) + input = 1 + if(ATM_OUTPUT) + output = 1 + + portData[++portData.len] = list("dir" = dir_name(P.dir, capitalize = 1), \ + "concentration" = P.concentration, \ + "input" = input, \ + "output" = output, \ + "con_lock" = P.con_lock) + + if(portData.len) + data["ports"] = portData + if(output) + data["pressure"] = target_pressure + + return data + +/obj/machinery/atmospherics/omni/mixer/Topic(href, href_list) + if(..()) return + + switch(href_list["command"]) + if("power") + if(!configuring) + on = !on + else + on = 0 + if("configure") + configuring = !configuring + if(configuring) + on = 0 + + //only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on + if(configuring && !on) + switch(href_list["command"]) + if("set_pressure") + var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",target_pressure) as num + target_pressure = between(0, new_pressure, 4500) + if("switch_mode") + switch_mode(dir_flag(href_list["dir"]), href_list["mode"]) + if("switch_con") + change_concentration(dir_flag(href_list["dir"])) + if("switch_conlock") + con_lock(dir_flag(href_list["dir"])) + + update_icon() + nanomanager.update_uis(src) + return + +/obj/machinery/atmospherics/omni/mixer/proc/switch_mode(var/port = NORTH, var/mode = ATM_NONE) + if(mode != ATM_INPUT && mode != ATM_OUTPUT) + switch(mode) + if("in") + mode = ATM_INPUT + if("out") + mode = ATM_OUTPUT + else + mode = ATM_NONE + + for(var/datum/omni_port/P in ports) + var/old_mode = P.mode + if(P.dir == port) + switch(mode) + if(ATM_INPUT) + if(P.mode == ATM_OUTPUT) + return + P.mode = mode + if(ATM_OUTPUT) + P.mode = mode + if(ATM_NONE) + if(P.mode == ATM_OUTPUT) + return + if(P.mode == ATM_INPUT && inputs.len > 2) + P.mode = mode + else if(P.mode == ATM_OUTPUT && mode == ATM_OUTPUT) + P.mode = ATM_INPUT + if(P.mode != old_mode) + switch(P.mode) + if(ATM_NONE) + initialize_directions &= ~P.dir + P.disconnect() + else + initialize_directions |= P.dir + P.connect() + P.update = 1 + + update_ports() + +/obj/machinery/atmospherics/omni/mixer/proc/change_concentration(var/port = NORTH) + tag_north_con = null + tag_south_con = null + tag_east_con = null + tag_west_con = null + + var/old_con = 0 + var/non_locked = 0 + var/remain_con = 1 + + for(var/datum/omni_port/P in inputs) + if(P.dir == port) + old_con = P.concentration + else if(!P.con_lock) + non_locked++ + else + remain_con -= P.concentration + + //return if no adjustable ports + if(non_locked < 1) + return + + var/new_con = (input(usr,"Enter a new concentration (0-[round(remain_con * 100, 0.5)])%","Concentration control", min(remain_con, old_con)*100) as num) / 100 + + //cap it between 0 and the max remaining concentration + new_con = between(0, new_con, remain_con) + + //new_con = min(remain_con, new_con) + + //clamp remaining concentration so we don't go into negatives + remain_con = max(0, remain_con - new_con) + + //distribute remaining concentration between unlocked ports evenly + remain_con /= max(1, non_locked) + + for(var/datum/omni_port/P in inputs) + if(P.dir == port) + P.concentration = new_con + else if(!P.con_lock) + P.concentration = remain_con + +/obj/machinery/atmospherics/omni/mixer/proc/con_lock(var/port = NORTH) + for(var/datum/omni_port/P in inputs) + if(P.dir == port) + P.con_lock = !P.con_lock \ No newline at end of file diff --git a/code/WorkInProgress/Chinsky/overmap/ships/computers/engine_control.dm b/code/WorkInProgress/Chinsky/overmap/ships/computers/engine_control.dm index 07d6a4579be..41f2c4cdf9d 100644 --- a/code/WorkInProgress/Chinsky/overmap/ships/computers/engine_control.dm +++ b/code/WorkInProgress/Chinsky/overmap/ships/computers/engine_control.dm @@ -30,7 +30,7 @@ ui_interact(user) -/obj/machinery/computer/engines/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/computer/engines/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) if(!linked) return @@ -50,7 +50,7 @@ data["engines_info"] = enginfo - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "engines_control.tmpl", "[linked.name] Engines Control", 380, 530) ui.set_initial_data(data) diff --git a/code/WorkInProgress/Chinsky/overmap/ships/computers/helm.dm b/code/WorkInProgress/Chinsky/overmap/ships/computers/helm.dm index f81e569abcf..d78934f5749 100644 --- a/code/WorkInProgress/Chinsky/overmap/ships/computers/helm.dm +++ b/code/WorkInProgress/Chinsky/overmap/ships/computers/helm.dm @@ -70,7 +70,7 @@ ui_interact(user) -/obj/machinery/computer/helm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/computer/helm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) if(!linked) return @@ -101,7 +101,7 @@ data["locations"] = locations - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "helm.tmpl", "[linked.name] Helm Control", 380, 530) ui.set_initial_data(data) diff --git a/code/WorkInProgress/Chinsky/overmap/ships/computers/shuttle.dm b/code/WorkInProgress/Chinsky/overmap/ships/computers/shuttle.dm index c63ad2d763a..4ebc9469da3 100644 --- a/code/WorkInProgress/Chinsky/overmap/ships/computers/shuttle.dm +++ b/code/WorkInProgress/Chinsky/overmap/ships/computers/shuttle.dm @@ -44,7 +44,7 @@ var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag] return shuttle && destination && get_dist(home, destination) <= shuttle.range -/obj/machinery/computer/shuttle_control/explore/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/computer/shuttle_control/explore/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag] if (!istype(shuttle)) @@ -103,7 +103,7 @@ "can_force" = can_go && shuttle.can_force(), ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "shuttle_control_console_exploration.tmpl", "[shuttle_tag] Shuttle Control", 470, 310) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 4ddb6d39cc9..1d2c06a2043 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -416,7 +416,7 @@ * * @return nothing */ -/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) if(user == connected.occupant || user.stat) return @@ -496,7 +496,7 @@ data["beakerVolume"] += R.volume // 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) + 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 diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 799f7f7da90..333a5d48f1e 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -39,7 +39,7 @@ var/global/datum/controller/gameticker/ticker /datum/controller/gameticker/proc/pregame() do - pregame_timeleft = 180 + pregame_timeleft = 20 world << "Welcome to the pre-game lobby!" world << "Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds" while(current_state == GAME_STATE_PREGAME) diff --git a/code/game/machinery/Freezer.dm b/code/game/machinery/Freezer.dm index 7de58c6f220..3b3cfe87543 100644 --- a/code/game/machinery/Freezer.dm +++ b/code/game/machinery/Freezer.dm @@ -44,7 +44,7 @@ /obj/machinery/atmospherics/unary/cold_sink/freezer/attack_hand(mob/user as mob) src.ui_interact(user) -/obj/machinery/atmospherics/unary/cold_sink/freezer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/atmospherics/unary/cold_sink/freezer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) // this is the data which will be sent to the ui var/data[0] data["on"] = on ? 1 : 0 @@ -62,7 +62,7 @@ data["gasTemperatureClass"] = temp_class // 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) + 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 @@ -137,7 +137,7 @@ /obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_hand(mob/user as mob) src.ui_interact(user) -/obj/machinery/atmospherics/unary/heat_reservoir/heater/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/atmospherics/unary/heat_reservoir/heater/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) // this is the data which will be sent to the ui var/data[0] data["on"] = on ? 1 : 0 @@ -153,7 +153,7 @@ data["gasTemperatureClass"] = temp_class // 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) + 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 diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 5ff49a1dcc9..4f91b933fbb 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -251,7 +251,7 @@ update_flag /obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob) return src.ui_interact(user) -/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) if (src.destroyed) return @@ -271,7 +271,7 @@ update_flag data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure())) // 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) + 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 diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index cbc1dba9af1..f75296796c0 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -80,7 +80,7 @@ if(stat & (NOPOWER|BROKEN)) return ui_interact(user) -/obj/machinery/computer/card/ui_interact(mob/user, ui_key="main", datum/nanoui/ui=null) +/obj/machinery/computer/card/ui_interact(mob/user, ui_key="main", var/datum/nanoui/ui = null, var/force_open = 1) user.set_machine(src) var/data[0] @@ -134,7 +134,7 @@ data["regions"] = regions - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "identification_computer.tmpl", src.name, 600, 700) ui.set_initial_data(data) diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index 528815ad07e..d7595e1a29d 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -57,7 +57,7 @@ /obj/machinery/computer/crew/interact(mob/user) ui_interact(user) -/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) if(stat & (BROKEN|NOPOWER)) return user.set_machine(src) @@ -97,7 +97,7 @@ data["crewmembers"] = crewmembers - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if(!ui) ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 600) ui.set_initial_data(data) diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 7815c2833ff..49e4d912d78 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -123,7 +123,7 @@ * * @return nothing */ -/obj/machinery/atmospherics/unary/cryo_cell/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/atmospherics/unary/cryo_cell/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) if(user == occupant || user.stat) return @@ -171,7 +171,7 @@ data["beakerVolume"] += R.volume // 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) + 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 diff --git a/code/game/machinery/embedded_controller/airlock_controllers.dm b/code/game/machinery/embedded_controller/airlock_controllers.dm index 4a48558f875..96177f9a9df 100644 --- a/code/game/machinery/embedded_controller/airlock_controllers.dm +++ b/code/game/machinery/embedded_controller/airlock_controllers.dm @@ -17,7 +17,7 @@ /obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller name = "Advanced Airlock Controller" -/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] data = list( @@ -29,7 +29,7 @@ "secure" = program.memory["secure"] ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "advanced_airlock_console.tmpl", name, 470, 290) @@ -75,7 +75,7 @@ name = "Airlock Controller" tag_secure = 1 -/obj/machinery/embedded_controller/radio/airlock/airlock_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/embedded_controller/radio/airlock/airlock_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] data = list( @@ -85,7 +85,7 @@ "processing" = program.memory["processing"], ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "simple_airlock_console.tmpl", name, 470, 290) @@ -140,7 +140,7 @@ else icon_state = "access_control_off" -/obj/machinery/embedded_controller/radio/airlock/access_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/embedded_controller/radio/airlock/access_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] data = list( @@ -149,7 +149,7 @@ "processing" = program.memory["processing"] ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "door_access_console.tmpl", name, 330, 220) diff --git a/code/game/machinery/embedded_controller/airlock_docking_controller.dm b/code/game/machinery/embedded_controller/airlock_docking_controller.dm index 0e9877d797e..cb69c4d5bf5 100644 --- a/code/game/machinery/embedded_controller/airlock_docking_controller.dm +++ b/code/game/machinery/embedded_controller/airlock_docking_controller.dm @@ -11,7 +11,7 @@ docking_program = new/datum/computer/file/embedded_program/docking/airlock(src, airlock_program) program = docking_program -/obj/machinery/embedded_controller/radio/airlock/docking_port/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/embedded_controller/radio/airlock/docking_port/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] data = list( @@ -24,7 +24,7 @@ "override_enabled" = docking_program.override_enabled, ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "docking_airlock_console.tmpl", name, 470, 290) diff --git a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm b/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm index 99c7bf57848..d03bffcbae5 100644 --- a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm +++ b/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm @@ -22,7 +22,7 @@ child_names[tags[i]] = names[i] -/obj/machinery/embedded_controller/radio/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/embedded_controller/radio/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] var/list/airlocks[child_names.len] @@ -35,7 +35,7 @@ "airlocks" = airlocks, ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "multi_docking_console.tmpl", name, 470, 290) @@ -60,7 +60,7 @@ airlock_program = new/datum/computer/file/embedded_program/airlock/multi_docking(src) program = airlock_program -/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] data = list( @@ -73,7 +73,7 @@ "override_enabled" = airlock_program.override_enabled, ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "docking_airlock_console.tmpl", name, 470, 290) diff --git a/code/game/machinery/embedded_controller/escape_pod_docking_controller.dm b/code/game/machinery/embedded_controller/escape_pod_docking_controller.dm index f84fbf0b323..7a14c9edc20 100644 --- a/code/game/machinery/embedded_controller/escape_pod_docking_controller.dm +++ b/code/game/machinery/embedded_controller/escape_pod_docking_controller.dm @@ -2,7 +2,7 @@ /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod var/datum/shuttle/ferry/escape_pod/pod -/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] data = list( @@ -14,7 +14,7 @@ "is_armed" = pod.arming_controller.armed, ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "escape_pod_console.tmpl", name, 470, 290) @@ -44,7 +44,7 @@ docking_program = new/datum/computer/file/embedded_program/docking/simple/escape_pod(src) program = docking_program -/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] var/armed = null @@ -58,7 +58,7 @@ "armed" = armed, ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "escape_pod_berth_console.tmpl", name, 470, 290) diff --git a/code/game/machinery/embedded_controller/simple_docking_controller.dm b/code/game/machinery/embedded_controller/simple_docking_controller.dm index a7fec342cbf..93c325d4cc5 100644 --- a/code/game/machinery/embedded_controller/simple_docking_controller.dm +++ b/code/game/machinery/embedded_controller/simple_docking_controller.dm @@ -9,7 +9,7 @@ docking_program = new/datum/computer/file/embedded_program/docking/simple(src) program = docking_program -/obj/machinery/embedded_controller/radio/simple_docking_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/embedded_controller/radio/simple_docking_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] data = list( @@ -19,7 +19,7 @@ "door_lock" = docking_program.memory["door_status"]["lock"], ) - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "simple_docking_console.tmpl", name, 470, 290) diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index 118f12e9616..123eeee2ee5 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -142,9 +142,7 @@ * SmartFridge Menu ********************/ - - -/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) user.set_machine(src) var/data[0] @@ -161,7 +159,7 @@ data["contents"] = items - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "smartfridge.tmpl", src.name, 400, 500) ui.set_initial_data(data) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 07f9073056c..430ccad1b9b 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -322,7 +322,7 @@ var/global/list/obj/item/device/pda/PDAs = list() return -/obj/item/device/pda/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/item/device/pda/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) ui_tick++ var/datum/nanoui/old_ui = nanomanager.get_open_ui(user, src, "main") var/auto_update = 1 @@ -457,7 +457,7 @@ var/global/list/obj/item/device/pda/PDAs = list() // 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) + 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 diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index dc92438dadc..282abc1b2bc 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -67,7 +67,7 @@ /obj/item/device/transfer_valve/attack_self(mob/user as mob) ui_interact(user) -/obj/item/device/transfer_valve/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/item/device/transfer_valve/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) // this is the data which will be sent to the ui var/data[0] @@ -77,7 +77,7 @@ data["valveOpen"] = valve_open ? 1 : 0 // 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) + 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 diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index 4e7d8d0244b..5dc95d86680 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -181,7 +181,7 @@ var/list/world_uplinks = list() /* NANO UI FOR UPLINK WOOP WOOP */ -/obj/item/device/uplink/hidden/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/item/device/uplink/hidden/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/title = "Syndicate Uplink" var/data[0] @@ -190,7 +190,7 @@ var/list/world_uplinks = list() data["welcome"] = welcome // 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) + 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 diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 616dc0c114b..d4a0cb0c972 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -127,7 +127,7 @@ ui_interact(user) -/obj/item/weapon/tank/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/obj/item/weapon/tank/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/using_internal if(istype(loc,/mob/living/carbon)) @@ -150,7 +150,7 @@ data["maskConnected"] = 1 // 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) + 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 diff --git a/code/modules/economy/Accounts_DB.dm b/code/modules/economy/Accounts_DB.dm index 94da6347d30..e7c16540552 100644 --- a/code/modules/economy/Accounts_DB.dm +++ b/code/modules/economy/Accounts_DB.dm @@ -73,7 +73,7 @@ if(stat & (NOPOWER|BROKEN)) return ui_interact(user) -/obj/machinery/account_database/ui_interact(mob/user, ui_key="main", datum/nanoui/ui=null) +/obj/machinery/account_database/ui_interact(mob/user, ui_key="main", var/datum/nanoui/ui = null, var/force_open = 1) user.set_machine(src) var/data[0] @@ -119,7 +119,7 @@ if (accounts.len > 0) data["accounts"] = accounts - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "accounts_terminal.tmpl", src.name, 400, 640) ui.set_initial_data(data) diff --git a/code/modules/nano/nanoexternal.dm b/code/modules/nano/nanoexternal.dm index ff4c85ba7f5..3e5a011d5fa 100644 --- a/code/modules/nano/nanoexternal.dm +++ b/code/modules/nano/nanoexternal.dm @@ -31,12 +31,18 @@ * ui_interact is currently defined for /atom/movable * * @param user /mob The mob who is interacting with this ui +<<<<<<< HEAD * @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main") * @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui +======= + * @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main") + * @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui + * @param force_open boolean Force the UI to (re)open, even if it's already open +>>>>>>> 7e7e6cd... Continued work in progress on a major revision of the NanoUI templating system. * * @return nothing */ -/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) +/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) return // Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob diff --git a/code/modules/nano/nanomanager.dm b/code/modules/nano/nanomanager.dm index 647c9ff2e6d..ad58c1feed3 100644 --- a/code/modules/nano/nanomanager.dm +++ b/code/modules/nano/nanomanager.dm @@ -38,19 +38,23 @@ * @param ui_key string A string key used for the ui * @param ui /datum/nanoui An existing instance of the ui (can be null) * @param data list The data to be passed to the ui, if it exists + * @param force_open boolean The ui is being forced to (re)open, so close ui if it exists (instead of updating) * * @return /nanoui Returns the found ui, for null if none exists */ -/datum/nanomanager/proc/try_update_ui(var/mob/user, src_object, ui_key, var/datum/nanoui/ui, data) - if (!ui) // no ui has been passed, so we'll search for one +/datum/nanomanager/proc/try_update_ui(var/mob/user, src_object, ui_key, var/datum/nanoui/ui, data, var/force_open = 0) + if (isnull(ui)) // no ui has been passed, so we'll search for one { - ui = get_open_ui(user, src, ui_key) + ui = get_open_ui(user, src_object, ui_key) } if (!isnull(ui)) - // The UI is already open so push the data to it - ui.push_data(data) - return ui - + // The UI is already open + if (!force_open) + ui.push_data(data) + return ui + else + testing("nanomanager/try_update_ui mob [user.name] [src_object:name] [ui_key] [force_open] - forcing opening of ui") + ui.close() return null /** @@ -65,14 +69,17 @@ /datum/nanomanager/proc/get_open_ui(var/mob/user, src_object, ui_key) var/src_object_key = "\ref[src_object]" if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) + testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open") return null else if (isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list)) + testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open for this object") return null for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key]) if (ui.user == user) return ui + testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found") return null /** @@ -127,6 +134,7 @@ */ /datum/nanomanager/proc/close_user_uis(var/mob/user, src_object = null, ui_key = null) if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0) + testing("nanomanager/close_user_uis mob [user.name] has no open uis") return 0 // has no open uis var/close_count = 0 @@ -135,6 +143,8 @@ ui.close() close_count++ + testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [close_count] uis") + return close_count /** @@ -156,6 +166,7 @@ var/list/uis = open_uis[src_object_key][ui.ui_key] uis.Add(ui) processing_uis.Add(ui) + testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]") /** * Remove a /nanoui ui from the list of open uis @@ -175,7 +186,11 @@ processing_uis.Remove(ui) ui.user.open_uis.Remove(ui) var/list/uis = open_uis[src_object_key][ui.ui_key] - return uis.Remove(ui) + uis.Remove(ui) + + testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]") + + return 1 /** * This is called on user logout @@ -188,13 +203,8 @@ // /datum/nanomanager/proc/user_logout(var/mob/user) - if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0) - return 0 // has no open uis - - for (var/datum/nanoui/ui in user.open_uis) - ui.close(); - - + testing("nanomanager/user_logout user [user.name]") + return close_user_uis(user) /** * This is called when a player transfers from one mob to another @@ -206,7 +216,9 @@ * @return nothing */ /datum/nanomanager/proc/user_transferred(var/mob/oldMob, var/mob/newMob) - if (!oldMob || isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0) + testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]") + if (isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0) + testing("nanomanager/user_transferred mob [oldMob.name] has no open uis") return 0 // has no open uis if (isnull(newMob.open_uis) || !istype(newMob.open_uis, /list)) diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index e0d2cb88609..c0d00af60af 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -43,6 +43,8 @@ nanoui is used to open and update nano browser uis // the body content for this ui, do not change unless you know what you're doing // the #mainTemplate div will contain the compiled "main" template html var/content = "
" + // the title of this ui + var/state_key = "default" // initial data, containing the full data structure, must be sent to the ui (the data structure cannot be extended later on) var/list/initial_data[0] // set to 1 to update the ui automatically every master_controller tick @@ -96,7 +98,10 @@ nanoui is used to open and update nano browser uis add_script("libraries.min.js") // A JS file comprising of jQuery, doT.js and jQuery Timer libraries (compressed together) add_script("nano_utility.js") // The NanoUtility JS, this is used to store utility functions. add_script("nano_template.js") // The NanoTemplate JS, this is used to render templates. - add_script("nano_update.js") // The NanoUpdate JS, this is used to receive updates and apply them. + add_script("nano_state_manager.js") // The + add_script("nano_state.js") // The + add_script("nano_state_default.js") // The + add_script("nano_base_callbacks.js") // The add_script("nano_base_helpers.js") // The NanoBaseHelpers JS, this is used to set up template helpers which are common to all templates add_stylesheet("shared.css") // this CSS sheet is common to all UIs add_stylesheet("icons.css") // this CSS sheet is common to all UIs @@ -110,12 +115,15 @@ nanoui is used to open and update nano browser uis * @return nothing */ /datum/nanoui/proc/set_status(state, push_update) - if (state != status) - status = state - if (push_update || !status) - push_data(list(), 1) // Update the UI, force the update in case the status is 0 - else - status = state + if (state != status) // Only update if it is different + if (status == STATUS_DISABLED) + status = state + if (push_update) + update() + else + status = state + if (push_update || status == 0) + push_data(null, 1) // Update the UI, force the update in case the status is 0, data is null so that previous data is used /** * Update the status (visibility) of this ui based on the user's status @@ -124,7 +132,7 @@ nanoui is used to open and update nano browser uis * * @return nothing */ -/datum/nanoui/proc/update_status(push_update = 0) +/datum/nanoui/proc/update_status(var/push_update = 0) if (istype(user, /mob/living/silicon/ai)) set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility) else if (istype(user, /mob/living/silicon/robot)) @@ -174,21 +182,39 @@ nanoui is used to open and update nano browser uis * @return nothing */ /datum/nanoui/proc/set_initial_data(list/data) - initial_data = add_default_data(data) + initial_data = data /** - * Add default data to the data being sent to the ui. + * Get config data to sent to the ui. * - * @param data /list The list of data to be modified - * - * @return /list modified data + * @return /list config data */ -/datum/nanoui/proc/add_default_data(list/data) - data["ui"] = list( +/datum/nanoui/proc/get_config_data() + var/list/config_data = list( + "title" = title, + "srcObject" = list("name" = src_object.name), + "stateKey" = state_key, "status" = status, "user" = list("name" = user.name) ) - return data + return config_data + + /** + * Get data to sent to the ui. + * + * @param data /list The list of general data for this ui (can be null to use previous data sent) + * + * @return /list data to send to the ui + */ +/datum/nanoui/proc/get_send_data(var/list/data) + var/list/config_data = get_config_data() + + var/list/send_data = list("config" = config_data) + + if (!isnull(data)) + send_data["data"] = data + + return send_data /** * Set the browser window options for this ui @@ -246,6 +272,16 @@ nanoui is used to open and update nano browser uis /datum/nanoui/proc/set_content(ncontent) content = ncontent + /** + * Set the state key for use in the frontend Javascript + * + * @param nstate_key string The new HTML content for this UI + * + * @return nothing + */ +/datum/nanoui/proc/set_state_key(nstate_key) + state_key = nstate_key + /** * Set whether or not to use the "old" on close logic (mainly unset_machine()) * @@ -278,9 +314,8 @@ nanoui is used to open and update nano browser uis if (templatel_data.len > 0) template_data_json = list2json(templatel_data) - var/initial_data_json = "{}" // An empty JSON object - if (initial_data.len > 0) - initial_data_json = list2json(initial_data) + var/list/send_data = get_send_data(initial_data) + var/initial_data_json = list2json(send_data) var/url_parameters_json = list2json(list("src" = "\ref[src]")) @@ -291,11 +326,15 @@ nanoui is used to open and update nano browser uis @@ -305,7 +344,16 @@ nanoui is used to open and update nano browser uis| t |