mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-21 13:05:36 +01:00
Fixes big roundstart ductnets breaking world init (#58659)
closes: #58623 (Having two stationary plumbing tanks connected broke the map) you can now map infinitely huge plumbing networks Byond mistakes big chains of connecting ducts for an infinite loops, so when a lot of ducts (about 60) initialize at once and chain connect, byond kills the worldtick. Plumbing already had an internal duct limit of about 800~ ducts, which has now finally been fixed aswell. The plumbing subsystem (SSfluids, I need to rename this shit) tells one duct to start connecting and uses the timer subsystem to call them one by one.
This commit is contained in:
+13
-3
@@ -1,23 +1,29 @@
|
||||
///We handle the unity part of plumbing. We track who is connected to who.
|
||||
/datum/ductnet
|
||||
///Stuff that can supply chems
|
||||
var/list/suppliers = list()
|
||||
////Stuff that can take chems
|
||||
var/list/demanders = list()
|
||||
///All the ducts that make this network
|
||||
var/list/obj/machinery/duct/ducts = list()
|
||||
|
||||
///Max reagents we can carry per tick
|
||||
var/capacity
|
||||
|
||||
///Add a duct to our network
|
||||
/datum/ductnet/proc/add_duct(obj/machinery/duct/D)
|
||||
if(!D || (D in ducts))
|
||||
return
|
||||
ducts += D
|
||||
D.duct = src
|
||||
|
||||
///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/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)
|
||||
addtimer(CALLBACK(D, /obj/machinery/duct/proc/attempt_connect)) //needs to happen after qdel
|
||||
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))
|
||||
@@ -28,6 +34,7 @@
|
||||
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
|
||||
@@ -38,6 +45,7 @@
|
||||
P.ducts -= dir
|
||||
if(!ducts.len) //there were no ducts, so it was a direct connection. we destroy ourselves since a ductnet with only one plumber and no ducts is worthless
|
||||
destroy_network()
|
||||
|
||||
///we combine ductnets. this occurs when someone connects to seperate sets of fluid ducts
|
||||
/datum/ductnet/proc/assimilate(datum/ductnet/D)
|
||||
ducts.Add(D.ducts)
|
||||
@@ -53,7 +61,9 @@
|
||||
var/obj/machinery/duct/M = A
|
||||
M.duct = src //forget your old master
|
||||
|
||||
destroy_network()
|
||||
D.ducts.Cut() //clear this so the other network doesnt clear the ducts along with themselves (this took the life out of me)
|
||||
D.destroy_network()
|
||||
|
||||
///destroy the network and tell all our ducts and plumbers we are gone
|
||||
/datum/ductnet/proc/destroy_network(delete=TRUE)
|
||||
for(var/A in suppliers + demanders)
|
||||
|
||||
@@ -63,9 +63,7 @@ All the important duct code:
|
||||
if(D.duct_layer & duct_layer)
|
||||
disconnect_duct()
|
||||
|
||||
if(active)
|
||||
attempt_connect()
|
||||
|
||||
attempt_connect()
|
||||
AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
|
||||
|
||||
///start looking around us for stuff to connect to
|
||||
@@ -132,9 +130,11 @@ All the important duct code:
|
||||
else
|
||||
create_duct()
|
||||
duct.add_duct(D)
|
||||
|
||||
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()
|
||||
|
||||
//Delegate to timer subsystem so its handled the next tick and doesnt cause byond to mistake it for an infinite loop and kill the game
|
||||
addtimer(CALLBACK(D, .proc/attempt_connect))
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -170,31 +170,6 @@ 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
|
||||
if(AM in get_step(src, neighbours[AM])) //did we move?
|
||||
for(var/plumber in AM.GetComponents(/datum/component/plumbing))
|
||||
if(!plumber) //apparently yes it will be null hahahaasahsdvashufv
|
||||
return
|
||||
connect_plumber(plumber, 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)
|
||||
|
||||
Reference in New Issue
Block a user