Optimizes atmos machine power updates

Makes power usage but atmos machinery less accurate but reduces lag
somewhat.
This commit is contained in:
mwerezak
2014-07-27 03:35:25 -04:00
parent 293855c48e
commit cb413454a3
6 changed files with 91 additions and 74 deletions

View File

@@ -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. //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! //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) /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 return -1
filtering &= source.gas //only filter gasses that are actually there. filtering &= source.gas //only filter gasses that are actually there.
@@ -50,7 +50,7 @@
var/total_filterable_moles = 0 var/total_filterable_moles = 0
var/list/specific_power_gas = list() var/list/specific_power_gas = list()
for (var/g in filtering) for (var/g in filtering)
if (source.gas[g] < MINUMUM_MOLES_TO_PUMP) if (source.gas[g] < MINUMUM_MOLES_TO_FILTER)
continue continue
var/specific_power = calculate_specific_power_gas(g, source, sink)/ATMOS_FILTER_EFFICIENCY var/specific_power = calculate_specific_power_gas(g, source, sink)/ATMOS_FILTER_EFFICIENCY
@@ -58,7 +58,7 @@
total_specific_power += specific_power total_specific_power += specific_power
total_filterable_moles += source.gas[g] total_filterable_moles += source.gas[g]
if (total_filterable_moles < MINUMUM_MOLES_TO_PUMP) if (total_filterable_moles < MINUMUM_MOLES_TO_FILTER)
return -1 return -1
//Figure out how much of each gas to filter //Figure out how much of each gas to filter
@@ -71,7 +71,7 @@
if (available_power && total_specific_power > 0) if (available_power && total_specific_power > 0)
total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power) 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 return -1
var/power_draw = 0 var/power_draw = 0
@@ -125,7 +125,38 @@
if (usage_amount > active_power_usage - 5) if (usage_amount > active_power_usage - 5)
update_use_power(2) update_use_power(2)
else 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) update_use_power(1)
if (usage_amount > idle_power_usage) 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. 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]"
*/

View File

