From 4e09cf33acb7046fad417d38fb215f1ece4c21f4 Mon Sep 17 00:00:00 2001 From: Ccomp5950 Date: Tue, 18 Feb 2014 02:11:59 -0600 Subject: [PATCH 1/4] Code effeciency project: /proc/get_mobs_in_view Before: Everytime you say something. This proc is ran. Along with it, recurses through EVERY /obj/ & /mob/ in view's contents, and EVERY /obj/ & /mob/ in that contents...and once again. After: Fuck recursion, we're going to loop through clients and see if they are within any obj's or mobs within one iteration. MUCH cheaper, and probably less buggy. If someone can't hear everyone and they are within an object and it's not catching? add it to the list commented for it of type checks. --- code/__HELPERS/game.dm | 49 +++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index e2c04299f1c..bf2672d099a 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -161,6 +161,8 @@ // The old system would loop through lists for a total of 5000 per function call, in an empty server. // This new system will loop at around 1000 in an empty server. +// SCREW THAT SHIT, we're not recursing. + /proc/get_mobs_in_view(var/R, var/atom/source) // Returns a list of mobs in range of R from source. Used in radio and say code. @@ -172,18 +174,45 @@ var/list/range = hear(R, T) - for(var/atom/A in range) - if(ismob(A)) - var/mob/M = A - if(M.client) - hear += M - //world.log << "Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])" - else if(istype(A, /obj/item/device/radio)) - hear += A + for(var/mob/M in range) + if(M.client) + hear += M + + var/list/objects = list() - if(isobj(A) || ismob(A)) - hear |= recursive_mob_check(A, hear, 3, 1, 0, 1) + var/list/obj_to_check = list() //IF SOMEONE DOESN'T HEAR SOMETHING AND ARE IN INSIDE A CONTAINER ADD IT TO THIS LIST. + obj_to_check += typesof(/obj/item/device/paicard) + obj_to_check += typesof(/obj/item/device/aicard) + obj_to_check += typesof(/obj/machinery/computer/aifixer) + for(var/obj/O in range) //Get a list of objects in hearing range. We'll check to see if any clients have their "eye" set to the object + if(istype(O, /obj/item/device/radio)) //This avoids all that bullshit with recursion. FUCK RECURSION ~Ccomp + hear += O + if(O.type in obj_to_check) + for(var/mob/living/M in O.contents) + if(!(M in hear)) + hear += M + + + objects += O + + for(var/client/C in clients) + if(!istype(C) || !C.eye) + continue //I have no idea when this client check would be needed, but if this runtimes people won't hear anything + //So kinda paranoid about runtime avoidance. + if(C.mob in hear) + continue + if(C.eye in (hear|objects)) + if(!(C.mob in hear)) + hear += C.mob + + else if(!(C.mob in hear)) + if(C.mob.loc in (hear|objects)) + hear += C.mob + else if(C.mob.loc.loc in (hear|objects)) + hear += C.mob + + return hear From 5909abb08008f43f10179cfbd0d43e5ad7c7d877 Mon Sep 17 00:00:00 2001 From: Ccomp5950 Date: Tue, 18 Feb 2014 05:40:06 -0600 Subject: [PATCH 2/4] This is rather ironic... My VERY FIRST PR, I used it to make ghost chat be bold, instead of using viewers() to figure out what ghosts could see the mob, I used get_mob_in_view() which sounded pretty descriptive. Unfortunately for me it was one of the most CPU intensive ways of determining who could view the speaker for this. So yeah, removing the second get_mobs_in_view and replacing it with viewers() Yes this code has been in since Oct/Nov time frame :( --- code/modules/mob/living/say.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 13523072cab..93369793586 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -302,7 +302,7 @@ var/list/department_radio_keys = list( var/list/listening listening = get_mobs_in_view(message_range, src) - var/list/onscreen = get_mobs_in_view(7, src) + var/list/onscreen = viewers() for(var/mob/M in player_list) if (!M.client) continue //skip monkeys and leavers From d29a7fb260e9934595dcb02a118c919217d9bbb0 Mon Sep 17 00:00:00 2001 From: Ccomp5950 Date: Tue, 18 Feb 2014 06:47:06 -0600 Subject: [PATCH 3/4] pAI / MMI emote fixes. Fixes #4191 --- code/modules/mob/emote.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index e2125ada66c..c33732ed133 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -38,13 +38,15 @@ // Type 1 (Visual) emotes are sent to anyone in view of the item if (m_type & 1) - for (var/mob/O in viewers(src, null)) + var/list/can_see = get_mobs_in_view(1,src) //Allows silicon & mmi mobs carried around to see the emotes of the person carrying them around. + can_see |= viewers(src,null) + for (var/mob/O in can_see) O.show_message(message, m_type) // Type 2 (Audible) emotes are sent to anyone in hear range // of the *LOCATION* -- this is important for pAIs to be heard else if (m_type & 2) - for (var/mob/O in hearers(get_turf(src), null)) + for (var/mob/O in get_mobs_in_view(7,src)) O.show_message(message, m_type) /mob/proc/emote_dead(var/message) From af193516081321c047f766488ac7a6f193fbaacc Mon Sep 17 00:00:00 2001 From: Ccomp5950 Date: Tue, 18 Feb 2014 06:51:45 -0600 Subject: [PATCH 4/4] Further optimizations, no need to loop through items with multiple istype checks --- code/__HELPERS/game.dm | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index bf2672d099a..856d7b5f6f7 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -180,20 +180,7 @@ var/list/objects = list() - var/list/obj_to_check = list() //IF SOMEONE DOESN'T HEAR SOMETHING AND ARE IN INSIDE A CONTAINER ADD IT TO THIS LIST. - obj_to_check += typesof(/obj/item/device/paicard) - obj_to_check += typesof(/obj/item/device/aicard) - obj_to_check += typesof(/obj/machinery/computer/aifixer) - for(var/obj/O in range) //Get a list of objects in hearing range. We'll check to see if any clients have their "eye" set to the object - if(istype(O, /obj/item/device/radio)) //This avoids all that bullshit with recursion. FUCK RECURSION ~Ccomp - hear += O - if(O.type in obj_to_check) - for(var/mob/living/M in O.contents) - if(!(M in hear)) - hear += M - - objects += O for(var/client/C in clients) @@ -207,9 +194,11 @@ hear += C.mob else if(!(C.mob in hear)) - if(C.mob.loc in (hear|objects)) + if(C.mob.loc && C.mob.loc in (hear|objects)) hear += C.mob - else if(C.mob.loc.loc in (hear|objects)) + else if(C.mob.loc.loc && C.mob.loc.loc in (hear|objects)) + hear += C.mob + else if(C.mob.loc.loc.loc && C.mob.loc.loc.loc in (hear|objects)) //Going a little deeper hear += C.mob