1use super::*;
4
5#[derive(Debug, Clone)]
10pub struct ComponentDescription {
11 pub bucket: u32,
14 pub descriptions: Vec<Option<String>>,
17}
18
19pub fn component_description(data: &[u8]) -> Result<ComponentDescription> {
21 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
22 if h.type_id != type_id("ComponentDescription") {
23 return format_err(format!(
24 "expected ComponentDescription, found {:#010x}",
25 h.type_id
26 ));
27 }
28 r.block(|r, _| {
29 let bucket = r.u32()?;
30 let descriptions = (0..r.count()?)
31 .map(|_| r.external_ref())
32 .collect::<Result<_>>()?;
33 Ok(ComponentDescription {
34 bucket,
35 descriptions,
36 })
37 })
38 })?;
39 Ok(value)
40}
41
42#[derive(Debug, Clone)]
44pub struct ModelVariant {
45 pub animations: Option<String>,
47 pub meshes: Vec<Option<String>>,
49}
50
51#[derive(Debug, Clone)]
55pub struct ModelDescription {
56 pub variants: Vec<ModelVariant>,
59 pub variant: i32,
62 pub mesh: i32,
65 pub random_variant: bool,
68}
69
70pub fn model_description(data: &[u8]) -> Result<ModelDescription> {
72 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
73 if h.type_id != type_id("ModelDescription") {
74 return format_err(format!(
75 "expected ModelDescription, found {:#010x}",
76 h.type_id
77 ));
78 }
79 r.block(|r, _| {
80 let mut variants = Vec::new();
81 for _ in 0..r.count()? {
82 let animations = r.external_ref()?;
83 let meshes = (0..r.count()?)
84 .map(|_| r.external_ref())
85 .collect::<Result<_>>()?;
86 variants.push(ModelVariant { animations, meshes });
87 }
88 Ok(ModelDescription {
89 variants,
90 variant: r.i32()?,
91 mesh: r.i32()?,
92 random_variant: r.bool()?,
93 })
94 })
95 })?;
96 Ok(value)
97}
98
99#[derive(Debug, Clone, PartialEq)]
104pub struct DecalDescription {
105 pub alpha: f32,
108 pub materials: Vec<Option<String>>,
111 pub scale: f32,
114 pub rects: Vec<[f32; 4]>,
117 pub tiled: bool,
120 pub flag: bool,
123}
124
125pub fn decal_description(data: &[u8]) -> Result<DecalDescription> {
127 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
128 if h.type_id != type_id("DecalDescription") {
129 return format_err(format!(
130 "expected DecalDescription, found {:#010x}",
131 h.type_id
132 ));
133 }
134 r.block(|r, _| {
135 let alpha = r.f32()?;
136 let materials = (0..r.count()?)
137 .map(|_| r.external_ref())
138 .collect::<Result<_>>()?;
139 let scale = r.f32()?;
140 let rects = (0..r.count()?)
141 .map(|_| r.f32s::<4>())
142 .collect::<Result<_>>()?;
143 Ok(DecalDescription {
144 alpha,
145 materials,
146 scale,
147 rects,
148 tiled: r.bool()?,
149 flag: r.bool()?,
150 })
151 })
152 })?;
153 Ok(value)
154}
155
156#[derive(Debug, Clone, Copy, PartialEq)]
163pub struct CharacterDescription {
164 pub radius: f32,
167 pub yaw_offset: f32,
170 pub turn_keep: f32,
173 pub blend: f32,
176 pub follow_speed: f32,
179 pub road_speed: f32,
182 pub type0_speed: f32,
185 pub fixed_height: bool,
188 pub height: f32,
190 pub min_height: f32,
193}
194
195pub fn character_description(data: &[u8]) -> Result<CharacterDescription> {
197 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
198 if h.type_id != type_id("CharacterDescription") {
199 return format_err(format!(
200 "expected CharacterDescription, found {:#010x}",
201 h.type_id
202 ));
203 }
204 r.block(|r, _| {
205 Ok(CharacterDescription {
206 radius: r.f32()?,
207 yaw_offset: r.f32()?,
208 turn_keep: r.f32()?,
209 blend: r.f32()?,
210 follow_speed: r.f32()?,
211 road_speed: r.f32()?,
212 type0_speed: r.f32()?,
213 fixed_height: r.bool()?,
214 height: r.f32()?,
215 min_height: r.f32()?,
216 })
217 })
218 })?;
219 Ok(value)
220}
221
222#[derive(Debug, Clone, PartialEq)]
224pub struct NamedPoint {
225 pub name: String,
227 pub position: [f32; 3],
229 pub yaw: f32,
231}
232
233#[derive(Debug, Clone)]
238pub struct PointList {
239 pub mesh: String,
241 pub source: String,
243 pub path_points: Vec<NamedPoint>,
245 pub points: Vec<NamedPoint>,
247}
248
249pub fn point_list(data: &[u8]) -> Result<PointList> {
251 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
252 if h.type_id != type_id("PointList") {
253 return format_err(format!("expected PointList, found {:#010x}", h.type_id));
254 }
255 r.block(|r, _| {
256 let mesh = r.string()?;
257 let source = r.string()?;
258 let list = |r: &mut Reader| -> Result<Vec<NamedPoint>> {
259 (0..r.count()?)
260 .map(|_| {
261 Ok(NamedPoint {
262 name: r.string()?,
263 position: r.f32s::<3>()?,
264 yaw: r.f32()?,
265 })
266 })
267 .collect()
268 };
269 let path_points = list(r)?;
270 let points = list(r)?;
271 Ok(PointList {
272 mesh,
273 source,
274 path_points,
275 points,
276 })
277 })
278 })?;
279 Ok(value)
280}
281
282#[derive(Debug, Clone)]
288pub struct InteractDescription {
289 pub points: Option<String>,
291}
292
293pub fn interact_description(data: &[u8]) -> Result<InteractDescription> {
295 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
296 if h.type_id != type_id("InteractDescription") {
297 return format_err(format!(
298 "expected InteractDescription, found {:#010x}",
299 h.type_id
300 ));
301 }
302 r.block(|r, _| {
303 Ok(InteractDescription {
304 points: r.external_ref()?,
305 })
306 })
307 })?;
308 Ok(value)
309}
310
311pub fn interaction_points(list: &PointList, category: usize) -> Vec<&NamedPoint> {
313 let name = ["use", "build", "create"][category];
314 list.points.iter().filter(|p| p.name == name).collect()
315}
316
317impl Default for CharacterDescription {
318 fn default() -> Self {
319 CharacterDescription {
320 radius: 0.25,
321 yaw_offset: 0.0,
322 turn_keep: 0.85,
323 blend: 0.1,
324 follow_speed: 1.0,
325 road_speed: 1.0,
326 type0_speed: 1.0,
327 fixed_height: false,
328 height: 0.0,
329 min_height: -10.0,
330 }
331 }
332}