@@ -61,17 +61,17 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/binary/pump/process() /obj/machinery/atmospherics/binary/pump/process()
if((stat & (NOPOWER|BROKEN)) || !on) 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_power_draw = 0
last_flow_rate = 0 last_flow_rate = 0
return return
var/power_draw = -1 var/power_draw = -1
if (air1.temperature > 0 || air2.temperature > 0) var/pressure_delta = target_pressure - air2.return_pressure()
var/pressure_delta = target_pressure - air2.return_pressure()
if(pressure_delta > 0.01) if(pressure_delta > 0.01)
/* TODO Uncomment this once we have a good way to get the volume of a pipe network. /* 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. //Figure out how much gas to transfer to meet the target pressure.
var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature 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 //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) 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) if(network1)
network1.update = 1 network1.update = 1
@@ -89,7 +89,8 @@ Thus, the two variables affect pump operation are set in New():
network2.update = 1 network2.update = 1
if (power_draw < 0) 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_power_draw = 0
last_flow_rate = 0 last_flow_rate = 0
else if (power_draw > 0) else if (power_draw > 0)

View File

@@ -139,35 +139,26 @@
if (!node) if (!node)
on = 0 on = 0
if(!can_pump()) 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_power_draw = 0
last_flow_rate = 0 last_flow_rate = 0
return 0 return 0
var/datum/gas_mixture/environment = loc.return_air() var/datum/gas_mixture/environment = loc.return_air()
var/environment_pressure = environment.return_pressure()
var/pressure_delta = DEFAULT_PRESSURE_DELTA
var/power_draw = -1 var/power_draw = -1
if((air_contents.temperature > 0 || environment.temperature > 0) && pressure_delta > 0.5)
if(pump_direction) //internal -> external //Figure out the target pressure difference
if(pressure_checks & PRESSURE_CHECK_EXTERNAL) var/pressure_delta = get_pressure_delta(environment)
pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here
if(pressure_checks & PRESSURE_CHECK_INTERNAL) if(pressure_delta > 0.5)
pressure_delta = min(pressure_delta, air_contents.return_pressure() - internal_pressure_bound) //decreasing the pressure here if(pump_direction) //internal -> external
var/output_volume = environment.volume * environment.group_multiplier var/output_volume = environment.volume * environment.group_multiplier
var/air_temperature = environment.temperature? environment.volume : air_contents.temperature var/air_temperature = environment.temperature? environment.volume : air_contents.temperature
var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION) 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) power_draw = pump_gas(air_contents, environment, transfer_moles, active_power_usage)
else //external -> internal 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/output_volume = air_contents.volume * air_contents.group_multiplier
var/air_temperature = air_contents.temperature? air_contents.temperature : environment.temperature var/air_temperature = air_contents.temperature? air_contents.temperature : environment.temperature
var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION) var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
@@ -175,7 +166,7 @@
//limit flow rate from turfs //limit flow rate from turfs
transfer_moles = min(transfer_moles, environment.total_moles*MAX_SIPHON_FLOWRATE/environment.volume) //group_multiplier gets divided out here 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) if(network)
network.update = 1 network.update = 1
@@ -183,7 +174,8 @@
if (power_draw < 0) if (power_draw < 0)
last_power_draw = 0 last_power_draw = 0
last_flow_rate = 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) if (power_draw > 0)
handle_pump_power_draw(power_draw) handle_pump_power_draw(power_draw)
last_power_draw = power_draw last_power_draw = power_draw
@@ -194,35 +186,25 @@
return 1 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/get_pressure_delta(datum/gas_mixture/environment)
/obj/machinery/atmospherics/unary/vent_pump/proc/transfer_gas(datum/gas_mixture/source, datum/gas_mixture/sink, var/transfer_moles) if (air_contents.temperature == 0 && environment.temperature == 0)
if(source.total_moles < MINUMUM_MOLES_TO_PUMP) return 0
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)
//Get the gas to be transferred var/pressure_delta = DEFAULT_PRESSURE_DELTA
if (transfer_moles < MINUMUM_MOLES_TO_PUMP) var/environment_pressure = environment.return_pressure()
return -1 //don't bother
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 pressure_delta
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
//Radio remote control //Radio remote control

View File

@@ -111,33 +111,33 @@
set_frequency(frequency) set_frequency(frequency)
/obj/machinery/atmospherics/unary/vent_scrubber/process() /obj/machinery/atmospherics/unary/vent_scrubber/process()
..() ..()
if(stat & (NOPOWER|BROKEN)) if(stat & (NOPOWER|BROKEN))
return return
if (!node) if (!node)
on = 0 on = 0
//broadcast_status() //broadcast_status()
if(!on) 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 return 0
var/datum/gas_mixture/environment = loc.return_air() var/datum/gas_mixture/environment = loc.return_air()
var/power_draw = -1 var/power_draw = -1
if (environment.temperature > 0 || air_contents.temperature > 0) if(scrubbing)
if(scrubbing) //limit flow rate from turfs
//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
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)
power_draw = filter_gas(scrubbing_gas, environment, air_contents, transfer_moles, active_power_usage) else //Just siphon all air
else //Just siphon all air //limit flow rate from turfs
//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
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) 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) else if (power_draw > 0)
//last_power_draw = power_draw //last_power_draw = power_draw
handle_pump_power_draw(power_draw) handle_pump_power_draw(power_draw)

View File

@@ -42,8 +42,10 @@
if(!src.loc) if(!src.loc)
return 0 return 0
if(!use_power) //This is bad. This makes machines which are switched off not update their stat flag correctly when power_change() is called.
return 1 //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 var/area/A = src.loc.loc // make sure it's in an area
if(!A || !isarea(A) || !A.master) if(!A || !isarea(A) || !A.master)

View File

@@ -840,4 +840,5 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse
#define ATMOS_PUMP_EFFICIENCY 1.0 #define ATMOS_PUMP_EFFICIENCY 1.0
#define ATMOS_FILTER_EFFICIENCY 0.9 #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. #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