Optimizes duct reconnecting (#47434)

* optimizes duct connecting

* i hang myself on live television

* yippa ka yay
This commit is contained in:
Time-Green
2019-10-31 00:31:17 +01:00
committed by Rob Bailey
parent 8f5332f489
commit 8393e52a4e
2 changed files with 53 additions and 17 deletions

View File

@@ -14,19 +14,20 @@
///Remove a duct from our network and commit suicide, because this is probably easier than to check who that duct was connected to and what part of us was lost
/datum/ductnet/proc/remove_duct(obj/machinery/duct/ducting)
destroy_network(FALSE)
for(var/A in ducting.neighbours)
var/obj/machinery/duct/D = A
D.attempt_connect() //we destroyed the network, so now we tell the disconnected ducts neighbours they can start making a new ductnet
for(var/obj/machinery/duct/D in ducting.neighbours)
addtimer(CALLBACK(D, /obj/machinery/duct/proc/reconnect), 0) //all needs to happen after the original duct that was destroyed finishes destroying itself
addtimer(CALLBACK(D, /obj/machinery/duct/proc/generate_connects), 0)
qdel(src)
///add a plumbing object to either demanders or suppliers
/datum/ductnet/proc/add_plumber(datum/component/plumbing/P, dir)
if(!P.can_add(src, dir))
return
return FALSE
P.ducts[num2text(dir)] = src
if(dir & P.supply_connects)
suppliers += P
else if(dir & P.demand_connects)
demanders += P
return TRUE
///remove a plumber. we dont delete ourselves because ductnets dont persist through plumbing objects
/datum/ductnet/proc/remove_plumber(datum/component/plumbing/P)
suppliers.Remove(P) //we're probably only in one of these, but Remove() is inherently sane so this is fine

View File

@@ -10,7 +10,7 @@ All the important duct code:
level = 1
///bitfield with the directions we're connected in
var/connects
///set to TRUE to disable smart cable behaviour
///set to TRUE to disable smart duct behaviour
var/dumb = FALSE
///wheter we allow our connects to be changed after initialization or not
var/lock_connects = FALSE
@@ -93,11 +93,11 @@ All the important duct code:
if(!dumb && D.dumb && !(opposite_dir & D.connects))
return
if(dumb && D.dumb && !(connects & D.connects)) //we eliminated a few more scenario in attempt connect
if(dumb && D.dumb && !(connects & D.connects)) //we eliminated a few more scenarios in attempt connect
return
if((duct == D.duct) && duct)//check if we're not just comparing two null values
add_neighbour(D)
add_neighbour(D, direction)
D.add_connects(opposite_dir)
D.update_icon()
@@ -119,8 +119,10 @@ All the important duct code:
else
create_duct()
duct.add_duct(D)
add_neighbour(D)
D.attempt_connect()//tell our buddy its time to pass on the torch of connecting to pipes. This shouldn't ever infinitely loop since it only works on pipes that havent been inductrinated
add_neighbour(D, direction)
//tell our buddy its time to pass on the torch of connecting to pipes. This shouldn't ever infinitely loop since it only works on pipes that havent been inductrinated
D.attempt_connect()
return TRUE
///connect to a plumbing object
/obj/machinery/duct/proc/connect_plumber(datum/component/plumbing/P, direction)
@@ -135,8 +137,9 @@ All the important duct code:
if(opposite_dir & comp_directions)
if(!duct)
create_duct()
duct.add_plumber(P, opposite_dir)
return TRUE
if(duct.add_plumber(P, opposite_dir))
neighbours[P.parent] = direction
return TRUE
///we disconnect ourself from our neighbours. we also destroy our ductnet and tell our neighbours to make a new one
/obj/machinery/duct/proc/disconnect_duct()
anchored = FALSE
@@ -150,20 +153,52 @@ All the important duct code:
new drop_on_wrench(drop_location())
qdel(src)
///''''''''''''''''optimized''''''''''''''''' proc for quickly reconnecting after a duct net was destroyed
/obj/machinery/duct/proc/reconnect()
if(neighbours.len && !duct)
create_duct()
for(var/atom/movable/AM in neighbours)
if(istype(AM, /obj/machinery/duct))
var/obj/machinery/duct/D = AM
if(D.duct)
if(D.duct == duct) //we're already connected
continue
else
duct.assimilate(D.duct)
continue
else
duct.add_duct(D)
D.reconnect()
else
var/datum/component/plumbing/P = AM.GetComponent(/datum/component/plumbing)
if(AM in get_step(src, neighbours[AM])) //did we move?
if(P)
connect_plumber(P, neighbours[AM])
else
neighbours -= AM //we moved
///Special proc to draw a new connect frame based on neighbours. not the norm so we can support multiple duct kinds
/obj/machinery/duct/proc/generate_connects()
if(lock_connects)
return
connects = 0
for(var/A in neighbours)
connects |= neighbours[A]
update_icon()
///create a new duct datum
/obj/machinery/duct/proc/create_duct()
duct = new()
duct.add_duct(src)
///add a duct as neighbour. this means we're connected and will connect again if we ever regenerate
/obj/machinery/duct/proc/add_neighbour(obj/machinery/duct/D)
/obj/machinery/duct/proc/add_neighbour(obj/machinery/duct/D, direction)
if(!(D in neighbours))
neighbours += D
neighbours[D] = direction
if(!(src in D.neighbours))
D.neighbours += src
D.neighbours[src] = turn(direction, 180)
///remove all our neighbours, and remove us from our neighbours aswell
/obj/machinery/duct/proc/lose_neighbours()
for(var/A in neighbours)
var/obj/machinery/duct/D = A
for(var/obj/machinery/duct/D in neighbours)
D.neighbours.Remove(src)
neighbours = list()
///add a connect direction
@@ -272,7 +307,7 @@ All the important duct code:
return
add_connects(direction) //the connect of the other duct is handled in connect_network, but do this here for the parent duct because it's not necessary in normal cases
add_neighbour(D)
add_neighbour(D, direction)
connect_network(D, direction, TRUE)
update_icon()
///has a total of 5 layers and doesnt give a shit about color. its also dumb so doesnt autoconnect.