From b687b75bca09f0f85c93a5c94f73ee8456e7383c Mon Sep 17 00:00:00 2001 From: "CIB123@gmail.com" Date: Mon, 9 Jul 2012 15:16:00 +0000 Subject: [PATCH] Optimized radio code broadcasting code. Rather than calling a function on every single radio object which expensively collects hearers(in closets etc.), the proc will now instead build a list of radios. This list is then passed to another proc, which iterates through all clients in the world, and checks if the client's mob can hear the message. Note that I did shallow testing, but deeper issues may still be present with stuff like pAIs which I wasn't able to test on my single player server. If any other problems are found, please notify me. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@4019 316c924e-a436-60f5-8080-3fe189b3f50e --- code/defines/procs/gamehelpers.dm | 25 ++++++++++ code/game/machinery/telecomms/broadcaster.dm | 19 +++++--- code/game/objects/radio/intercom.dm | 31 +++++-------- code/game/objects/radio/radio.dm | 48 +++++++------------- code/global.dm | 4 ++ code/modules/client/client procs.dm | 4 ++ code/modules/mob/say.dm | 8 ++++ 7 files changed, 80 insertions(+), 59 deletions(-) diff --git a/code/defines/procs/gamehelpers.dm b/code/defines/procs/gamehelpers.dm index 10e1dc7adbd..9925ee0072f 100644 --- a/code/defines/procs/gamehelpers.dm +++ b/code/defines/procs/gamehelpers.dm @@ -219,6 +219,31 @@ return hear + +/proc/get_mobs_in_radio_ranges(var/list/obj/item/device/radio/radios) + // Returns a list of mobs who can hear any of the radios given in @radios + + var/list/hearers = list() + + // Try to find all the players who can hear the message + for(var/key in client_list) + var/client/C = client_list[key] + var/mob/M = C.mob + if(!M) continue + + var/atom/ear = M.get_ear() + if(!ear) continue + + // Now see if they're near any broadcasting radio + for(var/obj/item/device/radio/R in radios) + var/turf/radio_loc = get_turf(R) + if(ear in view(R.canhear_range,radio_loc)) + hearers += M + break + + return hearers + + #define SIGN(X) ((X<0)?-1:1) proc diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index bee35cac592..e2f7f1a58b1 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -208,15 +208,15 @@ var/list/recentmessages = list() // global list of recent messages broadcasted : var/display_freq = connection.frequency - var/list/receive = list() + var/list/obj/item/device/radio/radios = list() // --- Broadcast only to intercom devices --- if(data == 1) for (var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"]) - - receive |= R.send_hear(display_freq) + if(R.receive_range(display_freq) > 0) + radios += R // --- Broadcast only to intercoms and station-bounced radios --- @@ -227,7 +227,8 @@ var/list/recentmessages = list() // global list of recent messages broadcasted : if(istype(R, /obj/item/device/radio/headset)) continue - receive |= R.send_hear(display_freq) + if(R.receive_range(display_freq) > 0) + radios += R // --- Broadcast to syndicate radio! --- @@ -237,15 +238,19 @@ var/list/recentmessages = list() // global list of recent messages broadcasted : for (var/obj/item/device/radio/R in syndicateconnection.devices["[RADIO_CHAT]"]) - receive |= R.send_hear(SYND_FREQ) - + if(R.receive_range(SYND_FREQ) > 0) + radios += R // --- Broadcast to ALL radio devices --- else for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) + if(R.receive_range(display_freq) > 0) + radios += R - receive |= R.send_hear(display_freq) + + // Get a list of mobs who can hear from the radios we collected. + var/list/receive = get_mobs_in_radio_ranges(radios) /* ###### Organize the receivers into categories for displaying the message ###### */ diff --git a/code/game/objects/radio/intercom.dm b/code/game/objects/radio/intercom.dm index 5a5db05bb4d..0c25ddba7c0 100644 --- a/code/game/objects/radio/intercom.dm +++ b/code/game/objects/radio/intercom.dm @@ -4,6 +4,7 @@ icon_state = "intercom" anchored = 1 w_class = 4.0 + canhear_range = 4 var/number = 0 var/anyai = 1 var/mob/living/silicon/ai/ai = list() @@ -26,31 +27,21 @@ send_hear(freq) + var/range = receive_range(freq) + + if(range > 0) + return get_mobs_in_view(canhear_range, src) + + receive_range(freq) if (!(src.wires & WIRE_RECEIVE)) - return + return 0 if (!src.listening) - return + return 0 if(freq == SYND_FREQ) if(!(src.syndie)) - return//Prevents broadcast of messages over devices lacking the encryption - /* - var/turf/T = get_turf(src) - var/list/hear = hearers(7, T) - var/list/V - //find mobs in lockers, cryo and intellycards - for(var/mob/M in world) - if (isturf(M.loc)) - continue //if M can hear us it is already was found by hearers() - if (!M.client) - continue //skip monkeys and leavers - if (!V) //lasy initialisation - V = view(7, T) - if (get_turf(M) in V) //this slow, but I don't think we'd have a lot of wardrobewhores every round --rastaf0 - hear+=M - */ - //return hear + return 0//Prevents broadcast of messages over devices lacking the encryption - return get_mobs_in_view(4, src) + return canhear_range hear_talk(mob/M as mob, msg) diff --git a/code/game/objects/radio/radio.dm b/code/game/objects/radio/radio.dm index 5d0a08dc06a..61f163e7233 100644 --- a/code/game/objects/radio/radio.dm +++ b/code/game/objects/radio/radio.dm @@ -619,27 +619,23 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use return null return */ -/obj/item/device/radio/proc/send_hear(freq) - /* - I'm removing this because this is apparently a REALLY REALLY bad thing and causes - people's transmissions to get cut off. This also means radios have no delay. A - fair price to pay for reliable radios. -- Doohl - if(last_transmission && world.time < (last_transmission + TRANSMISSION_DELAY)) - return - last_transmission = world.time - */ +/obj/item/device/radio/proc/receive_range(freq) + // check if this radio can receive on the given frequency, and if so, + // what the range is in which mobs will hear the radio + // returns: 0 if can't receive, range otherwise + if (!(wires & WIRE_RECEIVE)) - return + return 0 if(freq == SYND_FREQ) if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys - return + return 0 if (!on) - return + return 0 if (!freq) //recieved on main frequency if (!listening) - return + return 0 else var/accept = (freq==frequency && listening) if (!accept) @@ -649,28 +645,16 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use accept = 1 break if (!accept) - return + return 0 - /* // UURAAAGH ALL THE CPUS, WASTED. ALL OF THEM. NO. -- Doohl - var/turf/T = get_turf(src) - var/list/hear = hearers(1, T) - var/list/V - //find mobs in lockers, cryo and intellicards, brains, MMIs, and so on. - for (var/mob/M in world) - if (isturf(M.loc)) - continue //if M can hear us it is already was found by hearers() - if (!M.client) - continue //skip monkeys and leavers - if (!V) //lasy initialisation - V = view(1, T) - if (get_turf(M) in V) //this slow, but I don't think we'd have a lot of wardrobewhores every round --rastaf0 - hear+=M - */ + return canhear_range - /* Instead, let's individually search potential containers for mobs! More verbose but a LOT more efficient and less laggy */ - // Check gamehelpers.dm for the proc definition: +/obj/item/device/radio/proc/send_hear(freq) + var/range = receive_range(freq) + + if(range > 0) + return get_mobs_in_view(canhear_range, src) - return get_mobs_in_view(canhear_range, src) /obj/item/device/radio/examine() set src in view() diff --git a/code/global.dm b/code/global.dm index d082619af1e..71bacc5204d 100644 --- a/code/global.dm +++ b/code/global.dm @@ -11,6 +11,10 @@ var/global/list/processing_objects = list() var/global/list/active_diseases = list() //items that ask to be called every cycle +// This list will map client ckeys to client objects +// It will be automatically kept up to date by client/New and client/Del +var/global/list/client_list = list() + var/global/defer_powernet_rebuild = 0 // true if net rebuild will be called manually after an event var/global/list/global_map = null diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 90d1c2b6bd4..e4042500c0c 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -95,6 +95,8 @@ host = key world.update_status() + client_list[ckey] = src + ..() //calls mob.Login() //Admin Authorisation @@ -109,6 +111,8 @@ //DISCONNECT// ////////////// /client/Del() + client_list.Remove(ckey) + spawn(0) if(holder) del(holder) diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 5f6d33e9900..2b8f31f0cd7 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -70,3 +70,11 @@ /mob/proc/emote(var/act) return + +/mob/proc/get_ear() + // returns an atom representing a location on the map from which this + // mob can hear things + + // should be overloaded for all mobs whose "ear" is separate from their "mob" + + return get_turf(src) \ No newline at end of file