veloren_world/site2/plot/
desert_city_temple.rs

1use super::*;
2use crate::{
3    Land,
4    util::{RandomField, Sampler},
5};
6use common::terrain::{Block, BlockKind};
7use rand::prelude::*;
8use std::sync::Arc;
9use vek::*;
10
11/// Represents house data generated by the `generate()` method
12pub struct DesertCityTemple {
13    /// Tile position of the door tile
14    pub door_tile: Vec2<i32>,
15    /// Axis aligned bounding region for the house
16    bounds: Aabr<i32>,
17    /// Approximate altitude of the door tile
18    pub(crate) alt: i32,
19}
20
21impl DesertCityTemple {
22    pub fn generate(
23        land: &Land,
24        _rng: &mut impl Rng,
25        site: &Site,
26        door_tile: Vec2<i32>,
27        door_dir: Vec2<i32>,
28        tile_aabr: Aabr<i32>,
29        alt: Option<i32>,
30    ) -> Self {
31        let door_tile_pos = site.tile_center_wpos(door_tile);
32        let bounds = Aabr {
33            min: site.tile_wpos(tile_aabr.min),
34            max: site.tile_wpos(tile_aabr.max),
35        };
36
37        Self {
38            bounds,
39            door_tile: door_tile_pos,
40            alt: alt.unwrap_or_else(|| {
41                land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32
42            }),
43        }
44    }
45}
46
47impl Structure for DesertCityTemple {
48    #[cfg(feature = "use-dyn-lib")]
49    const UPDATE_FN: &'static [u8] = b"render_desertcitytemple\0";
50
51    #[cfg_attr(
52        feature = "be-dyn-lib",
53        unsafe(export_name = "render_desertcitytemple")
54    )]
55    fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
56        let sandstone = Fill::Sampling(Arc::new(|center| {
57            Some(match (RandomField::new(0).get(center)) % 37 {
58                0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
59                9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
60                18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
61                27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
62                _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
63            })
64        }));
65        let sandstone_broken = Fill::Sampling(Arc::new(|center| {
66            Some(match (RandomField::new(0).get(center)) % 42 {
67                0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
68                9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
69                18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
70                27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
71                36..=40 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
72                _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
73            })
74        }));
75        let base = self.alt + 1;
76        let center = self.bounds.center();
77        let diameter =
78            10 + (self.bounds.max.x - self.bounds.min.x).min(self.bounds.max.y - self.bounds.min.y);
79        // Fence
80        painter
81            .aabb(Aabb {
82                min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
83                max: Vec2::new(self.bounds.min.x + 2, self.bounds.max.y).with_z(base + 2),
84            })
85            .union(painter.aabb(Aabb {
86                min: Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 1).with_z(base - 20),
87                max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
88            }))
89            .union(painter.aabb(Aabb {
90                min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
91                max: Vec2::new(self.bounds.max.x, self.bounds.min.y + 2).with_z(base + 2),
92            }))
93            .union(painter.aabb(Aabb {
94                min: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y - 1).with_z(base - 20),
95                max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
96            }))
97            .fill(sandstone_broken);
98        painter
99            .aabb(Aabb {
100                min: Vec2::new(self.bounds.min.x + 1, center.y - 8).with_z(base),
101                max: Vec2::new(self.bounds.max.x, center.y + 8).with_z(base + 7),
102            })
103            .clear();
104        painter
105            .aabb(Aabb {
106                min: Vec2::new(center.x - 7, self.bounds.min.y + 1).with_z(base),
107                max: Vec2::new(center.x + 9, self.bounds.max.y).with_z(base + 7),
108            })
109            .clear();
110        // Foundation
111        painter
112            .aabb(Aabb {
113                min: (self.bounds.min + 1).with_z(base - 20),
114                max: (self.bounds.max).with_z(base),
115            })
116            .fill(sandstone.clone());
117
118        // Temple
119        let temple_color = match (RandomField::new(0).get((center - 3).with_z(base))) % 2 {
120            0 => Fill::Brick(BlockKind::Rock, Rgb::new(100, 101, 250), 3),
121            _ => Fill::Brick(BlockKind::Rock, Rgb::new(63, 49, 63), 24),
122        };
123        let temple_size = diameter / 3;
124        let floaty_block = Fill::Brick(BlockKind::GlowingWeakRock, Rgb::new(253, 240, 149), 2);
125        let temple = Aabb {
126            min: (center - temple_size).with_z(base),
127            max: (center + temple_size - 1).with_z(base + temple_size + 1),
128        };
129
130        // temple with roof carve out
131        painter.aabb(temple).fill(sandstone.clone());
132        // roof decoration
133        painter
134            .aabb(Aabb {
135                min: (center - temple_size - 1).with_z(base + temple_size + 1),
136                max: (center + temple_size).with_z(base + temple_size + 4),
137            })
138            .fill(sandstone.clone());
139        painter
140            .aabb(Aabb {
141                min: (center - temple_size).with_z(base + temple_size + 2),
142                max: (center + temple_size - 1).with_z(base + temple_size + 4),
143            })
144            .clear();
145        painter
146            .aabb(Aabb {
147                min: Vec2::new(center.x - temple_size - 1, center.y - (temple_size / 4) - 2)
148                    .with_z(base + temple_size + 3),
149                max: Vec2::new(center.x + temple_size, center.y + (temple_size / 4) + 1)
150                    .with_z(base + temple_size + 4),
151            })
152            .clear();
153        painter
154            .aabb(Aabb {
155                min: Vec2::new(center.x - (temple_size / 4) - 2, center.y - temple_size - 1)
156                    .with_z(base + temple_size + 3),
157                max: Vec2::new(center.x + (temple_size / 4) + 1, center.y + temple_size)
158                    .with_z(base + temple_size + 4),
159            })
160            .clear();
161
162        // roof carve out
163        painter
164            .aabb(Aabb {
165                min: (center - temple_size + 1).with_z(base + temple_size),
166                max: (center + temple_size - 2).with_z(base + temple_size + 3),
167            })
168            .clear();
169        //corner pillars
170        for dir in SQUARE_4 {
171            let corner_pos = center - temple_size;
172            let pillar_center = corner_pos + (dir * ((2 * temple_size) - 1));
173            // Pillar foot
174            painter
175                .aabb(Aabb {
176                    min: (pillar_center - 4).with_z(base),
177                    max: (pillar_center + 4).with_z(base + 4),
178                })
179                .fill(sandstone.clone());
180
181            // Pillar
182            painter
183                .aabb(Aabb {
184                    min: (pillar_center - 3).with_z(base + 4),
185                    max: (pillar_center + 3).with_z(base + temple_size + 3),
186                })
187                .fill(sandstone.clone());
188            // Pillar Top
189            painter
190                .aabb(Aabb {
191                    min: (pillar_center - 4).with_z(base + temple_size + 3),
192                    max: (pillar_center + 4).with_z(base + temple_size + 6),
193                })
194                .fill(sandstone.clone());
195
196            painter
197                .aabb(Aabb {
198                    min: (pillar_center - 3).with_z(base + temple_size + 4),
199                    max: (pillar_center + 3).with_z(base + temple_size + 6),
200                })
201                .clear();
202
203            // clear parts of pillar top for roof carve out
204            painter
205                .aabb(Aabb {
206                    min: (center - temple_size).with_z(base + temple_size + 3),
207                    max: (center + temple_size - 1).with_z(base + temple_size + 6),
208                })
209                .clear()
210        }
211
212        // temple decor carve out
213        // apply three carve options (horizontal, vertical, none) with two spread
214        // options (for horizontal and vertical)
215        for s in 0..2 {
216            // decor carve out style
217            let spread_select = ((RandomField::new(0).get((center - 1).with_z(base))) % 2) as i32;
218            let spread = 3 * spread_select;
219            let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
220            match carve_style {
221                //vertical
222                0 => {
223                    // decor carve outs1
224                    for c in 0..(temple_size - 5) {
225                        painter
226                            .aabb(Aabb {
227                                min: Vec2::new(
228                                    center.x - temple_size + 5 + (2 * c),
229                                    center.y - temple_size,
230                                )
231                                .with_z(base + 2),
232                                max: Vec2::new(
233                                    center.x - temple_size + 6 + (2 * c),
234                                    center.y + temple_size - 1,
235                                )
236                                .with_z(base + temple_size - 1),
237                            })
238                            .clear();
239                    }
240                    for c in 0..(temple_size - 5) {
241                        painter
242                            .aabb(Aabb {
243                                min: Vec2::new(
244                                    center.x - temple_size,
245                                    center.y - temple_size + 5 + (2 * c),
246                                )
247                                .with_z(base + 2),
248                                max: Vec2::new(
249                                    center.x + temple_size - 1,
250                                    center.y - temple_size + 6 + (2 * c),
251                                )
252                                .with_z(base + temple_size - 1),
253                            })
254                            .clear();
255                    }
256                },
257                1 => {
258                    // horizontal
259                    for c in 0..((temple_size / 2) - 2) {
260                        painter
261                            .aabb(Aabb {
262                                min: Vec2::new(center.x - temple_size + 5, center.y - temple_size)
263                                    .with_z(base + 2 + ((spread + 2) * c)),
264                                max: Vec2::new(
265                                    center.x + temple_size - 6,
266                                    center.y + temple_size - 1,
267                                )
268                                .with_z(base + 3 + ((spread + 2) * c) + spread_select),
269                            })
270                            .clear();
271                    }
272                    for c in 0..((temple_size / 2) - 2) {
273                        painter
274                            .aabb(Aabb {
275                                min: Vec2::new(center.x - temple_size, center.y - temple_size + 5)
276                                    .with_z(base + 2 + ((spread + 2) * c)),
277                                max: Vec2::new(
278                                    center.x + temple_size - 1,
279                                    center.y + temple_size - 6,
280                                )
281                                .with_z(base + 3 + ((spread + 2) * c) + spread_select),
282                            })
283                            .clear();
284                    }
285                },
286                _ => {},
287            }
288        }
289        // color inlays1
290        painter
291            .aabb(Aabb {
292                min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
293                    .with_z(base + 2),
294                max: Vec2::new(center.x + temple_size - 3, center.y - temple_size + 3)
295                    .with_z(base + temple_size - 1),
296            })
297            .fill(temple_color.clone());
298
299        painter
300            .aabb(Aabb {
301                min: Vec2::new(center.x - temple_size + 2, center.y + temple_size - 4)
302                    .with_z(base + 2),
303                max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
304                    .with_z(base + temple_size - 1),
305            })
306            .fill(temple_color.clone());
307        // color inlays2
308        painter
309            .aabb(Aabb {
310                min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
311                    .with_z(base + 2),
312                max: Vec2::new(center.x - temple_size + 3, center.y + temple_size - 3)
313                    .with_z(base + temple_size - 1),
314            })
315            .fill(temple_color.clone());
316        painter
317            .aabb(Aabb {
318                min: Vec2::new(center.x + temple_size - 4, center.y - temple_size + 2)
319                    .with_z(base + 2),
320                max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
321                    .with_z(base + temple_size - 1),
322            })
323            .fill(temple_color.clone());
324        // carve outside plane1
325        painter
326            .aabb(Aabb {
327                min: Vec2::new(center.x - temple_size + 6, center.y - temple_size).with_z(base + 3),
328                max: Vec2::new(center.x + temple_size - 7, center.y - temple_size + 1)
329                    .with_z(base + temple_size - 2),
330            })
331            .clear();
332        painter
333            .aabb(Aabb {
334                min: Vec2::new(center.x - temple_size + 6, center.y + temple_size - 2)
335                    .with_z(base + 3),
336                max: Vec2::new(center.x + temple_size - 7, center.y + temple_size - 1)
337                    .with_z(base + temple_size - 2),
338            })
339            .clear();
340        // carve outside plane2
341        painter
342            .aabb(Aabb {
343                min: Vec2::new(center.x - temple_size, center.y - temple_size + 6).with_z(base + 3),
344                max: Vec2::new(center.x - temple_size + 1, center.y + temple_size - 7)
345                    .with_z(base + temple_size - 2),
346            })
347            .clear();
348        painter
349            .aabb(Aabb {
350                min: Vec2::new(center.x + temple_size - 2, center.y - temple_size + 6)
351                    .with_z(base + 3),
352                max: Vec2::new(center.x + temple_size - 1, center.y + temple_size - 7)
353                    .with_z(base + temple_size - 2),
354            })
355            .clear();
356        // Temple Top Socket
357        painter
358            .cylinder(Aabb {
359                min: (center - temple_size + 3).with_z(base + temple_size),
360                max: (center + temple_size - 4).with_z(base + temple_size + 1),
361            })
362            .fill(sandstone.clone());
363        // Temple Top
364        let top = painter.sphere(Aabb {
365            min: (center - temple_size + 3).with_z(base),
366            max: (center + temple_size - 4).with_z(base + (2 * temple_size) - 7),
367        });
368        top.fill(sandstone.clone());
369
370        // temple top decoration
371        // apply two decoration options (horizontal, vertical, none) with two spread
372        // options for hor/ver options
373        for s in 0..2 {
374            // decor carve out style
375            let spread_select =
376                ((RandomField::new(0).get((center - 1 - s).with_z(base))) % 2) as i32;
377            let spread = 3 * spread_select;
378            let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
379            match carve_style {
380                //vertical
381                0 => {
382                    // decor carve outs1
383                    for c in 0..(temple_size - 2) {
384                        painter
385                            .aabb(Aabb {
386                                min: Vec2::new(
387                                    center.x - temple_size + 2 + ((spread + 2) * c),
388                                    center.y - temple_size,
389                                )
390                                .with_z(base + temple_size),
391                                max: Vec2::new(
392                                    center.x - temple_size + 3 + ((spread + 2) * c) + spread_select,
393                                    center.y + temple_size - 1,
394                                )
395                                .with_z(base + (2 * temple_size)),
396                            })
397                            .intersect(top)
398                            .fill(temple_color.clone());
399                    }
400                },
401                1 => {
402                    for c in 0..(temple_size - 2) {
403                        painter
404                            .aabb(Aabb {
405                                min: Vec2::new(
406                                    center.x - temple_size,
407                                    center.y - temple_size + 2 + ((spread + 2) * c),
408                                )
409                                .with_z(base + temple_size),
410                                max: Vec2::new(
411                                    center.x + temple_size - 1,
412                                    center.y - temple_size + 3 + ((spread + 2) * c) + spread_select,
413                                )
414                                .with_z(base + (2 * temple_size)),
415                            })
416                            .intersect(top)
417                            .fill(temple_color.clone());
418                    }
419                },
420                _ => {},
421            }
422        }
423        // Temple Top Socket
424        painter
425            .cylinder(Aabb {
426                min: (center - temple_size + 3).with_z(base + temple_size),
427                max: (center + temple_size - 4).with_z(base + temple_size + 1),
428            })
429            .fill(sandstone.clone());
430        // clear top
431        painter
432            .sphere(Aabb {
433                min: (center - temple_size + 4).with_z(base + 1),
434                max: (center + temple_size - 5).with_z(base + (2 * temple_size) - 8),
435            })
436            .clear();
437
438        // round or rectangle entries
439        let entry_select = ((RandomField::new(0).get((center + 1).with_z(base))) % 2) as i32;
440        match entry_select {
441            0 => {
442                //round Temple entries1
443                painter
444                    .aabb(Aabb {
445                        min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
446                        max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 4),
447                    })
448                    .fill(sandstone.clone());
449                painter
450                    .aabb(Aabb {
451                        min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base),
452                        max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 4),
453                    })
454                    .clear();
455
456                painter
457                    .aabb(Aabb {
458                        min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base + 4),
459                        max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 7),
460                    })
461                    .fill(sandstone.clone());
462                painter
463                    .aabb(Aabb {
464                        min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 4),
465                        max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 7),
466                    })
467                    .clear();
468
469                painter
470                    .aabb(Aabb {
471                        min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 7),
472                        max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 9),
473                    })
474                    .fill(sandstone.clone());
475                painter
476                    .aabb(Aabb {
477                        min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 7),
478                        max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 9),
479                    })
480                    .clear();
481
482                painter
483                    .aabb(Aabb {
484                        min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 9),
485                        max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 10),
486                    })
487                    .fill(sandstone.clone());
488
489                // round Temple entries2
490                painter
491                    .aabb(Aabb {
492                        min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
493                        max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 4),
494                    })
495                    .fill(sandstone.clone());
496                painter
497                    .aabb(Aabb {
498                        min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base),
499                        max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 4),
500                    })
501                    .clear();
502
503                painter
504                    .aabb(Aabb {
505                        min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base + 4),
506                        max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 7),
507                    })
508                    .fill(sandstone.clone());
509                painter
510                    .aabb(Aabb {
511                        min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 4),
512                        max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 7),
513                    })
514                    .clear();
515
516                painter
517                    .aabb(Aabb {
518                        min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 7),
519                        max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 9),
520                    })
521                    .fill(sandstone.clone());
522                painter
523                    .aabb(Aabb {
524                        min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 7),
525                        max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 9),
526                    })
527                    .clear();
528
529                painter
530                    .aabb(Aabb {
531                        min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 9),
532                        max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 10),
533                    })
534                    .fill(sandstone.clone());
535            },
536            _ => {
537                //rectangle Temple entries1
538                painter
539                    .aabb(Aabb {
540                        min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
541                        max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 8),
542                    })
543                    .fill(sandstone.clone());
544                painter
545                    .aabb(Aabb {
546                        min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base),
547                        max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 6),
548                    })
549                    .clear();
550
551                //rectangle Temple entries1
552                painter
553                    .aabb(Aabb {
554                        min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
555                        max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 8),
556                    })
557                    .fill(sandstone.clone());
558                painter
559                    .aabb(Aabb {
560                        min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base),
561                        max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 6),
562                    })
563                    .clear();
564            },
565        }
566
567        // carve temple
568        painter
569            .aabb(Aabb {
570                min: (center - temple_size + 4).with_z(base),
571                max: (center + temple_size - 5).with_z(base + temple_size - 1),
572            })
573            .clear();
574
575        // floating sculpture, placeholder for sun god
576
577        painter
578            .sphere(Aabb {
579                min: (center - 3).with_z(base),
580                max: (center + 2).with_z(base + 5),
581            })
582            .fill(sandstone.clone());
583        painter
584            .sphere(Aabb {
585                min: (center - 3).with_z(base + 4),
586                max: (center + 2).with_z(base + 9),
587            })
588            .fill(sandstone.clone());
589        painter
590            .sphere(Aabb {
591                min: (center - 3).with_z(base + 8),
592                max: (center + 2).with_z(base + 13),
593            })
594            .fill(sandstone.clone());
595        painter
596            .sphere(Aabb {
597                min: (center - 4).with_z(base + 14),
598                max: (center + 3).with_z(base + 15),
599            })
600            .fill(sandstone.clone());
601        painter
602            .sphere(Aabb {
603                min: (center - 3).with_z(base + 16),
604                max: (center + 2).with_z(base + 21),
605            })
606            .fill(floaty_block.clone());
607
608        // floating sculptures
609        for dir in SQUARE_4 {
610            let corner_pos = center - temple_size / 2;
611            let sclpt_center = corner_pos + (dir * (temple_size));
612
613            painter
614                .sphere(Aabb {
615                    min: (sclpt_center - 2).with_z(base),
616                    max: (sclpt_center + 1).with_z(base + 3),
617                })
618                .fill(sandstone.clone());
619            painter
620                .sphere(Aabb {
621                    min: (sclpt_center - 2).with_z(base + 2),
622                    max: (sclpt_center + 1).with_z(base + 5),
623                })
624                .fill(sandstone.clone());
625            painter
626                .sphere(Aabb {
627                    min: (sclpt_center - 3).with_z(base + 5),
628                    max: (sclpt_center + 2).with_z(base + 6),
629                })
630                .fill(sandstone.clone());
631            painter
632                .sphere(Aabb {
633                    min: (sclpt_center - 3).with_z(base + 7),
634                    max: (sclpt_center + 2).with_z(base + 8),
635                })
636                .fill(sandstone.clone());
637            painter
638                .sphere(Aabb {
639                    min: (sclpt_center - 2).with_z(base + 9),
640                    max: (sclpt_center + 1).with_z(base + 12),
641                })
642                .fill(floaty_block.clone());
643        }
644    }
645}