From f76f5ae53213255a04bd2246ff91539b5ff31bcd Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Sun, 8 Sep 2013 17:34:22 -0700 Subject: [PATCH] First pass on experimental change that allows zones to "Sleep" --- code/ZAS/Debug.dm | 13 +-- code/ZAS/FEA_system.dm | 73 +++++++++++++++-- code/ZAS/Functions.dm | 4 +- code/ZAS/ZAS_Turfs.dm | 24 +++--- code/ZAS/ZAS_Zones.dm | 104 +++++++++++++++++++++--- code/global.dm | 2 +- code/modules/admin/verbs/diagnostics.dm | 49 +++++------ 7 files changed, 205 insertions(+), 64 deletions(-) diff --git a/code/ZAS/Debug.dm b/code/ZAS/Debug.dm index 762843d5b1..5ac704cf9f 100644 --- a/code/ZAS/Debug.dm +++ b/code/ZAS/Debug.dm @@ -126,10 +126,11 @@ zone/proc/DebugDisplay(client/client) client.images -= client.zone_debug_images[src] client.zone_debug_images.Remove(src) - for(var/zone/Z in zones) - if(Z.air == air && Z != src) - var/turf/zloc = pick(Z.contents) - client << "\red Illegal air datum shared by: [zloc.loc.name]" + if(air_master) + for(var/zone/Z in air_master.zones) + if(Z.air == air && Z != src) + var/turf/zloc = pick(Z.contents) + client << "\red Illegal air datum shared by: [zloc.loc.name]" client/proc/TestZASRebuild() @@ -181,7 +182,7 @@ client/proc/TestZASRebuild() sleep(5) if(turfs[current]) - current.overlays += overlays[turfs[current]] + current.overlays -= overlays[turfs[current]] turfs[current] = lowest_id current.overlays += overlays[lowest_id] sleep(5) @@ -209,4 +210,4 @@ client/proc/TestZASRebuild() for(var/turf/current in turfs) current.overlays -= overlays - return final_arrangement + return final_arrangement \ No newline at end of file diff --git a/code/ZAS/FEA_system.dm b/code/ZAS/FEA_system.dm index 508cbb0125..004de68358 100644 --- a/code/ZAS/FEA_system.dm +++ b/code/ZAS/FEA_system.dm @@ -53,6 +53,9 @@ Important Procedures */ +#define ZONE_ACTIVE 1 +#define ZONE_SLEEPING 0 + var/tick_multiplier = 2 atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) @@ -105,6 +108,14 @@ var/datum/controller/air_system/air_master var/list/connections_to_check = list() var/list/connections_to_check_alternate + var/list/potential_intrazone_connections = list() + + //Zone lists + var/list/active_zones = list() + var/list/zones_needing_rebuilt = list() + var/list/zones = list() + + var/current_cycle = 0 var/update_delay = 5 //How long between check should it try to process atmos again. var/failed_ticks = 0 //How many ticks have runtimed? @@ -170,7 +181,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun current_cycle++ //If there are tiles to update, do so. - tick_progress = "update_air_properties" + tick_progress = "updating turf properties" if(tiles_to_update.len) updating_tiles = TRUE @@ -192,17 +203,49 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun tiles_to_update |= tiles_to_update_alternate tiles_to_update_alternate = null + //Rebuild zones. + if(.) + tick_progress = "rebuilding zones" + if(zones_needing_rebuilt.len) + for(var/zone/zone in zones_needing_rebuilt) + zone.Rebuild() + + zones_needing_rebuilt = list() + //Check sanity on connection objects. if(.) - tick_progress = "connections_to_check" + tick_progress = "checking/creating connections" if(connections_to_check.len) checking_connections = TRUE for(var/connection/C in connections_to_check) C.Cleanup() + for(var/turf/simulated/turf_1 in potential_intrazone_connections) + for(var/turf/simulated/turf_2 in potential_intrazone_connections[turf_1]) + + if(!turf_1.zone || !turf_2.zone) + continue + + if(turf_1.zone == turf_2.zone) + continue + + var/should_skip = FALSE + if(turf_1 in air_master.turfs_with_connections) + + for(var/connection/C in turfs_with_connections[turf_1]) + if(C.B == turf_2 || C.A == turf_2) + should_skip = TRUE + break + if(should_skip) + continue + + new /connection(turf_1, turf_2) + checking_connections = FALSE + potential_intrazone_connections = list() + if(connections_to_check_alternate) connections_to_check = connections_to_check_alternate connections_to_check_alternate = null @@ -211,8 +254,8 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun //Process zones. if(.) - tick_progress = "zone/process()" - for(var/zone/Z in zones) + tick_progress = "processing zones" + for(var/zone/Z in active_zones) if(Z.last_update < current_cycle) var/output = Z.process() if(Z) @@ -222,7 +265,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun //Ensure tiles still have zones. if(.) - tick_progress = "tiles_to_reconsider_zones" + tick_progress = "reconsidering zones on turfs" if(tiles_to_reconsider_zones.len) reconsidering_zones = TRUE @@ -240,7 +283,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun //Process fires. if(.) - tick_progress = "active_hotspots (fire)" + tick_progress = "processing fire" for(var/obj/fire/F in active_hotspots) if(. && F && !F.process()) . = 0 @@ -297,3 +340,21 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun else tiles_to_reconsider_zones |= zoneless_turf + + +/datum/controller/air_system/proc/AddIntrazoneConnection(var/turf/simulated/A, var/turf/simulated/B) + if(!istype(A) || !istype(B)) + return + + if(A in potential_intrazone_connections) + if(B in potential_intrazone_connections[A]) + return + + if (B in potential_intrazone_connections) + if(A in potential_intrazone_connections[B]) + return + + potential_intrazone_connections[B] += A + + else + potential_intrazone_connections[B] = list(A) \ No newline at end of file diff --git a/code/ZAS/Functions.dm b/code/ZAS/Functions.dm index 4a1ffaaea2..3037e13f41 100644 --- a/code/ZAS/Functions.dm +++ b/code/ZAS/Functions.dm @@ -155,7 +155,9 @@ proc/ZConnect(turf/simulated/A,turf/simulated/B) //Make some preliminary checks to see if the connection is valid. if(!A.zone || !B.zone) return - if(A.zone == B.zone) return + if(A.zone == B.zone) + air_master.AddIntrazoneConnection(A,B) + return if(A.CanPass(null, B, 1.5, 1) && A.zone.air.compare(B.zone.air)) return ZMerge(A.zone,B.zone) diff --git a/code/ZAS/ZAS_Turfs.dm b/code/ZAS/ZAS_Turfs.dm index d376d927f5..5280c57250 100644 --- a/code/ZAS/ZAS_Turfs.dm +++ b/code/ZAS/ZAS_Turfs.dm @@ -20,22 +20,21 @@ return GM -/turf/remove_air(amount as num, var/filtered = 0) +/turf/remove_air(amount as num) var/datum/gas_mixture/GM = new - var/sum = oxygen + carbon_dioxide + nitrogen + (toxins*(1-filtered)) + var/sum = oxygen + carbon_dioxide + nitrogen + toxins if(sum>0) GM.oxygen = (oxygen/sum)*amount GM.carbon_dioxide = (carbon_dioxide/sum)*amount GM.nitrogen = (nitrogen/sum)*amount - GM.toxins = ((toxins/sum)*amount)*(1-filtered) + GM.toxins = (toxins/sum)*amount GM.temperature = temperature GM.update_values() return GM - /turf/simulated/var/current_graphic = null /turf/simulated/var/tmp/datum/gas_mixture/air @@ -96,7 +95,7 @@ /turf/simulated/assume_air(datum/gas_mixture/giver) if(!giver) return 0 if(zone) - zone.air.merge(giver) + zone.assume_air(giver) return 1 else return ..() @@ -110,21 +109,20 @@ else return ..() -/turf/simulated/remove_air(amount as num, var/filtered = 0) +/turf/simulated/remove_air(amount as num) if(zone) - var/datum/gas_mixture/removed = null - removed = zone.air.remove(amount, filtered) - return removed + return zone.remove_air(amount) + else if(air) var/datum/gas_mixture/removed = null - removed = air.remove(amount, filtered) + removed = air.remove(amount) if(air.check_tile_graphic()) update_visuals(air) return removed else - return ..(amount, filtered) + return ..() /turf/simulated/proc/update_air_properties() var/air_directions_archived = air_check_directions @@ -179,7 +177,7 @@ //If the tile is in our own zone, and we cannot connect to it, better rebuild. if(istype(NT,/turf/simulated) && NT in zone.contents) - zone.rebuild = 1 + air_master.zones_needing_rebuilt.Add(zone) //Parse if we need to remove the tile, or rebuild the zone. else if(istype(NT) && NT in zone.unsimulated_tiles) @@ -197,7 +195,7 @@ //The unsimulated turf is adjacent to another one of our zone's turfs, // better rebuild to be sure we didn't get cut in twain if(consider_rebuild) - zone.rebuild = 1 + air_master.zones_needing_rebuilt.Add(zone) //Not adjacent to anything, and unsimulated. Goodbye~ else diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm index 37aabee83b..7bb8abd6b4 100644 --- a/code/ZAS/ZAS_Zones.dm +++ b/code/ZAS/ZAS_Zones.dm @@ -1,11 +1,12 @@ -var/list/zones = list() var/list/DoorDirections = list(NORTH,WEST) //Which directions doors turfs can connect to zones var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs can connect to zones /zone var/dbg_output = 0 //Enables debug output. - 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/datum/gas_mixture/archived_air + var/list/contents //All the tiles that are contained in this zone. var/list/unsimulated_tiles // Any space tiles in this list will cause air to flow out. @@ -17,6 +18,9 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs var/list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed. var/last_update = 0 + var/last_rebuilt = 0 + var/status = ZONE_ACTIVE + var/interactions_with_neighbors = 0 var/progress = "nothing" @@ -50,7 +54,9 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs air.update_values() //Add this zone to the global list. - zones.Add(src) + if(air_master) + air_master.zones.Add(src) + air_master.active_zones.Add(src) //DO NOT USE. Use the SoftDelete proc. @@ -63,14 +69,21 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs if(src in Z.connected_zones) Z.connected_zones.Remove(src) air_master.AddConnectionToCheck(connections) - zones.Remove(src) + + if(air_master) + air_master.zones.Remove(src) + air_master.active_zones.Remove(src) + air_master.zones_needing_rebuilt.Remove(src) air = null . = ..() //Handles deletion via garbage collection. /zone/proc/SoftDelete() - zones.Remove(src) + if(air_master) + air_master.zones.Remove(src) + air_master.active_zones.Remove(src) + air_master.zones_needing_rebuilt.Remove(src) air = null //Ensuring the zone list doesn't get clogged with null values. @@ -149,11 +162,6 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs progress = "problem with: Rebuild()" - //Does rebuilding stuff. - if(rebuild) - rebuild = 0 - Rebuild() //Shoving this into a proc. - if(!contents.len) //If we got soft deleted. return @@ -253,10 +261,17 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs if(Z.last_update > last_update) continue + //Handle adjacent zones that are sleeping + if(Z.status == ZONE_SLEEPING) + if(air.compare(Z.air)) + continue + + else + Z.SetStatus(ZONE_ACTIVE) + if(air && Z.air) //Ensure we're not doing pointless calculations on equilibrium zones. - var/moles_delta = abs(air.total_moles() - Z.air.total_moles()) - if(moles_delta > 0.1 || abs(air.temperature - Z.air.temperature) > 0.1) + if(!air.compare(Z.air)) if(abs(Z.air.return_pressure() - air.return_pressure()) > vsc.airflow_lightest_pressure) Airflow(src,Z) var/unsimulated_boost = 0 @@ -267,17 +282,75 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs unsimulated_boost = max(0, min(3, unsimulated_boost)) ShareRatio( air , Z.air , connected_zones[Z] + unsimulated_boost) + Z.interactions_with_neighbors++ + interactions_with_neighbors++ + for(var/zone/Z in closed_connection_zones) //If that zone has already processed, skip it. if(Z.last_update > last_update) continue + var/handle_temperature = abs(air.temperature - Z.air.temperature) > vsc.connection_temperature_delta + + if(Z.status == ZONE_SLEEPING) + if (handle_temperature) + Z.SetStatus(ZONE_ACTIVE) + else + continue + if(air && Z.air) - if( abs(air.temperature - Z.air.temperature) > vsc.connection_temperature_delta ) + if( handle_temperature ) ShareHeat(air, Z.air, closed_connection_zones[Z]) + Z.interactions_with_neighbors++ + interactions_with_neighbors++ + + if(!interactions_with_neighbors && !unsimulated_tiles) + SetStatus(ZONE_SLEEPING) + + interactions_with_neighbors = 0 + progress = "all components completed successfully, the problem is not here" + +/zone/proc/SetStatus(var/new_status) + if(status == ZONE_SLEEPING && new_status == ZONE_ACTIVE) + air_master.active_zones.Add(src) + status = ZONE_ACTIVE + + else if(status == ZONE_ACTIVE && new_status == ZONE_SLEEPING) + air_master.active_zones.Remove(src) + status = ZONE_SLEEPING + if(!archived_air) + archived_air = new + archived_air.copy_from(air) + + +/zone/proc/assume_air(var/datum/gas_mixture/giver) + if(status == ZONE_ACTIVE) + return air.merge(giver) + + else + var/result = air.merge(giver) + + if(!archived_air.compare(air)) + SetStatus(ZONE_ACTIVE) + + return result + + +/zone/proc/remove_air(var/amount) + if(status == ZONE_ACTIVE) + return air.remove(amount) + + else + var/result = air.remove(amount) + + if(!archived_air.compare(air)) + SetStatus(ZONE_ACTIVE) + + return result + //////////////// //Air Movement// //////////////// @@ -463,6 +536,11 @@ proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) //Used for updating zone geometry when a zone is cut into two parts. zone/proc/Rebuild() + if(last_rebuilt == air_master.current_cycle) + return + + last_rebuilt = air_master.current_cycle + var/list/new_zone_contents = IsolateContents() if(new_zone_contents.len == 1) return diff --git a/code/global.dm b/code/global.dm index 69678943ab..68d1fe6aee 100644 --- a/code/global.dm +++ b/code/global.dm @@ -193,7 +193,7 @@ var/list/AAlarmWireColorToIndex #define SPEED_OF_LIGHT_SQ 9e+16 #define FIRE_DAMAGE_MODIFIER 0.0215 //Higher values result in more external fire damage to the skin (default 0.0215) #define AIR_DAMAGE_MODIFIER 2.025 //More means less damage from hot air scalding lungs, less = more damage. (default 2.025) -#define INFINITY 1e31 //closer then enough +#define INFINITY 1.#INF //Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam #define MAX_MESSAGE_LEN 1024 diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index 1e328970fd..f7a0025621 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -2,45 +2,46 @@ set category = "Debug" set name = "Show Air Report" - /*(!master_controller || !air_master) + if(!master_controller || !air_master) alert(usr,"Master_controller or air_master not found.","Air Report") - return 0 + return - var/active_groups = 0 - var/inactive_groups = 0 - var/active_tiles = 0 - for(var/datum/air_group/group in air_master.air_groups) - if(group.group_processing) - active_groups++ - else - inactive_groups++ - active_tiles += group.members.len + var/active_groups = air_master.active_zones.len + var/inactive_groups = air_master.zones.len - active_groups var/hotspots = 0 - for(var/obj/effect/hotspot/hotspot in world) + for(var/obj/fire/hotspot in world) hotspots++ + var/active_on_main_station = 0 + var/inactive_on_main_station = 0 + for(var/zone/zone in air_master.zones) + var/turf/simulated/turf = locate() in zone.contents + if(turf && turf.z == 1) + if(zone.status) + active_on_main_station++ + else + inactive_on_main_station++ + var/output = {"AIR SYSTEMS REPORT
General Processing Data
-# of Groups: [air_master.air_groups.len]
+ Cycle: [air_master.current_cycle]
+ Groups: [air_master.zones.len]
---- Active: [active_groups]
----- Inactive: [inactive_groups]
--------- Tiles: [active_tiles]
-# of Active Singletons: [air_master.active_singletons.len]
+---- Inactive: [inactive_groups]

+---- Active on station: [active_on_main_station]
+---- Inactive on station: [inactive_on_main_station]

Special Processing Data
-Hotspot Processing: [hotspots]
-High Temperature Processing: [air_master.active_super_conductivity.len]
-High Pressure Processing: [air_master.high_pressure_delta.len] (not yet implemented)
-
+ Hotspot Processing: [hotspots]
+
Geometry Processing Data
-Group Rebuild: [air_master.groups_to_rebuild.len]
-Tile Update: [air_master.tiles_to_update.len]
+ Tile Update: [air_master.tiles_to_update.len]
"} usr << browse(output,"window=airreport") - feedback_add_details("admin_verb","SAR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -*/ + + /client/proc/air_status(turf/target as turf) set category = "Debug" set name = "Display Air Status"