-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy pathdatum_pipeline.dm
272 lines (224 loc) · 9.97 KB
/
datum_pipeline.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/datum/pipeline
var/datum/gas_mixture/air
var/list/datum/gas_mixture/other_airs
var/list/obj/machinery/atmospherics/pipe/members
var/list/obj/machinery/atmospherics/components/other_atmos_machines
var/update = TRUE
var/building = FALSE
/datum/pipeline/New()
other_airs = list()
members = list()
other_atmos_machines = list()
SSair.networks += src
/datum/pipeline/Destroy()
SSair.networks -= src
if(building)
SSair.remove_from_expansion(src)
if(air && air.return_volume())
temporarily_store_air()
for(var/obj/machinery/atmospherics/pipe/considered_pipe in members)
considered_pipe.parent = null
if(QDELETED(considered_pipe))
continue
SSair.add_to_rebuild_queue(considered_pipe)
for(var/obj/machinery/atmospherics/components/considered_component in other_atmos_machines)
considered_component.nullify_pipenet(src)
return ..()
/datum/pipeline/process()
if(!update || building)
return
update = FALSE
reconcile_air()
update = air.react(src)
/datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/base)
building = TRUE
var/volume = 0
if(istype(base, /obj/machinery/atmospherics/pipe))
var/obj/machinery/atmospherics/pipe/considered_pipe = base
volume = considered_pipe.volume
members += considered_pipe
if(considered_pipe.air_temporary)
air = considered_pipe.air_temporary
considered_pipe.air_temporary = null
else
add_machinery_member(base)
if(!air)
air = new
air.set_volume(volume)
SSair.add_to_expansion(src, base)
///Has the same effect as build_pipeline(), but this doesn't queue its work, so overrun abounds. It's useful for the pregame
/datum/pipeline/proc/build_pipeline_blocking(obj/machinery/atmospherics/base)
var/volume = 0
if(istype(base, /obj/machinery/atmospherics/pipe))
var/obj/machinery/atmospherics/pipe/considered_pipe = base
volume = considered_pipe.volume
members += considered_pipe
if(considered_pipe.air_temporary)
air = considered_pipe.air_temporary
considered_pipe.air_temporary = null
else
add_machinery_member(base)
if(!air)
air = new
var/list/possible_expansions = list(base)
while(possible_expansions.len)
for(var/obj/machinery/atmospherics/borderline in possible_expansions)
var/list/result = borderline.pipeline_expansion(src)
if(!result?.len)
possible_expansions -= borderline
continue
for(var/obj/machinery/atmospherics/considered_device in result)
if(!istype(considered_device, /obj/machinery/atmospherics/pipe))
considered_device.set_pipenet(src, borderline)
add_machinery_member(considered_device)
continue
var/obj/machinery/atmospherics/pipe/item = considered_device
if(members.Find(item))
continue
if(item.parent)
var/static/pipenetwarnings = 10
if(pipenetwarnings > 0)
log_mapping("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) around [AREACOORD(item)].")
pipenetwarnings--
if(pipenetwarnings == 0)
log_mapping("build_pipeline(): further messages about pipenets will be suppressed")
members += item
possible_expansions += item
volume += item.volume
item.parent = src
if(item.air_temporary)
air.merge(item.air_temporary)
item.air_temporary = null
possible_expansions -= borderline
air.set_volume(volume)
/**
* For a machine to properly "connect" to a pipeline and share gases,
* the pipeline needs to acknowledge a gas mixture as it's member.
* This is currently handled by the other_airs list in the pipeline datum.
*
* Other_airs itself is populated by gas mixtures through the parents list that each machineries have.
* This parents list is populated when a machinery calls update_parents and is then added into the queue by the controller.
*/
/datum/pipeline/proc/add_machinery_member(obj/machinery/atmospherics/components/considered_component)
other_atmos_machines |= considered_component
var/list/returned_airs = considered_component.return_pipenet_airs(src)
if (!length(returned_airs) || (null in returned_airs))
stack_trace("addMachineryMember: Nonexistent (empty list) or null machinery gasmix added to pipeline datum from [considered_component] \
which is of type [considered_component.type]. Nearby: ([considered_component.x], [considered_component.y], [considered_component.z])")
other_airs |= returned_airs
/datum/pipeline/proc/add_member(obj/machinery/atmospherics/reference_device, obj/machinery/atmospherics/device_to_add)
if(!istype(reference_device, /obj/machinery/atmospherics/pipe))
reference_device.set_pipenet(src, device_to_add)
add_machinery_member(reference_device)
else
var/obj/machinery/atmospherics/pipe/reference_pipe = reference_device
if(reference_pipe.parent)
merge(reference_pipe.parent)
reference_pipe.parent = src
var/list/adjacent = reference_pipe.pipeline_expansion()
for(var/obj/machinery/atmospherics/pipe/adjacent_pipe in adjacent)
if(adjacent_pipe.parent == src)
continue
var/datum/pipeline/parent_pipeline = adjacent_pipe.parent
merge(parent_pipeline)
if(!members.Find(reference_pipe))
members += reference_pipe
air.set_volume(air.return_volume() + reference_pipe.volume)
/datum/pipeline/proc/merge(datum/pipeline/parent_pipeline)
if(parent_pipeline == src)
return
air.set_volume(air.return_volume() + parent_pipeline.air.return_volume())
members.Add(parent_pipeline.members)
for(var/obj/machinery/atmospherics/pipe/reference_pipe in parent_pipeline.members)
reference_pipe.parent = src
air.merge(parent_pipeline.air)
for(var/obj/machinery/atmospherics/components/reference_component in parent_pipeline.other_atmos_machines)
reference_component.replace_pipenet(parent_pipeline, src)
other_atmos_machines |= parent_pipeline.other_atmos_machines
other_airs |= parent_pipeline.other_airs
parent_pipeline.members.Cut()
parent_pipeline.other_atmos_machines.Cut()
update = TRUE
qdel(parent_pipeline)
/obj/machinery/atmospherics/proc/add_member(obj/machinery/atmospherics/considered_device)
return
/obj/machinery/atmospherics/pipe/add_member(obj/machinery/atmospherics/considered_device)
parent.add_member(considered_device, src)
/obj/machinery/atmospherics/components/add_member(obj/machinery/atmospherics/considered_device)
var/datum/pipeline/device_pipeline = return_pipenet(considered_device)
if(!device_pipeline)
CRASH("null.add_member() called by [type] on [COORD(src)]")
device_pipeline.add_member(considered_device, src)
/datum/pipeline/proc/temporarily_store_air()
//Update individual gas_mixtures by volume ratio
for(var/obj/machinery/atmospherics/pipe/member in members)
member.air_temporary = new
member.air_temporary.set_volume(member.volume)
member.air_temporary.copy_from(air)
member.air_temporary.multiply(member.volume/air.return_volume())
member.air_temporary.set_temperature(air.return_temperature())
/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity)
var/total_heat_capacity = air.heat_capacity()
var/partial_heat_capacity = total_heat_capacity*(share_volume/air.return_volume())
var/target_temperature
var/target_heat_capacity
if(isopenturf(target))
var/turf/open/modeled_location = target
target_temperature = modeled_location.GetTemperature()
target_heat_capacity = modeled_location.GetHeatCapacity()
if(modeled_location.blocks_air)
if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
var/delta_temperature = air.return_temperature() - target_temperature
var/heat = thermal_conductivity*delta_temperature* \
(partial_heat_capacity*target_heat_capacity/(partial_heat_capacity+target_heat_capacity))
air.set_temperature(air.return_temperature() - heat/total_heat_capacity)
modeled_location.TakeTemperature(heat/target_heat_capacity)
else
var/delta_temperature = 0
var/sharer_heat_capacity = 0
delta_temperature = (air.return_temperature() - target_temperature)
sharer_heat_capacity = target_heat_capacity
var/self_temperature_delta = 0
var/sharer_temperature_delta = 0
if((sharer_heat_capacity>0) && (partial_heat_capacity>0))
var/heat = thermal_conductivity*delta_temperature* \
(partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity))
self_temperature_delta = -heat/total_heat_capacity
sharer_temperature_delta = heat/sharer_heat_capacity
else
return 1
air.set_temperature(air.return_temperature() + self_temperature_delta)
modeled_location.TakeTemperature(sharer_temperature_delta)
else
if((target.heat_capacity>0) && (partial_heat_capacity>0))
var/delta_temperature = air.return_temperature() - target.return_temperature()
var/heat = thermal_conductivity*delta_temperature* \
(partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
air.set_temperature(air.return_temperature() - heat/total_heat_capacity)
update = TRUE
/datum/pipeline/proc/return_air()
. = other_airs + air
if(listclearnulls(.))
stack_trace("[src] has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().")
/datum/pipeline/proc/empty()
for(var/datum/gas_mixture/GM as anything in get_all_connected_airs())
GM?.clear()
/datum/pipeline/proc/get_all_connected_airs()
var/list/datum/gas_mixture/gas_mixture_list = list()
var/list/datum/pipeline/pipeline_list = list()
pipeline_list += src
for(var/i = 1; i <= pipeline_list.len; i++) //can't do a for-each here because we may add to the list within the loop
var/datum/pipeline/pipeline = pipeline_list[i]
if(!pipeline)
continue
gas_mixture_list += pipeline.other_airs
gas_mixture_list += pipeline.air
for(var/obj/machinery/atmospherics/components/atmos_machine in pipeline.other_atmos_machines)
if(!atmos_machine.custom_reconcilation)
continue
pipeline_list |= atmos_machine.return_pipenets_for_reconcilation(src)
gas_mixture_list |= atmos_machine.return_airs_for_reconcilation(src)
return gas_mixture_list
/datum/pipeline/proc/reconcile_air()
var/list/datum/gas_mixture/GL = get_all_connected_airs()
equalize_all_gases_in_list(GL)