diff --git a/code/__DEFINES/mergers.dm b/code/__DEFINES/mergers.dm new file mode 100644 index 00000000000..7d80634f491 --- /dev/null +++ b/code/__DEFINES/mergers.dm @@ -0,0 +1,5 @@ +// Defines relating to merger datums + +// Indexes for the turf packet list +#define MERGE_TURF_PACKET_DIR 1 +#define MERGE_TURF_PACKET_ATOMS 2 diff --git a/code/datums/mergers/_merger.dm b/code/datums/mergers/_merger.dm index b7529ba9a24..8e7d656bcc0 100644 --- a/code/datums/mergers/_merger.dm +++ b/code/datums/mergers/_merger.dm @@ -11,7 +11,7 @@ /// The arbitrary "owner" member of the merge group var/atom/origin - /// A list of all members in the group + /// Assoc list of all members in the group -> dirs from them to their connected nighbors var/list/members = list() #if MERGERS_DEBUG @@ -83,56 +83,78 @@ addtimer(CALLBACK(src, .proc/Refresh), 1, TIMER_UNIQUE) /datum/merger/proc/Refresh() - var/list/tips = list() - var/list/checked_turfs = list() - var/list/new_members = list() + // List of turf -> list(interesting dir, found matching atoms) + var/list/found_turfs = list() if(origin) - tips[origin] = NORTH|EAST|SOUTH|WEST - new_members[origin] = NONE - while(length(tips)) - var/atom/focus = tips[length(tips)] - var/dirs_to_check = tips[focus] - tips.len-- + var/turf/starting = get_turf(origin) + check_turf(starting, found_turfs, NONE) + for(var/i = 1; i <= length(found_turfs), i++) + var/turf/focus = found_turfs[i] + var/list/focus_packet = found_turfs[focus] + var/dirs_checked = focus_packet[MERGE_TURF_PACKET_DIR] for(var/dir in GLOB.cardinals) - if(!(dirs_to_check & dir)) + if(dirs_checked & dir) continue var/turf/location = get_step(focus, dir) - if(!location || checked_turfs[location]) + if(!location) continue - checked_turfs[location] = TRUE - for(var/i in location) - var/atom/movable/thing = i - if(!merged_typecache[thing.type]) - continue - if(attempt_merge_proc && !call(thing, attempt_merge_proc)(src, new_members)) - continue - if(thing.mergers && thing.mergers[id] != src) - var/datum/merger/existing = thing.mergers[id] - qdel(src) - existing.Refresh() + if(!check_turf(location, found_turfs, dir)) + if(QDELETED(src)) return - new_members[focus] |= dir // This is not a list, value of the members list is a bitfield of dirs - var/next_dirs = turn(dir, 180) - new_members[thing] |= next_dirs - next_dirs = ~next_dirs - var/existing = tips[thing] || (NORTH|EAST|SOUTH|WEST) - tips[thing] = existing & next_dirs + continue + focus_packet[MERGE_TURF_PACKET_DIR] |= dir - var/list/leaving_members = members - new_members + // Now that we have an idea of our connecting directions, build the fresh members list + var/list/fresh_members = list() + for(var/turf/location as anything in found_turfs) + var/list/turf_packet = found_turfs[location] + var/connected_dirs = turf_packet[MERGE_TURF_PACKET_DIR] + for(var/datum/member as anything in turf_packet[MERGE_TURF_PACKET_ATOMS]) + fresh_members[member] = connected_dirs + + var/list/leaving_members = members - fresh_members for(var/atom/thing as anything in leaving_members) RemoveMember(thing) - var/list/joining_members = new_members - members + var/list/joining_members = fresh_members - members for(var/atom/thing as anything in joining_members) AddMember(thing, joining_members[thing]) // They may not need a full update but the connected dirs could change - for(var/atom/thing as anything in new_members) - members[thing] = new_members[thing] + for(var/atom/thing as anything in fresh_members) + members[thing] = fresh_members[thing] SEND_SIGNAL(src, COMSIG_MERGER_REFRESH_COMPLETE, leaving_members, joining_members) if(!length(members)) qdel(src) +// Checks to see if the passed in location contains something interesting to us. If it does, return TRUE, otherwise return false +// If it is interesting, we add it to our processing list +/datum/merger/proc/check_turf(turf/location, list/found_turfs, asking_from) + var/found_something = FALSE + // if asking_from is invalid (like if it's 0), we get a random output. that's bad, let's check for falsyness + var/us_to_them = asking_from && turn(asking_from, 180) + + if(found_turfs[location]) + found_turfs[location][MERGE_TURF_PACKET_DIR] |= us_to_them + return TRUE + + for(var/atom/movable/thing as anything in location) + if(!merged_typecache[thing.type]) + continue + if(attempt_merge_proc && !call(thing, attempt_merge_proc)(src, found_turfs)) + continue + if(thing.mergers && thing.mergers[id] != src) + var/datum/merger/existing = thing.mergers[id] + qdel(src) + existing.Refresh() + return FALSE + if(!found_turfs[location]) + found_turfs[location] = list(us_to_them, list()) + found_turfs[location][MERGE_TURF_PACKET_ATOMS] += thing + found_something = TRUE + + return found_something + #undef MERGERS_DEBUG diff --git a/tgstation.dme b/tgstation.dme index bd7feda4b95..0baa67e1ed4 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -107,6 +107,7 @@ #include "code\__DEFINES\mecha.dm" #include "code\__DEFINES\melee.dm" #include "code\__DEFINES\memory_defines.dm" +#include "code\__DEFINES\mergers.dm" #include "code\__DEFINES\mob_spawn.dm" #include "code\__DEFINES\mobs.dm" #include "code\__DEFINES\mod.dm"