Reduces processing of connections, zones now rely on the air properties of constituent turfs (they will adjust these properties when turfs are added or removed)

This commit is contained in:
SkyMarshal
2013-09-06 15:41:50 -07:00
parent e8f9d19c75
commit 3b2da3238c
5 changed files with 180 additions and 155 deletions
+95 -55
View File
@@ -13,68 +13,62 @@ Indirect connections will not merge the two zones after they reach equilibrium.
var/zone/zone_A
var/zone/zone_B
var/ref_A
var/ref_B
var/indirect = CONNECTION_DIRECT //If the connection is purely indirect, the zones should not join.
var/last_updated //The tick at which this was last updated.
var/no_zone_count = 0
/connection/New(turf/T,turf/O)
. = ..()
A = T
B = O
if(A.zone && B.zone)
if(!A.zone.connections) A.zone.connections = list()
if(!A.zone.connections)
A.zone.connections = list()
A.zone.connections += src
zone_A = A.zone
ref_A = "\ref[A]"
if(!B.zone.connections) B.zone.connections = list()
if(!B.zone.connections)
B.zone.connections = list()
B.zone.connections += src
zone_B = B.zone
ref_B = "\ref[B]"
if(ref_A in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[ref_A]
if(A in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[A]
connections.Add(src)
else
air_master.turfs_with_connections[ref_A] = list(src)
air_master.turfs_with_connections[A] = list(src)
if(ref_B in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[ref_B]
if(B in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[B]
connections.Add(src)
else
air_master.turfs_with_connections[ref_B] = list(src)
air_master.turfs_with_connections[B] = list(src)
if(A.CanPass(null, B, 0, 0))
ConnectZones(A.zone, B.zone, 1)
if(A.HasDoor(B) || B.HasDoor(A))
if(!A.CanPass(null, B, 1.5, 1))
indirect = CONNECTION_INDIRECT
ConnectZones(A.zone, B.zone, indirect)
else
ConnectZones(A.zone, B.zone)
indirect = CONNECTION_CLOSED
else
world.log << "Attempted to create connection object for non-zone tiles: [T] ([T.x],[T.y],[T.z]) -> [O] ([O.x],[O.y],[O.z])"
del(src)
SoftDelete()
/connection/Del()
//remove connections from master lists.
if(ref_B in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[ref_B]
if(B in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[B]
connections.Remove(src)
if(ref_A in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[ref_A]
if(A in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[A]
connections.Remove(src)
//Remove connection from zones.
@@ -104,13 +98,52 @@ Indirect connections will not merge the two zones after they reach equilibrium.
//Disconnect zones while handling unusual conditions.
// e.g. loss of a zone on a turf
if(A && A.zone && B && B.zone)
DisconnectZones(A.zone, B.zone)
DisconnectZones(zone_A, zone_B)
//Finally, preform actual deletion.
. = ..()
/connection/proc/SoftDelete()
//remove connections from master lists.
if(B in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[B]
connections.Remove(src)
if(A in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[A]
connections.Remove(src)
//Remove connection from zones.
if(A)
if(A.zone && A.zone.connections)
A.zone.connections.Remove(src)
if(!A.zone.connections.len)
A.zone.connections = null
if(istype(zone_A) && (!A || A.zone != zone_A))
if(zone_A.connections)
zone_A.connections.Remove(src)
if(!zone_A.connections.len)
zone_A.connections = null
if(B)
if(B.zone && B.zone.connections)
B.zone.connections.Remove(src)
if(!B.zone.connections.len)
B.zone.connections = null
if(istype(zone_B) && (!B || B.zone != zone_B))
if(zone_B.connections)
zone_B.connections.Remove(src)
if(!zone_B.connections.len)
zone_B.connections = null
//Disconnect zones while handling unusual conditions.
// e.g. loss of a zone on a turf
DisconnectZones(zone_A, zone_B)
/connection/proc/ConnectZones(var/zone/zone_1, var/zone/zone_2, open = 0)
//Sanity checking
@@ -140,6 +173,18 @@ Indirect connections will not merge the two zones after they reach equilibrium.
zone_2.connected_zones += zone_1
zone_2.connected_zones[zone_1] = 1
if(open == CONNECTION_DIRECT)
if(!zone_1.direct_connections)
zone_1.direct_connections = list(src)
else
zone_1.direct_connections += src
if(!zone_2.direct_connections)
zone_2.direct_connections = list(src)
else
zone_2.direct_connections += src
//Handle closed connections.
else
@@ -193,6 +238,15 @@ Indirect connections will not merge the two zones after they reach equilibrium.
if(!zone_2.connected_zones.len)
zone_2.connected_zones = null
if(indirect == CONNECTION_DIRECT)
zone_1.direct_connections -= src
if(!zone_1.direct_connections.len)
zone_1.direct_connections = null
zone_2.direct_connections -= src
if(!zone_2.direct_connections.len)
zone_2.direct_connections = null
else
//Handle disconnection of closed zones.
if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) )
@@ -222,35 +276,23 @@ Indirect connections will not merge the two zones after they reach equilibrium.
//Check sanity: existance of turfs
if(!A || !B)
del src
SoftDelete()
return
//Check sanity: loss of zone
if(!A.zone || !B.zone)
SoftDelete()
return
//Check sanity: zones are different
if(A.zone == B.zone)
del src
//Check sanity: same turfs as before.
if(ref_A != "\ref[A]" || ref_B != "\ref[B]")
del src
SoftDelete()
return
//Handle zones changing on a turf.
if((A.zone && A.zone != zone_A) || (B.zone && B.zone != zone_B))
Sanitize()
//Manage sudden loss of a turfs zone. (e.g. a wall being built)
if(!A.zone || !B.zone)
no_zone_count++
if(no_zone_count >= 5)
//world.log << "Connection removed: [A] or [B] missing a zone."
del src
return 0
return 1
/connection/proc/CheckPassSanity()
//Sanity check, first.
Cleanup()
if(A.zone && B.zone)
//If no walls are blocking us...
@@ -263,7 +305,7 @@ Indirect connections will not merge the two zones after they reach equilibrium.
//Make and remove connections to let air pass.
if(indirect == CONNECTION_CLOSED)
DisconnectZones(A.zone, B.zone)
ConnectZones(A.zone, B.zone, 1)
ConnectZones(A.zone, B.zone, door_pass + 1)
if(door_pass)
indirect = CONNECTION_DIRECT
@@ -278,7 +320,8 @@ Indirect connections will not merge the two zones after they reach equilibrium.
//If I can no longer pass air, better delete
else
del src
SoftDelete()
return
/connection/proc/Sanitize()
//If the zones change on connected turfs, update it.
@@ -294,9 +337,6 @@ Indirect connections will not merge the two zones after they reach equilibrium.
A = temp
zone_B = B.zone
zone_A = A.zone
var/temp_ref = ref_A
ref_A = ref_B
ref_B = temp_ref
return
//Handle removal of connections from archived zones.
+12 -12
View File
@@ -199,7 +199,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
checking_connections = TRUE
for(var/connection/C in connections_to_check)
C.CheckPassSanity()
C.Cleanup()
checking_connections = FALSE
@@ -209,6 +209,17 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
else
connections_to_check = list()
//Process zones.
if(.)
tick_progress = "zone/process()"
for(var/zone/Z in zones)
if(Z.last_update < current_cycle)
var/output = Z.process()
if(Z)
Z.last_update = current_cycle
if(. && Z && !output)
. = 0
//Ensure tiles still have zones.
if(.)
tick_progress = "tiles_to_reconsider_zones"
@@ -227,17 +238,6 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
else
tiles_to_reconsider_zones = list()
//Process zones.
if(.)
tick_progress = "zone/process()"
for(var/zone/Z in zones)
if(Z.last_update < current_cycle)
var/output = Z.process()
if(Z)
Z.last_update = current_cycle
if(. && Z && !output)
. = 0
//Process fires.
if(.)
tick_progress = "active_hotspots (fire)"
+4 -5
View File
@@ -157,14 +157,13 @@ proc/ZConnect(turf/simulated/A,turf/simulated/B)
if(!A.zone || !B.zone) return
if(A.zone == B.zone) return
if(A.CanPass(null,B,0,1))
if(A.zone.air.compare(B.zone.air))
return ZMerge(A.zone,B.zone)
//Ensure the connection isn't already made.
if("\ref[A]" in air_master.turfs_with_connections)
for(var/connection/C in air_master.turfs_with_connections["\ref[A]"])
C.Cleanup()
if(C && (C.B == B || C.A == B))
if(A in air_master.turfs_with_connections)
for(var/connection/C in air_master.turfs_with_connections[A])
if(C.B == B || C.A == B)
return
//Make the connection.
+2 -2
View File
@@ -157,8 +157,8 @@
new/zone(list(src))
//Check pass sanity of the connections.
if("\ref[src]" in air_master.turfs_with_connections)
air_master.AddConnectionToCheck(air_master.turfs_with_connections["\ref[src]"])
if(src in air_master.turfs_with_connections)
air_master.AddConnectionToCheck(air_master.turfs_with_connections[src])
if(zone && CanPass(null, src, 0, 0))
+67 -81
View File
@@ -7,11 +7,15 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
var/rebuild = 0 //If 1, zone will be rebuilt on next process. Not sure if used.
var/datum/gas_mixture/air //The air contents of the zone.
var/list/contents //All the tiles that are contained in this zone.
var/list/connections // /connection objects which refer to connections with other zones, e.g. through a door.
var/list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number
//of points they're connected at.
var/list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed.
var/list/unsimulated_tiles // Any space tiles in this list will cause air to flow out.
var/list/connections //connection objects which refer to connections with other zones, e.g. through a door.
var/list/direct_connections //connections which directly connect two zones.
var/list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number
//of points they're connected at.
var/list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed.
var/last_update = 0
var/progress = "nothing"
@@ -49,7 +53,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
zones.Add(src)
//LEGACY, DO NOT USE. Use the SoftDelete proc.
//DO NOT USE. Use the SoftDelete proc.
/zone/Del()
//Ensuring the zone list doesn't get clogged with null values.
for(var/turf/simulated/T in contents)
@@ -64,7 +68,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
. = ..()
//Handles deletion via garbage collection.
//Handles deletion via garbage collection.
/zone/proc/SoftDelete()
zones.Remove(src)
air = null
@@ -96,8 +100,15 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
T.zone.RemoveTurf(T)
contents += T
if(air)
air.oxygen = (air.oxygen * air.group_multiplier + T.oxygen) / (air.group_multiplier + 1)
air.nitrogen = (air.nitrogen * air.group_multiplier + T.nitrogen) / (air.group_multiplier + 1)
air.carbon_dioxide = (air.carbon_dioxide * air.group_multiplier + T.carbon_dioxide) / (air.group_multiplier + 1)
air.toxins = (air.toxins * air.group_multiplier + T.toxins) / (air.group_multiplier + 1)
air.temperature = (air.temperature * air.group_multiplier + T.temperature) / (air.group_multiplier + 1)
air.group_multiplier++
T.zone = src
else
if(!unsimulated_tiles)
unsimulated_tiles = list()
@@ -113,9 +124,19 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
return
contents -= T
if(air)
T.oxygen = air.oxygen
T.nitrogen = air.nitrogen
T.carbon_dioxide = air.carbon_dioxide
T.toxins = air.toxins
T.temperature = air.temperature
air.group_multiplier--
if(T.zone == src)
T.zone = null
if(!contents.len)
SoftDelete()
else if(unsimulated_tiles)
unsimulated_tiles -= T
if(!unsimulated_tiles.len)
@@ -224,17 +245,13 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
progress = "problem with: ZMerge(), a couple of misc procs"
for(var/connection/C in connections)
//Check if the connection is valid first.
if(!C.Cleanup())
continue
if(length(direct_connections))
for(var/connection/C in connections)
//Do merging if conditions are met. Specifically, if there's a non-door connection
//to somewhere with space, the zones are merged regardless of equilibrium, to speed
//up spacing in areas with double-plated windows.
if(C && C.A.zone && C.B.zone)
//indirect = 2 is a direct connection.
if( C.indirect == 2 )
//Do merging if conditions are met. Specifically, if there's a non-door connection
//to somewhere with space, the zones are merged regardless of equilibrium, to speed
//up spacing in areas with double-plated windows.
if(C.A.zone && C.B.zone)
if(C.A.zone.air.compare(C.B.zone.air) || unsimulated_tiles)
ZMerge(C.A.zone,C.B.zone)
@@ -264,6 +281,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
//If that zone has already processed, skip it.
if(Z.last_update > last_update)
continue
if(air && Z.air)
if( abs(air.temperature - Z.air.temperature) > vsc.connection_temperature_delta )
ShareHeat(air, Z.air, closed_connection_zones[Z])
@@ -455,69 +473,45 @@ proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
zone/proc/Rebuild()
//Choose a random turf and regenerate the zone from it.
var
turf/simulated/sample = locate() in contents
list/new_contents
problem = 0
var/list/new_contents
var/list/new_unsimulated
//
var/list/turfs_to_consider = contents.Copy()
var/list/turfs_needing_zones = list()
while(!sample || !sample.CanPass(null, sample, 1.5, 1))
if(sample)
turfs_to_consider.Remove(sample)
sample = locate() in turfs_to_consider
if(!sample)
break
var/list/zones_to_check_connections = list(src)
if(!istype(sample) || !sample.CanPass(null, sample, 1.5, 1)) //Not a single valid turf.
for(var/turf/simulated/T in contents)
air_master.tiles_to_update |= T
if(!locate(/turf/simulated/floor) in contents)
for(var/turf/simulated/turf in contents)
air_master.ReconsiderTileZone(turf)
return SoftDelete()
new_contents = FloodFill(sample)
new_contents = FloodFill(locate(/turf/simulated/floor) in contents)
var/list/new_unsimulated = ( unsimulated_tiles ? unsimulated_tiles : list() )
new_unsimulated = ( unsimulated_tiles ? unsimulated_tiles : list() )
//Now, we have allocated the new turfs into proper lists, and we can start actually rebuilding.
//If something isn't carried over, it will need a new zone.
for(var/turf/T in contents)
if(!(T in new_contents))
RemoveTurf(T)
turfs_needing_zones += T
//Handle addition of new turfs
for(var/turf/S in new_contents)
if(!istype(S, /turf/simulated))
new_unsimulated |= S
new_contents.Remove(S)
if(contents.len != new_contents.len)
problem = 1
//If something new is added, we need to deal with it seperately.
else if(!(S in contents) && istype(S, /turf/simulated))
if(!(S.zone in zones_to_check_connections))
zones_to_check_connections += S.zone
//If something isn't carried over, there was a complication.
for(var/turf/T in contents)
if(!(T in new_contents))
T.zone = null
problem = 1
S.zone.RemoveTurf(S)
AddTurf(S)
if(problem)
//Build some new zones for stuff that wasn't included.
var/list/turf/simulated/rebuild_turfs = contents - new_contents
var/list/turf/simulated/reconsider_turfs = list()
contents = new_contents
for(var/turf/simulated/T in rebuild_turfs)
if(!T.zone && T.CanPass(null, T, 1.5, 1))
var/zone/Z = new /zone(T)
Z.air.copy_from(air)
else
reconsider_turfs |= T
for(var/turf/simulated/T in reconsider_turfs)
if(!T.zone && T.CanPass(null, T, 1.5, 1))
var/zone/Z = new /zone(T)
Z.air.copy_from(air)
else if(!T in air_master.tiles_to_update)
air_master.tiles_to_update.Add(T)
for(var/turf/simulated/T in contents)
if(T.zone && T.zone != src)
T.zone.RemoveTurf(T)
T.zone = src
else if(!T.zone)
T.zone = src
air.group_multiplier = contents.len
//Handle the addition of new unsimulated tiles.
unsimulated_tiles = null
if(new_unsimulated.len)
@@ -529,20 +523,12 @@ zone/proc/Rebuild()
if(istype(T) && T.zone && S.CanPass(null, T, 0, 0))
T.zone.AddTurf(S)
//UNUSED
/*
zone/proc/connected_zones()
//A legacy proc for getting connected zones.
. = list()
for(var/connection/C in connections)
var/zone/Z
if(C.A.zone == src)
Z = C.B.zone
else
Z = C.A.zone
//Finally, handle the orphaned turfs
if(Z in .)
.[Z]++
else
. += Z
.[Z] = 1*/
for(var/turf/simulated/T in turfs_needing_zones)
if(!T.zone)
zones_to_check_connections += new /zone(T)
for(var/zone/zone in zones_to_check_connections)
for(var/connection/C in zone.connections)
C.Cleanup()