1use super::*;
4
5impl Callbacks for Sim<'_, '_> {
6 fn machine(&mut self, site: usize) -> &mut Machine {
7 &mut self.sites.get_mut(&site).unwrap().machine
8 }
9
10 fn call(&mut self, jobs: &mut Jobs, e: usize, f: Callback) -> bool {
11 match f {
12 Callback::None | Callback::Missing => false,
13 Callback::ClearEnter0 => {
14 let instant = self
17 .sites
18 .get(&e)
19 .and_then(|s| self.site_templates[s.template].clear.as_ref())
20 .is_some_and(|d| d.instant);
21 if instant {
22 self.clear_instantly(jobs, e);
23 }
24 if self.is_clear(e) {
25 self.machine(e).request(1);
26 } else {
27 self.register_clear(jobs, e);
28 }
29 true
30 }
31 Callback::ClearUpdate0 => {
32 if self.is_clear(e) {
33 self.machine(e).request(1);
34 }
35 false
36 }
37 Callback::ClearExit0 => {
38 if self.sites[&e].work_id >= 0 && jobs.works.contains_key(&self.sites[&e].work_id) {
40 self.remove_work(jobs, e);
41 }
42 true
43 }
44 Callback::ClearExit15 => {
46 let id = self.sites[&e].work_id;
47 if id >= 0 && jobs.works.contains_key(&id) {
48 self.remove_work(jobs, e);
49 }
50 true
51 }
52 Callback::OrchardEnter2 => {
53 self.orchard_enter2(e);
54 false
55 }
56 Callback::OrchardUpdate2 => {
57 self.orchard_update2(e);
58 true
59 }
60 Callback::OrchardEnter9 => {
61 self.orchard_enter9(jobs, e);
62 true
63 }
64 Callback::OrchardUpdate9 => {
65 self.orchard_update9(jobs, e);
66 true
67 }
68 Callback::OrchardEnter10 => {
69 self.orchard_enter10(jobs, e);
70 true
71 }
72 Callback::OrchardUpdate10 => {
73 self.orchard_update10(jobs, e);
74 true
75 }
76 Callback::OrchardExitWork => {
77 self.orchard_exit_work(jobs, e);
78 true
79 }
80 Callback::OrchardEnter12 => {
81 self.orchard_enter12(jobs, e);
82 true
83 }
84 Callback::OrchardUpdate12 => {
85 self.orchard_update12(e);
86 true
87 }
88 Callback::OrchardEnter11 => {
89 self.orchard_enter11(jobs, e);
90 true
91 }
92 Callback::OrchardUpdate11 => {
93 self.orchard_update11(jobs, e);
94 true
95 }
96 Callback::OrchardEnter14 => {
97 self.orchard_enter14(jobs, e);
98 true
99 }
100 Callback::OrchardExit14 => {
101 self.orchard_exit14(jobs, e);
102 true
103 }
104 Callback::OrchardUpdate14 => {
105 self.orchard_update14(e);
106 true
107 }
108 Callback::CropEnter2 => {
109 self.crop_enter2(e);
110 false
111 }
112 Callback::CropUpdate2 => {
113 self.crop_update2(e);
114 true
115 }
116 Callback::CropEnter9 => {
117 self.crop_enter9(jobs, e);
118 true
119 }
120 Callback::CropUpdate9 => {
121 self.crop_update9(jobs, e);
122 true
123 }
124 Callback::CropEnter10 => {
125 self.crop_enter10(jobs, e);
126 true
127 }
128 Callback::CropExit10 => {
129 self.crop_exit10(jobs, e);
130 true
131 }
132 Callback::CropUpdate10 => {
133 self.crop_update10(e);
134 true
135 }
136 Callback::CropEnter11 => {
137 self.crop_enter11(jobs, e);
138 true
139 }
140 Callback::CropUpdate11 => {
141 self.crop_update11(jobs, e);
142 true
143 }
144 Callback::ClearEnter1 => {
145 self.clear_area_stamp(e);
147 self.machine(e).request(2);
148 true
149 }
150 Callback::ClearEnter2 => {
151 self.stamp(e);
154 self.decal_opaque(e);
155 for part in self.sites[&e].parts.clone() {
156 self.stamp(part);
157 self.decal_opaque(part);
158 }
159 true
160 }
161 Callback::AbsorbUpdate0 => {
162 self.absorb_piles(jobs, e);
163 true
164 }
165 Callback::MarketEnter2 => {
167 self.storage_changes.push((e, true));
168 false
169 }
170 Callback::MarketEnter3 => {
171 self.storage_changes.push((e, false));
172 false
173 }
174 Callback::CemeteryEnter2 => {
175 self.cemetery_enter2(e);
176 false
177 }
178 Callback::CemeteryEnter3 => {
179 self.cemeteries.retain(|&c| c != e);
180 false
181 }
182 Callback::StorageEnter2 => {
183 self.storage_changes.push((e, true));
184 false
185 }
186 Callback::StorageEnter3 => {
187 self.storage_changes.push((e, false));
188 false
189 }
190 Callback::PastureEnter2 => {
191 self.pasture_enter2(e);
192 false
193 }
194 Callback::PastureUpdate2 => {
195 self.pasture_update2(jobs, e);
196 true
197 }
198 Callback::PastureEnter3 => {
199 self.pasture_leave(e);
200 false
201 }
202 Callback::WorkPlaceEnter0 => {
203 self.become_site(jobs, e);
204 false
205 }
206 Callback::WorkPlaceEnter2 => {
207 self.become_building(jobs, e);
208 false
209 }
210 Callback::WorkPlaceEnter3 => {
212 self.refresh_demolishing();
213 let mut workers = self.workers();
214 self.workforce.clear_workers(&mut workers, e);
215 self.set_workers(&workers);
216 if let Some(p) = self.workforce.workplaces.get(&e).and_then(|w| w.profession) {
217 self.workforce.unregister(e, p);
218 }
219 false
220 }
221 Callback::BuildEnter1 => {
222 let site = self.sites.get_mut(&e).unwrap();
225 site.stages = site.multi_stages.unwrap_or(1);
226 self.clear_area_stamp(e);
227 if !self.site_list.contains(&e) {
228 self.site_list.push(e);
229 }
230 if !self.has_materials(e) {
231 let site = &self.sites[&e];
232 let t = &self.site_templates[site.template];
233 let stored: Vec<i32> = t
234 .materials
235 .iter()
236 .map(|&(_, m)| self.storages[site.storage].available(m))
237 .collect();
238 let gather = Gather {
239 transit: vec![0; stored.len()],
240 stored,
241 workers: Default::default(),
242 };
243 let work = Work::new(
244 e,
245 self.rect_cell(e),
246 self.professions.laborer,
247 WorkKind::Gather(gather),
248 );
249 self.set_work(jobs, e, work, CONSTRUCTION_MASK, true);
250 let site = &self.sites[&e];
251 let t = &self.site_templates[site.template];
252 let (mut capacity, mut accepts) = (0i32, 0u32);
253 for &(n, m) in &t.materials {
254 accepts |= self.materials[m].flags;
255 capacity += n * self.materials[m].size * site.stages;
256 }
257 let s = &mut self.storages[site.storage];
258 s.items.clear();
259 s.capacity = capacity;
260 s.accepts = accepts;
261 } else {
262 self.machine(e).request(8);
263 }
264 true
265 }
266 Callback::BuildUpdate1 => {
267 if self.has_materials(e) {
268 self.remove_work(jobs, e);
269 self.machine(e).request(8);
270 }
271 true
272 }
273 Callback::BuildEnter8 => {
274 self.decal_opaque(e);
275 self.set_mesh(e, 0);
276 let work = Work::new(
277 e,
278 self.rect_cell(e),
279 self.professions.builder,
280 WorkKind::Build(BuildWork {
281 occupied: vec![false; self.build_point_count(e)],
282 ..Default::default()
283 }),
284 );
285 self.set_work(jobs, e, work, CONSTRUCTION_MASK, true);
286 true
287 }
288 Callback::BuildUpdate8 => {
289 let site = &self.sites[&e];
290 let total = self.site_templates[site.template].work * site.stages;
291 let meshes = self.meshes(e);
292 if site.progress < total {
293 let mut m = ((site.progress as f32 / total as f32) * meshes as f32) as i32;
294 if m == meshes - 1 {
295 m = meshes - 2;
296 }
297 self.set_mesh(e, m);
298 } else {
299 self.remove_work(jobs, e);
300 self.set_mesh(e, meshes - 1);
301 self.machine(e).request(2);
302 }
303 true
304 }
305 Callback::BuildExit8 => {
306 self.site_list.retain(|&s| s != e);
307 self.set_icon(e, crate::work::professions::icon::BUILD_PAUSED, false);
309 if self.wildlife.pastures.contains_key(&e) {
313 self.pasture_built(e);
314 }
315 let parts = self.sites[&e].parts.clone();
316 for x in std::iter::once(e).chain(parts) {
317 if self.templates[self.placed[x].template].terraform.is_some() {
318 self.terraform_requests
319 .push(crate::world::terraform::Terraform::Dig(x));
320 }
321 }
322 if let Some(q) = &self.templates[self.placed[e].template].quarry {
324 self.terraform_requests
325 .push(crate::world::terraform::Terraform::Quarry {
326 entity: e,
327 floor: q.shallow,
328 claim: false,
329 });
330 }
331 true
332 }
333 Callback::BuildFinish => {
334 self.finish_storage(e);
335 self.sites.get_mut(&e).unwrap().complete = true;
336 false
337 }
338 Callback::ResidenceEnter2 => {
339 self.workforce.residences.push(e);
342 let site = self.sites.get_mut(&e).unwrap();
343 let kept = site.home.take();
344 let storage = site.storage;
345 if let Some(desc) = self.site_templates[site.template].residence {
346 let home =
347 kept.unwrap_or_else(|| crate::people::life::Home::new(desc, storage));
348 self.homes.entry(e).or_insert(home);
349 }
350 false
351 }
352 Callback::ResidenceEnter3 => {
353 self.residence_leave(e);
354 false
355 }
356 Callback::DestroyEnter3 => {
357 self.destroy_enter3(jobs, e);
358 false
359 }
360 Callback::DestroyEnter4 => {
361 self.destroy_enter4(jobs, e);
362 false
363 }
364 Callback::DestroyUpdate4 => {
365 self.destroy_update4(jobs, e);
366 true
367 }
368 Callback::DestroyEnter5 => {
369 self.destroy_enter5(jobs, e);
370 true
371 }
372 Callback::DestroyUpdate5 => {
373 self.destroy_update5(jobs, e);
374 true
375 }
376 Callback::DestroyEnter6 => {
377 self.destroy_enter6(e);
378 false
379 }
380 Callback::DestroyUpdate6 => {
381 self.destroy_update6(e, self.site_dt);
382 true
383 }
384 Callback::DestroyExit6 => {
385 self.destroy_exit6(e);
386 true
387 }
388 Callback::ImmigrationEnter2 => {
389 self.immigration_idle(e);
390 false
391 }
392 Callback::ImmigrationUpdate2 => {
393 self.immigration_idle(e);
394 true
395 }
396 Callback::ImmigrationEnterF => {
397 self.immigration_wait(e);
398 false
399 }
400 Callback::ImmigrationUpdateF => {
401 self.immigration_waiting(e, self.site_dt);
402 true
403 }
404 Callback::ImmigrationEnter10 => {
405 self.immigration_call(e, true);
406 true
407 }
408 Callback::ImmigrationUpdate10 => {
409 self.immigration_call(e, false);
410 true
411 }
412 Callback::ImmigrationEnter11 => {
413 self.band_arrived(e);
414 true
415 }
416 Callback::ImmigrationUpdate11 => {
417 self.band_waiting(e);
418 true
419 }
420 Callback::ImmigrationLeave => {
421 self.send_band_away(e);
422 true
423 }
424 Callback::TradeEnter2 => {
425 self.trade_enter2(jobs, e);
426 false
427 }
428 Callback::TradeUpdate2 => {
429 self.trade_update2(e, self.site_dt);
430 false
431 }
432 Callback::TradeEnter12 => true,
433 Callback::TradeEnter13 => {
434 self.trade_enter13(e);
435 true
436 }
437 Callback::TradeExit13 => {
438 self.trade_exit13(e);
439 true
440 }
441 Callback::TradeUpdate13 => {
442 self.trade_update13(e, self.site_dt);
443 true
444 }
445 Callback::TradeLeave => {
446 self.trade_leave(e);
447 true
448 }
449 Callback::MultiObjectEnter2 => {
450 let size = self.size;
455 for part in self.sites[&e].parts.clone() {
456 let p = &self.placed[part];
457 if let Some(mesh) = self.templates[p.template].floor.clone() {
458 let floor = crate::world::floor::Floor::placed(&mesh, p);
459 self.cells.floors.add(size, part, floor);
460 }
461 }
462 false
463 }
464 Callback::WellEnter2 => {
465 self.well_join(e, true);
466 false
467 }
468 Callback::WellEnter3 => {
469 self.well_join(e, false);
470 false
471 }
472 Callback::AttendanceEnter2 => {
473 self.attendance_enter(jobs, e);
474 false
475 }
476 Callback::AttendanceExit2 => {
477 let full = self.attendance_full(e);
479 self.set_icon(e, crate::work::professions::icon::LIMIT, full);
480 false
481 }
482 Callback::AttendanceEnter3 => {
483 self.remove_work(jobs, e);
484 self.attendance_leave(e);
485 false
486 }
487 Callback::HealerEnter2 => {
488 if !self.healers.contains(&e) {
489 self.healers.push(e);
490 }
491 false
492 }
493 Callback::HappinessEnter => {
494 self.happiness_enter(e);
495 false
496 }
497 Callback::HappinessUpdate => {
498 self.happiness_update(e);
499 false
500 }
501 Callback::HappinessLeave => {
502 self.happiness_leave(e);
503 false
504 }
505 Callback::HealerEnter3 => {
506 self.healers.retain(|&x| x != e);
507 false
508 }
509 Callback::ProduceEnter2 => {
510 let off = self.sites[&e].produce.as_ref().is_some_and(|p| p.disabled);
511 self.machine(e).request(if off { 0xe } else { 0xd });
512 false
513 }
514 Callback::ProduceClearPoints => {
515 self.produce_clear_points(e);
516 false
517 }
518 Callback::ProduceEnterD => {
519 if self.sites[&e].produce.as_ref().is_some_and(|p| p.disabled) {
520 self.machine(e).request(0xe);
521 return true;
522 }
523 let t = &self.site_templates[self.sites[&e].template];
526 let work = if t.herbalist.is_some() {
527 self.herbalist_work(e)
528 } else if t.forester.is_some() {
529 self.forester_work(e)
530 } else if t.fishing.is_some() {
531 self.fishing_work(e)
532 } else if t.hunt.is_some() {
533 self.hunt_work(e)
534 } else if t.market.is_some() {
535 self.market_work(e)
536 } else {
537 self.produce_work(e)
538 };
539 self.set_work(jobs, e, work, 1, false);
540 self.enable_workplace(e, true);
541 self.fishing_register(e);
543 false
544 }
545 Callback::ProduceEnterE => {
546 let id = self.sites[&e].work_id;
548 if id >= 0 && jobs.works.contains_key(&id) {
549 self.remove_work(jobs, e);
550 }
551 self.enable_workplace(e, false);
552 self.fishing_unregister(e);
554 true
555 }
556 Callback::ProduceUpdateD => {
557 self.fishing_water(e);
559 false
560 }
561 Callback::ProduceLeaveD => {
562 self.fishing_unregister(e);
564 true
565 }
566 Callback::ClearResourceEnter2 => {
567 if let Some(site) = self.sites.get_mut(&e) {
570 site.destroyed = true;
571 }
572 true
573 }
574 }
575 }
576}