From cb413454a3393cc99f16f277dd002f5409eea68f Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 27 Jul 2014 03:35:25 -0400 Subject: [PATCH] Optimizes atmos machine power updates Makes power usage but atmos machinery less accurate but reduces lag somewhat. --- code/ATMOSPHERICS/atmospherics_helpers.dm | 41 +++++++++-- .../components/binary_devices/pump.dm | 19 ++--- .../components/unary/vent_pump.dm | 70 +++++++------------ .../components/unary/vent_scrubber.dm | 26 +++---- code/modules/power/power.dm | 6 +- code/setup.dm | 3 +- 6 files changed, 91 insertions(+), 74 deletions(-) diff --git a/code/ATMOSPHERICS/atmospherics_helpers.dm b/code/ATMOSPHERICS/atmospherics_helpers.dm index 0e39a60ae3..1b9523cc15 100644 --- a/code/ATMOSPHERICS/atmospherics_helpers.dm +++ b/code/ATMOSPHERICS/atmospherics_helpers.dm @@ -40,7 +40,7 @@ //total_transfer_moles - Limits the amount of moles to filter. The actual amount of gas filtered may also be limited by available_power, if given. //available_power - the maximum amount of power that may be used when filtering gas. If null then the filtering is not limited by power, however power will still be used! /obj/machinery/atmospherics/proc/filter_gas(var/list/filtering, var/datum/gas_mixture/source, var/datum/gas_mixture/sink, var/total_transfer_moles = null, var/available_power = null) - if (source.total_moles < MINUMUM_MOLES_TO_PUMP) + if (source.total_moles < MINUMUM_MOLES_TO_FILTER) return -1 filtering &= source.gas //only filter gasses that are actually there. @@ -50,7 +50,7 @@ var/total_filterable_moles = 0 var/list/specific_power_gas = list() for (var/g in filtering) - if (source.gas[g] < MINUMUM_MOLES_TO_PUMP) + if (source.gas[g] < MINUMUM_MOLES_TO_FILTER) continue var/specific_power = calculate_specific_power_gas(g, source, sink)/ATMOS_FILTER_EFFICIENCY @@ -58,7 +58,7 @@ total_specific_power += specific_power total_filterable_moles += source.gas[g] - if (total_filterable_moles < MINUMUM_MOLES_TO_PUMP) + if (total_filterable_moles < MINUMUM_MOLES_TO_FILTER) return -1 //Figure out how much of each gas to filter @@ -71,7 +71,7 @@ if (available_power && total_specific_power > 0) total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power) - if (total_transfer_moles < MINUMUM_MOLES_TO_PUMP) + if (total_transfer_moles < MINUMUM_MOLES_TO_FILTER) return -1 var/power_draw = 0 @@ -125,7 +125,38 @@ if (usage_amount > active_power_usage - 5) update_use_power(2) else + use_power = 1 //Don't update here. Sure, we will use more power than we are supposed to, but it's easier on CPU + + /* + //This is the correct way to update pump power usage. Unfortunately it is also pretty laggy. + //Leaving this here in case someone finds a way to do this that doesn't involve doing area power updates all the time. update_use_power(1) if (usage_amount > idle_power_usage) - use_power(round(usage_amount)) //in practice it's pretty rare that we will get here, so calling use_power() is alright. \ No newline at end of file + use_power(round(usage_amount)) + */ + +/* +//DEBUG +/var/global/enable_scrubbing = 0 +/var/global/enable_vent_pump = 0 +/var/global/enable_power_net = 0 + +/mob/verb/toggle_scrubbing() + set name = "Toggle Scrubbing" + set category = "Debug" + enable_scrubbing = !enable_scrubbing + world << "enable_scrubbing set to [enable_scrubbing]" + +/mob/verb/toggle_vent_pump() + set name = "Toggle Vent Pumps" + set category = "Debug" + enable_vent_pump = !enable_vent_pump + world << "enable_vent_pump set to [enable_vent_pump]" + +/mob/verb/toggle_pump_powernet() + set name = "Toggle Pump Power Update" + set category = "Debug" + enable_power_net = !enable_power_net + world << "enable_power_net set to [enable_power_net]" +*/ \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm index dd13de5c61..5ba80ff0bf 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm @@ -61,17 +61,17 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/binary/pump/process() if((stat & (NOPOWER|BROKEN)) || !on) - update_use_power(0) + update_use_power(0) //usually we get here because a player turned a pump off - definitely want to update. last_power_draw = 0 last_flow_rate = 0 return - var/power_draw = -1 - if (air1.temperature > 0 || air2.temperature > 0) - var/pressure_delta = target_pressure - air2.return_pressure() + var/power_draw = -1 + var/pressure_delta = target_pressure - air2.return_pressure() - if(pressure_delta > 0.01) - /* TODO Uncomment this once we have a good way to get the volume of a pipe network. + if(pressure_delta > 0.01) + /* TODO Uncomment this once we have a good way to get the volume of a pipe network. + if (air1.temperature > 0 || air2.temperature > 0) //Figure out how much gas to transfer to meet the target pressure. var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature @@ -79,8 +79,8 @@ Thus, the two variables affect pump operation are set in New(): //Return the number of moles that would have to be transfered to bring sink to the target pressure var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION) - */ - power_draw = pump_gas(air1, air2, air1.total_moles, active_power_usage) + */ + power_draw = pump_gas(air1, air2, air1.total_moles, active_power_usage) if(network1) network1.update = 1 @@ -89,7 +89,8 @@ Thus, the two variables affect pump operation are set in New(): network2.update = 1 if (power_draw < 0) - update_use_power(0) + //update_use_power(0) + use_power = 0 //don't force update - easier on CPU last_power_draw = 0 last_flow_rate = 0 else if (power_draw > 0) diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index 3d8483ff26..6312a32f84 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -139,35 +139,26 @@ if (!node) on = 0 if(!can_pump()) - update_use_power(0) + update_use_power(0) //usually we get here because a player turned a pump off - definitely want to update. last_power_draw = 0 last_flow_rate = 0 return 0 var/datum/gas_mixture/environment = loc.return_air() - var/environment_pressure = environment.return_pressure() - - var/pressure_delta = DEFAULT_PRESSURE_DELTA var/power_draw = -1 - if((air_contents.temperature > 0 || environment.temperature > 0) && pressure_delta > 0.5) - if(pump_direction) //internal -> external - if(pressure_checks & PRESSURE_CHECK_EXTERNAL) - pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here - if(pressure_checks & PRESSURE_CHECK_INTERNAL) - pressure_delta = min(pressure_delta, air_contents.return_pressure() - internal_pressure_bound) //decreasing the pressure here - + + //Figure out the target pressure difference + var/pressure_delta = get_pressure_delta(environment) + + if(pressure_delta > 0.5) + if(pump_direction) //internal -> external var/output_volume = environment.volume * environment.group_multiplier var/air_temperature = environment.temperature? environment.volume : air_contents.temperature var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION) power_draw = pump_gas(air_contents, environment, transfer_moles, active_power_usage) else //external -> internal - if(pressure_checks & PRESSURE_CHECK_EXTERNAL) - pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here - if(pressure_checks & PRESSURE_CHECK_INTERNAL) - pressure_delta = min(pressure_delta, internal_pressure_bound - air_contents.return_pressure()) //increasing the pressure here - var/output_volume = air_contents.volume * air_contents.group_multiplier var/air_temperature = air_contents.temperature? air_contents.temperature : environment.temperature var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION) @@ -175,7 +166,7 @@ //limit flow rate from turfs transfer_moles = min(transfer_moles, environment.total_moles*MAX_SIPHON_FLOWRATE/environment.volume) //group_multiplier gets divided out here - power_draw = pump_gas(environment, air_contents, transfer_moles, active_power_usage) + power_draw = pump_gas(environment, air_contents, transfer_moles, active_power_usage) if(network) network.update = 1 @@ -183,7 +174,8 @@ if (power_draw < 0) last_power_draw = 0 last_flow_rate = 0 - update_use_power(0) + //update_use_power(0) + use_power = 0 //don't force update - easier on CPU if (power_draw > 0) handle_pump_power_draw(power_draw) last_power_draw = power_draw @@ -194,35 +186,25 @@ return 1 -//pumps gas from source to sink and returns the power used, or -1 if no pumping was done. -/obj/machinery/atmospherics/unary/vent_pump/proc/transfer_gas(datum/gas_mixture/source, datum/gas_mixture/sink, var/transfer_moles) - if(source.total_moles < MINUMUM_MOLES_TO_PUMP) - return -1 - - //limit transfer_moles by available power - var/specific_power = calculate_specific_power(source, sink)/ATMOS_PUMP_EFFICIENCY //this has to be calculated before we modify any gas mixtures - if (specific_power > 0) - transfer_moles = min(transfer_moles, active_power_usage / specific_power) +/obj/machinery/atmospherics/unary/vent_pump/proc/get_pressure_delta(datum/gas_mixture/environment) + if (air_contents.temperature == 0 && environment.temperature == 0) + return 0 - //Get the gas to be transferred - if (transfer_moles < MINUMUM_MOLES_TO_PUMP) - return -1 //don't bother + var/pressure_delta = DEFAULT_PRESSURE_DELTA + var/environment_pressure = environment.return_pressure() - var/datum/gas_mixture/removed = source.remove(transfer_moles) + if(pump_direction) //internal -> external + if(pressure_checks & PRESSURE_CHECK_EXTERNAL) + pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here + if(pressure_checks & PRESSURE_CHECK_INTERNAL) + pressure_delta = min(pressure_delta, air_contents.return_pressure() - internal_pressure_bound) //decreasing the pressure here + else //external -> internal + if(pressure_checks & PRESSURE_CHECK_EXTERNAL) + pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here + if(pressure_checks & PRESSURE_CHECK_INTERNAL) + pressure_delta = min(pressure_delta, internal_pressure_bound - air_contents.return_pressure()) //increasing the pressure here - if (isnull(removed)) //not sure why this would happen, but it does at the very beginning of the game - return -1 - - last_flow_rate = (removed.total_moles/(removed.total_moles + source.total_moles))*source.volume - - var/power_draw = specific_power*transfer_moles - if (power_draw > 0) - removed.add_thermal_energy(power_draw) - - //merge the removed gas into the sink - sink.merge(removed) - - return power_draw + return pressure_delta //Radio remote control diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index ab60d83998..7e6f9a3600 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -111,33 +111,33 @@ set_frequency(frequency) /obj/machinery/atmospherics/unary/vent_scrubber/process() - ..() + ..() if(stat & (NOPOWER|BROKEN)) return if (!node) on = 0 //broadcast_status() if(!on) - update_use_power(0) + update_use_power(0) //we got here because a player turned a pump off - definitely want to update. return 0 var/datum/gas_mixture/environment = loc.return_air() var/power_draw = -1 - if (environment.temperature > 0 || air_contents.temperature > 0) - if(scrubbing) - //limit flow rate from turfs - var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_FILTER_FLOWRATE/environment.volume) //group_multiplier gets divided out here - - power_draw = filter_gas(scrubbing_gas, environment, air_contents, transfer_moles, active_power_usage) - else //Just siphon all air - //limit flow rate from turfs - var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_SIPHON_FLOWRATE/environment.volume) //group_multiplier gets divided out here + if(scrubbing) + //limit flow rate from turfs + var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_FILTER_FLOWRATE/environment.volume) //group_multiplier gets divided out here + + power_draw = filter_gas(scrubbing_gas, environment, air_contents, transfer_moles, active_power_usage) + else //Just siphon all air + //limit flow rate from turfs + var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_SIPHON_FLOWRATE/environment.volume) //group_multiplier gets divided out here - power_draw = pump_gas(environment, air_contents, transfer_moles, active_power_usage) + power_draw = pump_gas(environment, air_contents, transfer_moles, active_power_usage) if (power_draw < 0) - update_use_power(0) + //update_use_power(0) + use_power = 0 //don't force update. Sure, we will continue to use power even though we're not pumping anything, but it is easier on the CPU else if (power_draw > 0) //last_power_draw = power_draw handle_pump_power_draw(power_draw) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index c634a4a2cb..5512f1ae36 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -42,8 +42,10 @@ if(!src.loc) return 0 - if(!use_power) - return 1 + //This is bad. This makes machines which are switched off not update their stat flag correctly when power_change() is called. + //If use_power is 0, then you probably shouldn't be checking power to begin with. + //if(!use_power) + // return 1 var/area/A = src.loc.loc // make sure it's in an area if(!A || !isarea(A) || !A.master) diff --git a/code/setup.dm b/code/setup.dm index 552386c70b..39b3ca7b04 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -840,4 +840,5 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse #define ATMOS_PUMP_EFFICIENCY 1.0 #define ATMOS_FILTER_EFFICIENCY 0.9 -#define MINUMUM_MOLES_TO_PUMP 0.01 //will not bother pumping or filtering if the gas source as fewer than this amount of moles, to help with performance. \ No newline at end of file +#define MINUMUM_MOLES_TO_PUMP 0.01 //will not bother pumping or filtering if the gas source as fewer than this amount of moles, to help with performance. +#define MINUMUM_MOLES_TO_FILTER 0.1