diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm index 7cede3b8b6..6256931926 100644 --- a/code/game/machinery/telecomms/logbrowser.dm +++ b/code/game/machinery/telecomms/logbrowser.dm @@ -27,7 +27,7 @@ data["temp"] = temp var/list/servers = list() - for(var/obj/machinery/telecomms/T in servers) + for(var/obj/machinery/telecomms/T in src.servers) servers.Add(list(list( "id" = T.id, "name" = T.name, @@ -46,7 +46,7 @@ for(var/c in SelectedServer.log_entries) i++ var/datum/comm_log_entry/C = c - + // This is necessary to prevent leaking information to the clientside var/static/list/acceptable_params = list("uspeech", "intelligible", "message", "name", "race", "job", "timecode") var/list/parameters = list() @@ -74,7 +74,7 @@ if(!ui) ui = new(user, src, "TelecommsLogBrowser", name) ui.open() - + /obj/machinery/computer/telecomms/server/tgui_act(action, params) if(..()) return TRUE @@ -139,7 +139,7 @@ set_temp("NEW NETWORK TAG SET IN ADDRESS \[[network]\]", "good") . = TRUE - + if("cleartemp") temp = null . = TRUE @@ -153,4 +153,4 @@ return 1 /obj/machinery/computer/telecomms/server/proc/set_temp(var/text, var/color = "average") - temp = list("color" = color, "text" = text) \ No newline at end of file + temp = list("color" = color, "text" = text) diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecommunications.dm similarity index 96% rename from code/game/machinery/telecomms/telecomunications.dm rename to code/game/machinery/telecomms/telecommunications.dm index c13695c860..7a741f7ae8 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecommunications.dm @@ -1,691 +1,691 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/* - Hello, friends, this is Doohl from sexylands. You may be wondering what this - monstrous code file is. Sit down, boys and girls, while I tell you the tale. - - - The machines defined in this file were designed to be compatible with any radio - signals, provided they use subspace transmission. Currently they are only used for - headsets, but they can eventually be outfitted for real COMPUTER networks. This - is just a skeleton, ladies and gentlemen. - - Look at radio.dm for the prequel to this code. -*/ - -var/global/list/obj/machinery/telecomms/telecomms_list = list() - -/obj/machinery/telecomms - icon = 'icons/obj/stationobjs.dmi' - var/list/links = list() // list of machines this machine is linked to - var/traffic = 0 // value increases as traffic increases - var/netspeed = 5 // how much traffic to lose per tick (50 gigabytes/second * netspeed) - var/list/autolinkers = list() // list of text/number values to link with - var/id = "NULL" // identification string - var/network = "NULL" // the network of the machinery - - var/list/freq_listening = list() // list of frequencies to tune into: if none, will listen to all - - var/machinetype = 0 // just a hacky way of preventing alike machines from pairing - var/toggled = 1 // Is it toggled on - var/on = 1 - var/integrity = 100 // basically HP, loses integrity by heat - var/produces_heat = 1 //whether the machine will produce heat when on. - var/delay = 10 // how many process() ticks to delay per heat - var/long_range_link = 0 // Can you link it across Z levels or on the otherside of the map? (Relay & Hub) - var/hide = 0 // Is it a hidden machine? - var/listening_level = 0 // 0 = auto set in New() - this is the z level that the machine is listening to. - - -/obj/machinery/telecomms/proc/relay_information(datum/signal/signal, filter, copysig, amount = 20) - // relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending - - if(!on) - return - //to_world("[src] ([src.id]) - [signal.debug_print()]") - var/send_count = 0 - - signal.data["slow"] += rand(0, round((100-integrity))) // apply some lag based on integrity - - /* - // Edit by Atlantis: Commented out as emergency fix due to causing extreme delays in communications. - // Apply some lag based on traffic rates - var/netlag = round(traffic / 50) - if(netlag > signal.data["slow"]) - signal.data["slow"] = netlag - */ -// Loop through all linked machines and send the signal or copy. - for(var/obj/machinery/telecomms/machine in links) - if(filter && !istype(machine, filter)) - continue - if(!machine.on) - continue - if(amount && send_count >= amount) - break - if(machine.loc.z != listening_level) - if(long_range_link == 0 && machine.long_range_link == 0) - continue - // If we're sending a copy, be sure to create the copy for EACH machine and paste the data - var/datum/signal/copy - if(copysig) - copy = new - copy.transmission_method = TRANSMISSION_SUBSPACE - copy.frequency = signal.frequency - copy.data = signal.data.Copy() - - // Keep the "original" signal constant - if(!signal.data["original"]) - copy.data["original"] = signal - else - copy.data["original"] = signal.data["original"] - - send_count++ - if(machine.is_freq_listening(signal)) - machine.traffic++ - - if(copysig && copy) - machine.receive_information(copy, src) - else - machine.receive_information(signal, src) - - - if(send_count > 0 && is_freq_listening(signal)) - traffic++ - - return send_count - -/obj/machinery/telecomms/proc/relay_direct_information(datum/signal/signal, obj/machinery/telecomms/machine) - // send signal directly to a machine - machine.receive_information(signal, src) - -/obj/machinery/telecomms/proc/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - // receive information from linked machinery - return - -/obj/machinery/telecomms/proc/is_freq_listening(datum/signal/signal) - // return 1 if found, 0 if not found - if(!signal) - return 0 - if((signal.frequency in freq_listening) || (!freq_listening.len)) - return 1 - else - return 0 - -/obj/machinery/telecomms/Initialize() - telecomms_list += src - ..() - default_apply_parts() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/telecomms/LateInitialize() - . = ..() - - //Set the listening_level if there's none. - if(!listening_level) - //Defaults to our Z level! - var/turf/position = get_turf(src) - listening_level = position.z - - if(autolinkers.len) - // Links nearby machines - if(!long_range_link) - for(var/obj/machinery/telecomms/T in orange(20, src)) - add_link(T) - else - for(var/obj/machinery/telecomms/T in telecomms_list) - add_link(T) - -/obj/machinery/telecomms/Destroy() - telecomms_list -= src - for(var/obj/machinery/telecomms/comm in telecomms_list) - comm.links -= src - links = list() - ..() - -// Used in auto linking -/obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T) - var/pos_z = get_z(src) - var/tpos_z = get_z(T) - if((pos_z == tpos_z) || (src.long_range_link && T.long_range_link)) - for(var/x in autolinkers) - if(T.autolinkers.Find(x)) - if(src != T) - links |= T - -/obj/machinery/telecomms/update_icon() - if(on) - icon_state = initial(icon_state) - else - icon_state = "[initial(icon_state)]_off" - -/obj/machinery/telecomms/proc/update_power() - - if(toggled) - if(stat & (BROKEN|NOPOWER|EMPED) || integrity <= 0) // if powered, on. if not powered, off. if too damaged, off - on = 0 - else - on = 1 - else - on = 0 - -/obj/machinery/telecomms/process() - update_power() - - // Check heat and generate some - checkheat() - - // Update the icon - update_icon() - - if(traffic > 0) - traffic -= netspeed - -/obj/machinery/telecomms/emp_act(severity) - if(prob(100/severity)) - if(!(stat & EMPED)) - stat |= EMPED - var/duration = (300 * 10)/severity - spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot. - stat &= ~EMPED - ..() - -/obj/machinery/telecomms/proc/checkheat() - // Checks heat from the environment and applies any integrity damage - var/datum/gas_mixture/environment = loc.return_air() - var/damage_chance = 0 // Percent based chance of applying 1 integrity damage this tick - switch(environment.temperature) - if((T0C + 40) to (T0C + 70)) // 40C-70C, minor overheat, 10% chance of taking damage - damage_chance = 10 - if((T0C + 70) to (T0C + 130)) // 70C-130C, major overheat, 25% chance of taking damage - damage_chance = 25 - if((T0C + 130) to (T0C + 200)) // 130C-200C, dangerous overheat, 50% chance of taking damage - damage_chance = 50 - if((T0C + 200) to INFINITY) // More than 200C, INFERNO. Takes damage every tick. - damage_chance = 100 - if (damage_chance && prob(damage_chance)) - integrity = between(0, integrity - 1, 100) - - - if(delay > 0) - delay-- - else if(on) - produce_heat() - delay = initial(delay) - - - -/obj/machinery/telecomms/proc/produce_heat() - if (!produces_heat) - return - - if (!use_power) - return - - if(!(stat & (NOPOWER|BROKEN))) - var/turf/simulated/L = loc - if(istype(L)) - var/datum/gas_mixture/env = L.return_air() - - var/transfer_moles = 0.25 * env.total_moles - - var/datum/gas_mixture/removed = env.remove(transfer_moles) - - if(removed) - - var/heat_produced = idle_power_usage //obviously can't produce more heat than the machine draws from it's power source - if (traffic <= 0) - heat_produced *= 0.30 //if idle, produce less heat. - - removed.add_thermal_energy(heat_produced) - - env.merge(removed) -/* - The receiver idles and receives messages from subspace-compatible radio equipment; - primarily headsets. They then just relay this information to all linked devices, - which can would probably be network hubs. - - Link to Processor Units in case receiver can't send to bus units. -*/ - -/obj/machinery/telecomms/receiver - name = "Subspace Receiver" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "broadcast receiver" - desc = "This machine has a dish-like shape and green lights. It is designed to detect and process subspace radio activity." - density = 1 - anchored = 1 - use_power = USE_POWER_IDLE - idle_power_usage = 600 - machinetype = 1 - produces_heat = 0 - circuit = /obj/item/circuitboard/telecomms/receiver - //Vars only used if you're using the overmap - var/overmap_range = 0 - var/overmap_range_min = 0 - var/overmap_range_max = 5 - - var/list/linked_radios_weakrefs = list() - -/obj/machinery/telecomms/receiver/proc/link_radio(var/obj/item/radio/R) - if(!istype(R)) - return - linked_radios_weakrefs |= weakref(R) - -/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal) - if(!on) // has to be on to receive messages - return - if(!signal) - return - if(!check_receive_level(signal)) - return - - if(signal.transmission_method == TRANSMISSION_SUBSPACE) - - if(is_freq_listening(signal)) // detect subspace signals - - //Remove the level and then start adding levels that it is being broadcasted in. - signal.data["level"] = list() - - var/can_send = relay_information(signal, /obj/machinery/telecomms/hub) // ideally relay the copied information to relays - if(!can_send) - relay_information(signal, /obj/machinery/telecomms/bus) // Send it to a bus instead, if it's linked to one - -/obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/signal) - // If it's a direct message from a bluespace radio, we eat it and convert it into a subspace signal locally - if(signal.transmission_method == TRANSMISSION_BLUESPACE) - var/obj/item/radio/R = signal.data["radio"] - - //Who're you? - if(!(weakref(R) in linked_radios_weakrefs)) - signal.data["reject"] = 1 - return 0 - - //We'll resend this for you - signal.data["level"] = z - signal.transmission_method = TRANSMISSION_SUBSPACE - return 1 - - //Where can we hear? - var/list/listening_levels = using_map.get_map_levels(listening_level, TRUE, overmap_range) - - // We couldn't 'hear' it, maybe a relay linked to our hub can 'hear' it - if(!(signal.data["level"] in listening_levels)) - for(var/obj/machinery/telecomms/hub/H in links) - var/list/relayed_levels = list() - for(var/obj/machinery/telecomms/relay/R in H.links) - if(R.can_receive(signal)) - relayed_levels |= R.listening_level - if(signal.data["level"] in relayed_levels) - return 1 - return 0 - return 1 - - -/* - The HUB idles until it receives information. It then passes on that information - depending on where it came from. - - This is the heart of the Telecommunications Network, sending information where it - is needed. It mainly receives information from long-distance Relays and then sends - that information to be processed. Afterwards it gets the uncompressed information - from Servers/Buses and sends that back to the relay, to then be broadcasted. -*/ - -/obj/machinery/telecomms/hub - name = "Telecommunication Hub" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "hub" - desc = "A mighty piece of hardware used to send/receive massive amounts of data." - density = 1 - anchored = 1 - use_power = USE_POWER_IDLE - idle_power_usage = 1600 - machinetype = 7 - circuit = /obj/item/circuitboard/telecomms/hub - long_range_link = 1 - netspeed = 40 - -/obj/machinery/telecomms/hub/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - if(is_freq_listening(signal)) - if(istype(machine_from, /obj/machinery/telecomms/receiver)) - //If the signal is compressed, send it to the bus. - relay_information(signal, /obj/machinery/telecomms/bus, 1) // ideally relay the copied information to bus units - else - // Get a list of relays that we're linked to, then send the signal to their levels. - relay_information(signal, /obj/machinery/telecomms/relay, 1) - relay_information(signal, /obj/machinery/telecomms/broadcaster, 1) // Send it to a broadcaster. - - -/* - The relay idles until it receives information. It then passes on that information - depending on where it came from. - - The relay is needed in order to send information pass Z levels. It must be linked - with a HUB, the only other machine that can send/receive pass Z levels. -*/ - -/obj/machinery/telecomms/relay - name = "Telecommunication Relay" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "relay" - desc = "A mighty piece of hardware used to send massive amounts of data far away." - density = 1 - anchored = 1 - use_power = USE_POWER_IDLE - idle_power_usage = 600 - machinetype = 8 - produces_heat = 0 - circuit = /obj/item/circuitboard/telecomms/relay - netspeed = 5 - long_range_link = 1 - var/broadcasting = 1 - var/receiving = 1 - -/obj/machinery/telecomms/relay/forceMove(var/newloc) - . = ..(newloc) - listening_level = z - -/obj/machinery/telecomms/relay/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - // Add our level and send it back - if(can_send(signal)) - signal.data["level"] |= using_map.get_map_levels(listening_level) - -// Checks to see if it can send/receive. - -/obj/machinery/telecomms/relay/proc/can(datum/signal/signal) - if(!on) - return 0 - if(!is_freq_listening(signal)) - return 0 - return 1 - -/obj/machinery/telecomms/relay/proc/can_send(datum/signal/signal) - if(!can(signal)) - return 0 - return broadcasting - -/obj/machinery/telecomms/relay/proc/can_receive(datum/signal/signal) - if(!can(signal)) - return 0 - return receiving - -/* - The bus mainframe idles and waits for hubs to relay them signals. They act - as junctions for the network. - - They transfer uncompressed subspace packets to processor units, and then take - the processed packet to a server for logging. - - Link to a subspace hub if it can't send to a server. -*/ - -/obj/machinery/telecomms/bus - name = "Bus Mainframe" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "bus" - desc = "A mighty piece of hardware used to send massive amounts of data quickly." - density = 1 - anchored = 1 - use_power = USE_POWER_IDLE - idle_power_usage = 1000 - machinetype = 2 - circuit = /obj/item/circuitboard/telecomms/bus - netspeed = 40 - var/change_frequency = 0 - -/obj/machinery/telecomms/bus/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - if(is_freq_listening(signal)) - - if(change_frequency) - signal.frequency = change_frequency - - if(!istype(machine_from, /obj/machinery/telecomms/processor) && machine_from != src) // Signal must be ready (stupid assuming machine), let's send it - // send to one linked processor unit - var/send_to_processor = relay_information(signal, /obj/machinery/telecomms/processor) - - if(send_to_processor) - return - // failed to send to a processor, relay information anyway - signal.data["slow"] += rand(1, 5) // slow the signal down only slightly - src.receive_information(signal, src) - - // Try sending it! - var/list/try_send = list(/obj/machinery/telecomms/server, /obj/machinery/telecomms/hub, /obj/machinery/telecomms/broadcaster, /obj/machinery/telecomms/bus) - var/i = 0 - for(var/send in try_send) - if(i) - signal.data["slow"] += rand(0, 1) // slow the signal down only slightly - i++ - var/can_send = relay_information(signal, send) - if(can_send) - break - - - -/* - The processor is a very simple machine that decompresses subspace signals and - transfers them back to the original bus. It is essential in producing audible - data. - - Link to servers if bus is not present -*/ - -/obj/machinery/telecomms/processor - name = "Processor Unit" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "processor" - desc = "This machine is used to process large quantities of information." - density = 1 - anchored = 1 - use_power = USE_POWER_IDLE - idle_power_usage = 600 - machinetype = 3 - delay = 5 - circuit = /obj/item/circuitboard/telecomms/processor - var/process_mode = 1 // 1 = Uncompress Signals, 0 = Compress Signals - -/obj/machinery/telecomms/processor/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - if(is_freq_listening(signal)) - - if(process_mode) - signal.data["compression"] = 0 // uncompress subspace signal - else - signal.data["compression"] = 100 // even more compressed signal - - if(istype(machine_from, /obj/machinery/telecomms/bus)) - relay_direct_information(signal, machine_from) // send the signal back to the machine - else // no bus detected - send the signal to servers instead - signal.data["slow"] += rand(5, 10) // slow the signal down - relay_information(signal, /obj/machinery/telecomms/server) - - -/* - The server logs all traffic and signal data. Once it records the signal, it sends - it to the subspace broadcaster. - - Store a maximum of 100 logs and then deletes them. -*/ - - -/obj/machinery/telecomms/server - name = "Telecommunication Server" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "comm_server" - desc = "A machine used to store data and network statistics." - density = 1 - anchored = 1 - use_power = USE_POWER_IDLE - idle_power_usage = 300 - machinetype = 4 - circuit = /obj/item/circuitboard/telecomms/server - var/list/log_entries = list() - var/list/stored_names = list() - var/list/TrafficActions = list() - var/logs = 0 // number of logs - var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes) - - var/list/memory = list() // stored memory - var/rawcode = "" // the code to compile (raw text) - var/datum/TCS_Compiler/Compiler // the compiler that compiles and runs the code - var/autoruncode = 0 // 1 if the code is set to run every time a signal is picked up - - var/encryption = "null" // encryption key: ie "password" - var/salt = "null" // encryption salt: ie "123comsat" - // would add up to md5("password123comsat") - var/obj/item/radio/headset/server_radio = null - -/obj/machinery/telecomms/server/Initialize() - Compiler = new - Compiler.Holder = src - server_radio = new - . = ..() - -/obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - if(signal.data["message"]) - - if(is_freq_listening(signal)) - - if(traffic > 0) - totaltraffic += traffic // add current traffic to total traffic - - //Is this a test signal? Bypass logging - if(signal.data["type"] != SIGNAL_TEST) - - // If signal has a message and appropriate frequency - - update_logs() - - var/datum/comm_log_entry/log = new - var/mob/M = signal.data["mob"] - - // Copy the signal.data entries we want - log.parameters["mobtype"] = signal.data["mobtype"] - log.parameters["job"] = signal.data["job"] - log.parameters["key"] = signal.data["key"] - log.parameters["vmessage"] = multilingual_to_message(signal.data["message"]) - log.parameters["vname"] = signal.data["vname"] - log.parameters["message"] = multilingual_to_message(signal.data["message"]) - log.parameters["name"] = signal.data["name"] - log.parameters["realname"] = signal.data["realname"] - log.parameters["timecode"] = worldtime2stationtime(world.time) - - var/race = "unknown" - if(ishuman(M)) - var/mob/living/carbon/human/H = M - race = "[H.species.name]" - log.parameters["intelligible"] = 1 - else if(isbrain(M)) - race = "Brain" - log.parameters["intelligible"] = 1 - else if(M.isMonkey()) - race = "Monkey" - else if(issilicon(M)) - race = "Artificial Life" - log.parameters["intelligible"] = 1 - else if(isslime(M)) - race = "Slime" - else if(isanimal(M)) - race = "Domestic Animal" - - log.parameters["race"] = race - - if(!istype(M, /mob/new_player) && M) - log.parameters["uspeech"] = M.universal_speak - else - log.parameters["uspeech"] = 0 - - // If the signal is still compressed, make the log entry gibberish - if(signal.data["compression"] > 0) - log.parameters["message"] = Gibberish(multilingual_to_message(signal.data["message"]), signal.data["compression"] + 50) - log.parameters["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50) - log.parameters["name"] = Gibberish(signal.data["name"], signal.data["compression"] + 50) - log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50) - log.parameters["vname"] = Gibberish(signal.data["vname"], signal.data["compression"] + 50) - log.input_type = "Corrupt File" - - // Log and store everything that needs to be logged - log_entries.Add(log) - if(!(signal.data["name"] in stored_names)) - stored_names.Add(signal.data["name"]) - logs++ - signal.data["server"] = src - - // Give the log a name - var/identifier = num2text( rand(-1000,1000) + world.time ) - log.name = "data packet ([md5(identifier)])" - - if(Compiler && autoruncode) - Compiler.Run(signal) // execute the code - - var/can_send = relay_information(signal, /obj/machinery/telecomms/hub) - if(!can_send) - relay_information(signal, /obj/machinery/telecomms/broadcaster) - - -/obj/machinery/telecomms/server/proc/setcode(var/t) - if(t) - if(istext(t)) - rawcode = t - -/obj/machinery/telecomms/server/proc/compile() - if(Compiler) - return Compiler.Compile(rawcode) - -/obj/machinery/telecomms/server/proc/update_logs() - // start deleting the very first log entry - if(logs >= 400) - for(var/i = 1, i <= logs, i++) // locate the first garbage collectable log entry and remove it - var/datum/comm_log_entry/L = log_entries[i] - if(L.garbage_collector) - log_entries.Remove(L) - logs-- - break - -/obj/machinery/telecomms/server/proc/add_entry(var/content, var/input) - var/datum/comm_log_entry/log = new - var/identifier = num2text( rand(-1000,1000) + world.time ) - log.name = "[input] ([md5(identifier)])" - log.input_type = input - log.parameters["message"] = content - log.parameters["timecode"] = stationtime2text() - log_entries.Add(log) - update_logs() - - - - -// Simple log entry datum - -/datum/comm_log_entry - var/parameters = list() // carbon-copy to signal.data[] - var/name = "data packet (#)" - var/garbage_collector = 1 // if set to 0, will not be garbage collected - var/input_type = "Speech File" - -//Generic telecomm connectivity test proc -/proc/can_telecomm(var/atom/A, var/atom/B, var/ad_hoc = FALSE) - if(!A || !B) - log_debug("can_telecomm(): Undefined endpoints!") - return FALSE - - //Can't in this case, obviously! - if(is_jammed(A) || is_jammed(B)) - return FALSE - - //Items don't have a Z when inside an object or mob - var/turf/src_z = get_z(A) - var/turf/dst_z = get_z(B) - - //Nullspace, probably. - if(!src_z || !dst_z) - return FALSE - - //We can do the simple check first, if you have ad_hoc radios. - if(ad_hoc && src_z == dst_z) - return TRUE - - return src_z in using_map.get_map_levels(dst_z, TRUE, om_range = DEFAULT_OVERMAP_RANGE) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/* + Hello, friends, this is Doohl from sexylands. You may be wondering what this + monstrous code file is. Sit down, boys and girls, while I tell you the tale. + + + The machines defined in this file were designed to be compatible with any radio + signals, provided they use subspace transmission. Currently they are only used for + headsets, but they can eventually be outfitted for real COMPUTER networks. This + is just a skeleton, ladies and gentlemen. + + Look at radio.dm for the prequel to this code. +*/ + +var/global/list/obj/machinery/telecomms/telecomms_list = list() + +/obj/machinery/telecomms + icon = 'icons/obj/stationobjs.dmi' + var/list/links = list() // list of machines this machine is linked to + var/traffic = 0 // value increases as traffic increases + var/netspeed = 5 // how much traffic to lose per tick (50 gigabytes/second * netspeed) + var/list/autolinkers = list() // list of text/number values to link with + var/id = "NULL" // identification string + var/network = "NULL" // the network of the machinery + + var/list/freq_listening = list() // list of frequencies to tune into: if none, will listen to all + + var/machinetype = 0 // just a hacky way of preventing alike machines from pairing + var/toggled = 1 // Is it toggled on + var/on = 1 + var/integrity = 100 // basically HP, loses integrity by heat + var/produces_heat = 1 //whether the machine will produce heat when on. + var/delay = 10 // how many process() ticks to delay per heat + var/long_range_link = 0 // Can you link it across Z levels or on the otherside of the map? (Relay & Hub) + var/hide = 0 // Is it a hidden machine? + var/listening_level = 0 // 0 = auto set in New() - this is the z level that the machine is listening to. + + +/obj/machinery/telecomms/proc/relay_information(datum/signal/signal, filter, copysig, amount = 20) + // relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending + + if(!on) + return + //to_world("[src] ([src.id]) - [signal.debug_print()]") + var/send_count = 0 + + signal.data["slow"] += rand(0, round((100-integrity))) // apply some lag based on integrity + + /* + // Edit by Atlantis: Commented out as emergency fix due to causing extreme delays in communications. + // Apply some lag based on traffic rates + var/netlag = round(traffic / 50) + if(netlag > signal.data["slow"]) + signal.data["slow"] = netlag + */ +// Loop through all linked machines and send the signal or copy. + for(var/obj/machinery/telecomms/machine in links) + if(filter && !istype(machine, filter)) + continue + if(!machine.on) + continue + if(amount && send_count >= amount) + break + if(machine.loc.z != listening_level) + if(long_range_link == 0 && machine.long_range_link == 0) + continue + // If we're sending a copy, be sure to create the copy for EACH machine and paste the data + var/datum/signal/copy + if(copysig) + copy = new + copy.transmission_method = TRANSMISSION_SUBSPACE + copy.frequency = signal.frequency + copy.data = signal.data.Copy() + + // Keep the "original" signal constant + if(!signal.data["original"]) + copy.data["original"] = signal + else + copy.data["original"] = signal.data["original"] + + send_count++ + if(machine.is_freq_listening(signal)) + machine.traffic++ + + if(copysig && copy) + machine.receive_information(copy, src) + else + machine.receive_information(signal, src) + + + if(send_count > 0 && is_freq_listening(signal)) + traffic++ + + return send_count + +/obj/machinery/telecomms/proc/relay_direct_information(datum/signal/signal, obj/machinery/telecomms/machine) + // send signal directly to a machine + machine.receive_information(signal, src) + +/obj/machinery/telecomms/proc/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + // receive information from linked machinery + return + +/obj/machinery/telecomms/proc/is_freq_listening(datum/signal/signal) + // return 1 if found, 0 if not found + if(!signal) + return 0 + if((signal.frequency in freq_listening) || (!freq_listening.len)) + return 1 + else + return 0 + +/obj/machinery/telecomms/Initialize() + telecomms_list += src + ..() + default_apply_parts() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/telecomms/LateInitialize() + . = ..() + + //Set the listening_level if there's none. + if(!listening_level) + //Defaults to our Z level! + var/turf/position = get_turf(src) + listening_level = position.z + + if(autolinkers.len) + // Links nearby machines + if(!long_range_link) + for(var/obj/machinery/telecomms/T in orange(20, src)) + add_link(T) + else + for(var/obj/machinery/telecomms/T in telecomms_list) + add_link(T) + +/obj/machinery/telecomms/Destroy() + telecomms_list -= src + for(var/obj/machinery/telecomms/comm in telecomms_list) + comm.links -= src + links = list() + ..() + +// Used in auto linking +/obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T) + var/pos_z = get_z(src) + var/tpos_z = get_z(T) + if((pos_z == tpos_z) || (src.long_range_link && T.long_range_link)) + for(var/x in autolinkers) + if(T.autolinkers.Find(x)) + if(src != T) + links |= T + +/obj/machinery/telecomms/update_icon() + if(on) + icon_state = initial(icon_state) + else + icon_state = "[initial(icon_state)]_off" + +/obj/machinery/telecomms/proc/update_power() + + if(toggled) + if(stat & (BROKEN|NOPOWER|EMPED) || integrity <= 0) // if powered, on. if not powered, off. if too damaged, off + on = 0 + else + on = 1 + else + on = 0 + +/obj/machinery/telecomms/process() + update_power() + + // Check heat and generate some + checkheat() + + // Update the icon + update_icon() + + if(traffic > 0) + traffic -= netspeed + +/obj/machinery/telecomms/emp_act(severity) + if(prob(100/severity)) + if(!(stat & EMPED)) + stat |= EMPED + var/duration = (300 * 10)/severity + spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot. + stat &= ~EMPED + ..() + +/obj/machinery/telecomms/proc/checkheat() + // Checks heat from the environment and applies any integrity damage + var/datum/gas_mixture/environment = loc.return_air() + var/damage_chance = 0 // Percent based chance of applying 1 integrity damage this tick + switch(environment.temperature) + if((T0C + 40) to (T0C + 70)) // 40C-70C, minor overheat, 10% chance of taking damage + damage_chance = 10 + if((T0C + 70) to (T0C + 130)) // 70C-130C, major overheat, 25% chance of taking damage + damage_chance = 25 + if((T0C + 130) to (T0C + 200)) // 130C-200C, dangerous overheat, 50% chance of taking damage + damage_chance = 50 + if((T0C + 200) to INFINITY) // More than 200C, INFERNO. Takes damage every tick. + damage_chance = 100 + if (damage_chance && prob(damage_chance)) + integrity = between(0, integrity - 1, 100) + + + if(delay > 0) + delay-- + else if(on) + produce_heat() + delay = initial(delay) + + + +/obj/machinery/telecomms/proc/produce_heat() + if (!produces_heat) + return + + if (!use_power) + return + + if(!(stat & (NOPOWER|BROKEN))) + var/turf/simulated/L = loc + if(istype(L)) + var/datum/gas_mixture/env = L.return_air() + + var/transfer_moles = 0.25 * env.total_moles + + var/datum/gas_mixture/removed = env.remove(transfer_moles) + + if(removed) + + var/heat_produced = idle_power_usage //obviously can't produce more heat than the machine draws from it's power source + if (traffic <= 0) + heat_produced *= 0.30 //if idle, produce less heat. + + removed.add_thermal_energy(heat_produced) + + env.merge(removed) +/* + The receiver idles and receives messages from subspace-compatible radio equipment; + primarily headsets. They then just relay this information to all linked devices, + which can would probably be network hubs. + + Link to Processor Units in case receiver can't send to bus units. +*/ + +/obj/machinery/telecomms/receiver + name = "Subspace Receiver" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "broadcast receiver" + desc = "This machine has a dish-like shape and green lights. It is designed to detect and process subspace radio activity." + density = 1 + anchored = 1 + use_power = USE_POWER_IDLE + idle_power_usage = 600 + machinetype = 1 + produces_heat = 0 + circuit = /obj/item/circuitboard/telecomms/receiver + //Vars only used if you're using the overmap + var/overmap_range = 0 + var/overmap_range_min = 0 + var/overmap_range_max = 5 + + var/list/linked_radios_weakrefs = list() + +/obj/machinery/telecomms/receiver/proc/link_radio(var/obj/item/radio/R) + if(!istype(R)) + return + linked_radios_weakrefs |= weakref(R) + +/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal) + if(!on) // has to be on to receive messages + return + if(!signal) + return + if(!check_receive_level(signal)) + return + + if(signal.transmission_method == TRANSMISSION_SUBSPACE) + + if(is_freq_listening(signal)) // detect subspace signals + + //Remove the level and then start adding levels that it is being broadcasted in. + signal.data["level"] = list() + + var/can_send = relay_information(signal, /obj/machinery/telecomms/hub) // ideally relay the copied information to relays + if(!can_send) + relay_information(signal, /obj/machinery/telecomms/bus) // Send it to a bus instead, if it's linked to one + +/obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/signal) + // If it's a direct message from a bluespace radio, we eat it and convert it into a subspace signal locally + if(signal.transmission_method == TRANSMISSION_BLUESPACE) + var/obj/item/radio/R = signal.data["radio"] + + //Who're you? + if(!(weakref(R) in linked_radios_weakrefs)) + signal.data["reject"] = 1 + return 0 + + //We'll resend this for you + signal.data["level"] = z + signal.transmission_method = TRANSMISSION_SUBSPACE + return 1 + + //Where can we hear? + var/list/listening_levels = using_map.get_map_levels(listening_level, TRUE, overmap_range) + + // We couldn't 'hear' it, maybe a relay linked to our hub can 'hear' it + if(!(signal.data["level"] in listening_levels)) + for(var/obj/machinery/telecomms/hub/H in links) + var/list/relayed_levels = list() + for(var/obj/machinery/telecomms/relay/R in H.links) + if(R.can_receive(signal)) + relayed_levels |= R.listening_level + if(signal.data["level"] in relayed_levels) + return 1 + return 0 + return 1 + + +/* + The HUB idles until it receives information. It then passes on that information + depending on where it came from. + + This is the heart of the Telecommunications Network, sending information where it + is needed. It mainly receives information from long-distance Relays and then sends + that information to be processed. Afterwards it gets the uncompressed information + from Servers/Buses and sends that back to the relay, to then be broadcasted. +*/ + +/obj/machinery/telecomms/hub + name = "Telecommunication Hub" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "hub" + desc = "A mighty piece of hardware used to send/receive massive amounts of data." + density = 1 + anchored = 1 + use_power = USE_POWER_IDLE + idle_power_usage = 1600 + machinetype = 7 + circuit = /obj/item/circuitboard/telecomms/hub + long_range_link = 1 + netspeed = 40 + +/obj/machinery/telecomms/hub/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + if(is_freq_listening(signal)) + if(istype(machine_from, /obj/machinery/telecomms/receiver)) + //If the signal is compressed, send it to the bus. + relay_information(signal, /obj/machinery/telecomms/bus, 1) // ideally relay the copied information to bus units + else + // Get a list of relays that we're linked to, then send the signal to their levels. + relay_information(signal, /obj/machinery/telecomms/relay, 1) + relay_information(signal, /obj/machinery/telecomms/broadcaster, 1) // Send it to a broadcaster. + + +/* + The relay idles until it receives information. It then passes on that information + depending on where it came from. + + The relay is needed in order to send information pass Z levels. It must be linked + with a HUB, the only other machine that can send/receive pass Z levels. +*/ + +/obj/machinery/telecomms/relay + name = "Telecommunication Relay" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "relay" + desc = "A mighty piece of hardware used to send massive amounts of data far away." + density = 1 + anchored = 1 + use_power = USE_POWER_IDLE + idle_power_usage = 600 + machinetype = 8 + produces_heat = 0 + circuit = /obj/item/circuitboard/telecomms/relay + netspeed = 5 + long_range_link = 1 + var/broadcasting = 1 + var/receiving = 1 + +/obj/machinery/telecomms/relay/forceMove(var/newloc) + . = ..(newloc) + listening_level = z + +/obj/machinery/telecomms/relay/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + + // Add our level and send it back + if(can_send(signal)) + signal.data["level"] |= using_map.get_map_levels(listening_level) + +// Checks to see if it can send/receive. + +/obj/machinery/telecomms/relay/proc/can(datum/signal/signal) + if(!on) + return 0 + if(!is_freq_listening(signal)) + return 0 + return 1 + +/obj/machinery/telecomms/relay/proc/can_send(datum/signal/signal) + if(!can(signal)) + return 0 + return broadcasting + +/obj/machinery/telecomms/relay/proc/can_receive(datum/signal/signal) + if(!can(signal)) + return 0 + return receiving + +/* + The bus mainframe idles and waits for hubs to relay them signals. They act + as junctions for the network. + + They transfer uncompressed subspace packets to processor units, and then take + the processed packet to a server for logging. + + Link to a subspace hub if it can't send to a server. +*/ + +/obj/machinery/telecomms/bus + name = "Bus Mainframe" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "bus" + desc = "A mighty piece of hardware used to send massive amounts of data quickly." + density = 1 + anchored = 1 + use_power = USE_POWER_IDLE + idle_power_usage = 1000 + machinetype = 2 + circuit = /obj/item/circuitboard/telecomms/bus + netspeed = 40 + var/change_frequency = 0 + +/obj/machinery/telecomms/bus/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + + if(is_freq_listening(signal)) + + if(change_frequency) + signal.frequency = change_frequency + + if(!istype(machine_from, /obj/machinery/telecomms/processor) && machine_from != src) // Signal must be ready (stupid assuming machine), let's send it + // send to one linked processor unit + var/send_to_processor = relay_information(signal, /obj/machinery/telecomms/processor) + + if(send_to_processor) + return + // failed to send to a processor, relay information anyway + signal.data["slow"] += rand(1, 5) // slow the signal down only slightly + src.receive_information(signal, src) + + // Try sending it! + var/list/try_send = list(/obj/machinery/telecomms/server, /obj/machinery/telecomms/hub, /obj/machinery/telecomms/broadcaster, /obj/machinery/telecomms/bus) + var/i = 0 + for(var/send in try_send) + if(i) + signal.data["slow"] += rand(0, 1) // slow the signal down only slightly + i++ + var/can_send = relay_information(signal, send) + if(can_send) + break + + + +/* + The processor is a very simple machine that decompresses subspace signals and + transfers them back to the original bus. It is essential in producing audible + data. + + Link to servers if bus is not present +*/ + +/obj/machinery/telecomms/processor + name = "Processor Unit" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "processor" + desc = "This machine is used to process large quantities of information." + density = 1 + anchored = 1 + use_power = USE_POWER_IDLE + idle_power_usage = 600 + machinetype = 3 + delay = 5 + circuit = /obj/item/circuitboard/telecomms/processor + var/process_mode = 1 // 1 = Uncompress Signals, 0 = Compress Signals + +/obj/machinery/telecomms/processor/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + + if(is_freq_listening(signal)) + + if(process_mode) + signal.data["compression"] = 0 // uncompress subspace signal + else + signal.data["compression"] = 100 // even more compressed signal + + if(istype(machine_from, /obj/machinery/telecomms/bus)) + relay_direct_information(signal, machine_from) // send the signal back to the machine + else // no bus detected - send the signal to servers instead + signal.data["slow"] += rand(5, 10) // slow the signal down + relay_information(signal, /obj/machinery/telecomms/server) + + +/* + The server logs all traffic and signal data. Once it records the signal, it sends + it to the subspace broadcaster. + + Store a maximum of 100 logs and then deletes them. +*/ + + +/obj/machinery/telecomms/server + name = "Telecommunication Server" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "comm_server" + desc = "A machine used to store data and network statistics." + density = 1 + anchored = 1 + use_power = USE_POWER_IDLE + idle_power_usage = 300 + machinetype = 4 + circuit = /obj/item/circuitboard/telecomms/server + var/list/log_entries = list() + var/list/stored_names = list() + var/list/TrafficActions = list() + var/logs = 0 // number of logs + var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes) + + var/list/memory = list() // stored memory + var/rawcode = "" // the code to compile (raw text) + var/datum/TCS_Compiler/Compiler // the compiler that compiles and runs the code + var/autoruncode = 0 // 1 if the code is set to run every time a signal is picked up + + var/encryption = "null" // encryption key: ie "password" + var/salt = "null" // encryption salt: ie "123comsat" + // would add up to md5("password123comsat") + var/obj/item/radio/headset/server_radio = null + +/obj/machinery/telecomms/server/Initialize() + Compiler = new + Compiler.Holder = src + server_radio = new + . = ..() + +/obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + + if(signal.data["message"]) + + if(is_freq_listening(signal)) + + if(traffic > 0) + totaltraffic += traffic // add current traffic to total traffic + + //Is this a test signal? Bypass logging + if(signal.data["type"] != SIGNAL_TEST) + + // If signal has a message and appropriate frequency + + update_logs() + + var/datum/comm_log_entry/log = new + var/mob/M = signal.data["mob"] + + // Copy the signal.data entries we want + log.parameters["mobtype"] = signal.data["mobtype"] + log.parameters["job"] = signal.data["job"] + log.parameters["key"] = signal.data["key"] + log.parameters["vmessage"] = multilingual_to_message(signal.data["message"]) + log.parameters["vname"] = signal.data["vname"] + log.parameters["message"] = multilingual_to_message(signal.data["message"]) + log.parameters["name"] = signal.data["name"] + log.parameters["realname"] = signal.data["realname"] + log.parameters["timecode"] = worldtime2stationtime(world.time) + + var/race = "unknown" + if(ishuman(M)) + var/mob/living/carbon/human/H = M + race = "[H.species.name]" + log.parameters["intelligible"] = 1 + else if(isbrain(M)) + race = "Brain" + log.parameters["intelligible"] = 1 + else if(M.isMonkey()) + race = "Monkey" + else if(issilicon(M)) + race = "Artificial Life" + log.parameters["intelligible"] = 1 + else if(isslime(M)) + race = "Slime" + else if(isanimal(M)) + race = "Domestic Animal" + + log.parameters["race"] = race + + if(!istype(M, /mob/new_player) && M) + log.parameters["uspeech"] = M.universal_speak + else + log.parameters["uspeech"] = 0 + + // If the signal is still compressed, make the log entry gibberish + if(signal.data["compression"] > 0) + log.parameters["message"] = Gibberish(multilingual_to_message(signal.data["message"]), signal.data["compression"] + 50) + log.parameters["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50) + log.parameters["name"] = Gibberish(signal.data["name"], signal.data["compression"] + 50) + log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50) + log.parameters["vname"] = Gibberish(signal.data["vname"], signal.data["compression"] + 50) + log.input_type = "Corrupt File" + + // Log and store everything that needs to be logged + log_entries.Add(log) + if(!(signal.data["name"] in stored_names)) + stored_names.Add(signal.data["name"]) + logs++ + signal.data["server"] = src + + // Give the log a name + var/identifier = num2text( rand(-1000,1000) + world.time ) + log.name = "data packet ([md5(identifier)])" + + if(Compiler && autoruncode) + Compiler.Run(signal) // execute the code + + var/can_send = relay_information(signal, /obj/machinery/telecomms/hub) + if(!can_send) + relay_information(signal, /obj/machinery/telecomms/broadcaster) + + +/obj/machinery/telecomms/server/proc/setcode(var/t) + if(t) + if(istext(t)) + rawcode = t + +/obj/machinery/telecomms/server/proc/compile() + if(Compiler) + return Compiler.Compile(rawcode) + +/obj/machinery/telecomms/server/proc/update_logs() + // start deleting the very first log entry + if(logs >= 400) + for(var/i = 1, i <= logs, i++) // locate the first garbage collectable log entry and remove it + var/datum/comm_log_entry/L = log_entries[i] + if(L.garbage_collector) + log_entries.Remove(L) + logs-- + break + +/obj/machinery/telecomms/server/proc/add_entry(var/content, var/input) + var/datum/comm_log_entry/log = new + var/identifier = num2text( rand(-1000,1000) + world.time ) + log.name = "[input] ([md5(identifier)])" + log.input_type = input + log.parameters["message"] = content + log.parameters["timecode"] = stationtime2text() + log_entries.Add(log) + update_logs() + + + + +// Simple log entry datum + +/datum/comm_log_entry + var/parameters = list() // carbon-copy to signal.data[] + var/name = "data packet (#)" + var/garbage_collector = 1 // if set to 0, will not be garbage collected + var/input_type = "Speech File" + +//Generic telecomm connectivity test proc +/proc/can_telecomm(var/atom/A, var/atom/B, var/ad_hoc = FALSE) + if(!A || !B) + log_debug("can_telecomm(): Undefined endpoints!") + return FALSE + + //Can't in this case, obviously! + if(is_jammed(A) || is_jammed(B)) + return FALSE + + //Items don't have a Z when inside an object or mob + var/turf/src_z = get_z(A) + var/turf/dst_z = get_z(B) + + //Nullspace, probably. + if(!src_z || !dst_z) + return FALSE + + //We can do the simple check first, if you have ad_hoc radios. + if(ad_hoc && src_z == dst_z) + return TRUE + + return src_z in using_map.get_map_levels(dst_z, TRUE, om_range = DEFAULT_OVERMAP_RANGE) diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm index 394b8b60b6..2d26f199ce 100644 --- a/code/game/machinery/telecomms/telemonitor.dm +++ b/code/game/machinery/telecomms/telemonitor.dm @@ -27,7 +27,7 @@ data["temp"] = temp var/list/machinelist = list() - for(var/obj/machinery/telecomms/T in machinelist) + for(var/obj/machinery/telecomms/T in src.machinelist) machinelist.Add(list(list( "id" = T.id, "name" = T.name, @@ -108,7 +108,7 @@ network = newnet machinelist = list() set_temp("NEW NETWORK TAG SET IN ADDRESS \[[network]\]", "good") - + . = TRUE if("cleartemp") @@ -125,4 +125,4 @@ return 1 /obj/machinery/computer/telecomms/monitor/proc/set_temp(var/text, var/color = "average") - temp = list("color" = color, "text" = text) \ No newline at end of file + temp = list("color" = color, "text" = text) diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 2a632e8d28..383ad01889 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -1539,7 +1539,7 @@ shaved */ /datum/sprite_accessory/facial_hair - icon = 'icons/mob/Human_face.dmi' + icon = 'icons/mob/human_face.dmi' color_blend_mode = ICON_ADD /datum/sprite_accessory/facial_hair/shaved diff --git a/polaris.dme b/polaris.dme index 1b62dc655e..15aad86337 100644 --- a/polaris.dme +++ b/polaris.dme @@ -800,7 +800,7 @@ #include "code\game\machinery\telecomms\logbrowser.dm" #include "code\game\machinery\telecomms\machine_interactions.dm" #include "code\game\machinery\telecomms\presets.dm" -#include "code\game\machinery\telecomms\telecomunications.dm" +#include "code\game\machinery\telecomms\telecommunications.dm" #include "code\game\machinery\telecomms\telemonitor.dm" #include "code\game\machinery\telecomms\traffic_control.dm" #include "code\game\machinery\virtual_reality\ar_console.dm"