rpgmxp_types/
actor.rs

1use crate::Table;
2use ruby_marshal::FromValue;
3use ruby_marshal::FromValueContext;
4use ruby_marshal::FromValueError;
5use ruby_marshal::IntoValue;
6use ruby_marshal::IntoValueError;
7use ruby_marshal::ObjectValue;
8use ruby_marshal::StringValue;
9use ruby_marshal::SymbolValue;
10use ruby_marshal::Value;
11use ruby_marshal::ValueArena;
12use ruby_marshal::ValueHandle;
13
14const OBJECT_NAME: &[u8] = b"RPG::Actor";
15
16const INITIAL_LEVEL_FIELD: &[u8] = b"@initial_level";
17const ARMOR4_ID_FIELD: &[u8] = b"@armor4_id";
18const WEAPON_ID_FIELD: &[u8] = b"@weapon_id";
19const CHARACTER_NAME_FIELD: &[u8] = b"@character_name";
20const NAME_FIELD: &[u8] = b"@name";
21const EXP_INFLATION_FIELD: &[u8] = b"@exp_inflation";
22const PARAMETERS_FIELD: &[u8] = b"@parameters";
23const ARMOR2_FIX_FIELD: &[u8] = b"@armor2_fix";
24const CLASS_ID_FIELD: &[u8] = b"@class_id";
25const ARMOR3_ID_FIELD: &[u8] = b"@armor3_id";
26const ARMOR1_FIX_FIELD: &[u8] = b"@armor1_fix";
27const EXP_BASIS_FIELD: &[u8] = b"@exp_basis";
28const ARMOR2_ID_FIELD: &[u8] = b"@armor2_id";
29const BATTLER_HUE_FIELD: &[u8] = b"@battler_hue";
30const ARMOR4_FIX_FIELD: &[u8] = b"@armor4_fix";
31const FINAL_LEVEL_FIELD: &[u8] = b"@final_level";
32const WEAPON_FIX_FIELD: &[u8] = b"@weapon_fix";
33const ARMOR1_ID_FIELD: &[u8] = b"@armor1_id";
34const ID_FIELD: &[u8] = b"@id";
35const CHARACTER_HUE_FIELD: &[u8] = b"@character_hue";
36const BATTLER_NAME_FIELD: &[u8] = b"@battler_name";
37const ARMOR3_FIX_FIELD: &[u8] = b"@armor3_fix";
38
39#[derive(Debug, serde::Serialize, serde::Deserialize)]
40pub struct Actor {
41    pub initial_level: i32,
42    pub armor4_id: i32,
43    pub weapon_id: i32,
44    pub character_name: String,
45    pub name: String,
46    pub exp_inflation: i32,
47    pub parameters: Table,
48    pub armor2_fix: bool,
49    pub class_id: i32,
50    pub armor3_id: i32,
51    pub armor1_fix: bool,
52    pub exp_basis: i32,
53    pub armor2_id: i32,
54    pub battler_hue: i32,
55    pub armor4_fix: bool,
56    pub final_level: i32,
57    pub weapon_fix: bool,
58    pub armor1_id: i32,
59    pub id: i32,
60    pub character_hue: i32,
61    pub battler_name: String,
62    pub armor3_fix: bool,
63}
64
65impl<'a> FromValue<'a> for Actor {
66    fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
67        let object: &ObjectValue = FromValue::from_value(ctx, value)?;
68        let name = object.name();
69        let name: &SymbolValue = ctx.from_value(name.into())?;
70        let name = name.value();
71
72        if name != OBJECT_NAME {
73            return Err(FromValueError::UnexpectedObjectName { name: name.into() });
74        }
75
76        let instance_variables = object.instance_variables();
77
78        let mut initial_level_field = None;
79        let mut armor4_id_field = None;
80        let mut weapon_id_field = None;
81        let mut character_name_field = None;
82        let mut name_field = None;
83        let mut exp_inflation_field = None;
84        let mut parameters_field = None;
85        let mut armor2_fix_field = None;
86        let mut class_id_field = None;
87        let mut armor3_id_field = None;
88        let mut armor1_fix_field = None;
89        let mut exp_basis_field = None;
90        let mut armor2_id_field = None;
91        let mut battler_hue_field = None;
92        let mut armor4_fix_field = None;
93        let mut final_level_field = None;
94        let mut weapon_fix_field = None;
95        let mut armor1_id_field = None;
96        let mut id_field = None;
97        let mut character_hue_field = None;
98        let mut battler_name_field = None;
99        let mut armor3_fix_field = None;
100
101        for (key, value) in instance_variables.iter().copied() {
102            let key: &SymbolValue = ctx.from_value(key.into())?;
103            let key = key.value();
104
105            match key {
106                INITIAL_LEVEL_FIELD => {
107                    if initial_level_field.is_some() {
108                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
109                    }
110
111                    let value: i32 = ctx.from_value(value)?;
112                    initial_level_field = Some(value);
113                }
114                ARMOR4_ID_FIELD => {
115                    if armor4_id_field.is_some() {
116                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
117                    }
118                    let value: i32 = ctx.from_value(value)?;
119                    armor4_id_field = Some(value);
120                }
121                WEAPON_ID_FIELD => {
122                    if weapon_id_field.is_some() {
123                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
124                    }
125                    let value: i32 = ctx.from_value(value)?;
126                    weapon_id_field = Some(value);
127                }
128                CHARACTER_NAME_FIELD => {
129                    if character_name_field.is_some() {
130                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
131                    }
132                    let value: &StringValue = ctx.from_value(value)?;
133                    let value = std::str::from_utf8(value.value())
134                        .map_err(FromValueError::new_other)?
135                        .to_string();
136                    character_name_field = Some(value);
137                }
138                NAME_FIELD => {
139                    if name_field.is_some() {
140                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
141                    }
142                    let value: &StringValue = ctx.from_value(value)?;
143                    let value = std::str::from_utf8(value.value())
144                        .map_err(FromValueError::new_other)?
145                        .to_string();
146                    name_field = Some(value);
147                }
148                EXP_INFLATION_FIELD => {
149                    if exp_inflation_field.is_some() {
150                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
151                    }
152                    let value: i32 = ctx.from_value(value)?;
153                    exp_inflation_field = Some(value);
154                }
155                PARAMETERS_FIELD => {
156                    if parameters_field.is_some() {
157                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
158                    }
159                    let value: Table = ctx.from_value(value)?;
160                    parameters_field = Some(value);
161                }
162                ARMOR2_FIX_FIELD => {
163                    if armor2_fix_field.is_some() {
164                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
165                    }
166                    let value: bool = ctx.from_value(value)?;
167                    armor2_fix_field = Some(value);
168                }
169                CLASS_ID_FIELD => {
170                    if class_id_field.is_some() {
171                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
172                    }
173                    let value: i32 = ctx.from_value(value)?;
174                    class_id_field = Some(value);
175                }
176                ARMOR3_ID_FIELD => {
177                    if armor3_id_field.is_some() {
178                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
179                    }
180                    let value: i32 = ctx.from_value(value)?;
181                    armor3_id_field = Some(value);
182                }
183                ARMOR1_FIX_FIELD => {
184                    if armor1_fix_field.is_some() {
185                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
186                    }
187                    let value: bool = ctx.from_value(value)?;
188                    armor1_fix_field = Some(value);
189                }
190                EXP_BASIS_FIELD => {
191                    if exp_basis_field.is_some() {
192                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
193                    }
194                    let value: i32 = ctx.from_value(value)?;
195                    exp_basis_field = Some(value);
196                }
197                ARMOR2_ID_FIELD => {
198                    if armor2_id_field.is_some() {
199                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
200                    }
201                    let value: i32 = ctx.from_value(value)?;
202                    armor2_id_field = Some(value);
203                }
204                BATTLER_HUE_FIELD => {
205                    if battler_hue_field.is_some() {
206                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
207                    }
208                    let value: i32 = ctx.from_value(value)?;
209                    battler_hue_field = Some(value);
210                }
211                ARMOR4_FIX_FIELD => {
212                    if armor4_fix_field.is_some() {
213                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
214                    }
215                    let value: bool = ctx.from_value(value)?;
216                    armor4_fix_field = Some(value);
217                }
218                FINAL_LEVEL_FIELD => {
219                    if final_level_field.is_some() {
220                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
221                    }
222                    let value: i32 = ctx.from_value(value)?;
223                    final_level_field = Some(value);
224                }
225                WEAPON_FIX_FIELD => {
226                    if weapon_fix_field.is_some() {
227                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
228                    }
229                    let value: bool = ctx.from_value(value)?;
230                    weapon_fix_field = Some(value);
231                }
232                ARMOR1_ID_FIELD => {
233                    if armor1_id_field.is_some() {
234                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
235                    }
236                    let value: i32 = ctx.from_value(value)?;
237                    armor1_id_field = Some(value);
238                }
239                ID_FIELD => {
240                    if id_field.is_some() {
241                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
242                    }
243                    let value: i32 = ctx.from_value(value)?;
244                    id_field = Some(value);
245                }
246                CHARACTER_HUE_FIELD => {
247                    if character_hue_field.is_some() {
248                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
249                    }
250                    let value: i32 = ctx.from_value(value)?;
251                    character_hue_field = Some(value);
252                }
253                BATTLER_NAME_FIELD => {
254                    if battler_name_field.is_some() {
255                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
256                    }
257                    let value: &StringValue = ctx.from_value(value)?;
258                    let value = std::str::from_utf8(value.value())
259                        .map_err(FromValueError::new_other)?
260                        .to_string();
261                    battler_name_field = Some(value);
262                }
263                ARMOR3_FIX_FIELD => {
264                    if armor3_fix_field.is_some() {
265                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
266                    }
267                    let value: bool = ctx.from_value(value)?;
268                    armor3_fix_field = Some(value);
269                }
270                _ => {
271                    return Err(FromValueError::UnknownInstanceVariable { name: key.into() });
272                }
273            }
274        }
275
276        let initial_level =
277            initial_level_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
278                name: INITIAL_LEVEL_FIELD.into(),
279            })?;
280        let armor4_id = armor4_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
281            name: ARMOR4_ID_FIELD.into(),
282        })?;
283        let weapon_id = weapon_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
284            name: WEAPON_ID_FIELD.into(),
285        })?;
286        let character_name =
287            character_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
288                name: CHARACTER_NAME_FIELD.into(),
289            })?;
290        let name = name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
291            name: NAME_FIELD.into(),
292        })?;
293        let exp_inflation =
294            exp_inflation_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
295                name: EXP_INFLATION_FIELD.into(),
296            })?;
297        let parameters =
298            parameters_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
299                name: PARAMETERS_FIELD.into(),
300            })?;
301        let armor2_fix =
302            armor2_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
303                name: ARMOR2_FIX_FIELD.into(),
304            })?;
305        let class_id = class_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
306            name: CLASS_ID_FIELD.into(),
307        })?;
308        let armor3_id = armor3_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
309            name: ARMOR3_ID_FIELD.into(),
310        })?;
311        let armor1_fix =
312            armor1_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
313                name: ARMOR1_FIX_FIELD.into(),
314            })?;
315        let exp_basis = exp_basis_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
316            name: EXP_BASIS_FIELD.into(),
317        })?;
318        let armor2_id = armor2_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
319            name: ARMOR2_ID_FIELD.into(),
320        })?;
321        let battler_hue =
322            battler_hue_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
323                name: BATTLER_HUE_FIELD.into(),
324            })?;
325        let armor4_fix =
326            armor4_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
327                name: ARMOR4_FIX_FIELD.into(),
328            })?;
329        let final_level =
330            final_level_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
331                name: FINAL_LEVEL_FIELD.into(),
332            })?;
333        let weapon_fix =
334            weapon_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
335                name: WEAPON_FIX_FIELD.into(),
336            })?;
337        let armor1_id = armor1_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
338            name: ARMOR1_ID_FIELD.into(),
339        })?;
340        let id = id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
341            name: ID_FIELD.into(),
342        })?;
343        let character_hue =
344            character_hue_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
345                name: CHARACTER_HUE_FIELD.into(),
346            })?;
347        let battler_name =
348            battler_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
349                name: BATTLER_NAME_FIELD.into(),
350            })?;
351        let armor3_fix =
352            armor3_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
353                name: ARMOR3_FIX_FIELD.into(),
354            })?;
355
356        Ok(Self {
357            initial_level,
358            armor4_id,
359            weapon_id,
360            character_name,
361            name,
362            exp_inflation,
363            parameters,
364            armor2_fix,
365            class_id,
366            armor3_id,
367            armor1_fix,
368            exp_basis,
369            armor2_id,
370            battler_hue,
371            armor4_fix,
372            final_level,
373            weapon_fix,
374            armor1_id,
375            id,
376            character_hue,
377            battler_name,
378            armor3_fix,
379        })
380    }
381}
382
383impl IntoValue for Actor {
384    fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
385        let object_name = arena.create_symbol(OBJECT_NAME.into());
386
387        let initial_level_field_key = arena.create_symbol(INITIAL_LEVEL_FIELD.into());
388        let armor4_id_field_key = arena.create_symbol(ARMOR4_ID_FIELD.into());
389        let weapon_id_field_key = arena.create_symbol(WEAPON_ID_FIELD.into());
390        let character_name_field_key = arena.create_symbol(CHARACTER_NAME_FIELD.into());
391        let name_field_key = arena.create_symbol(NAME_FIELD.into());
392        let exp_inflation_field_key = arena.create_symbol(EXP_INFLATION_FIELD.into());
393        let parameters_field_key = arena.create_symbol(PARAMETERS_FIELD.into());
394        let armor2_fix_field_key = arena.create_symbol(ARMOR2_FIX_FIELD.into());
395        let class_id_field_key = arena.create_symbol(CLASS_ID_FIELD.into());
396        let armor3_id_field_key = arena.create_symbol(ARMOR3_ID_FIELD.into());
397        let armor1_fix_field_key = arena.create_symbol(ARMOR1_FIX_FIELD.into());
398        let exp_basis_field_key = arena.create_symbol(EXP_BASIS_FIELD.into());
399        let armor2_id_field_key = arena.create_symbol(ARMOR2_ID_FIELD.into());
400        let battler_hue_field_key = arena.create_symbol(BATTLER_HUE_FIELD.into());
401        let armor4_fix_field_key = arena.create_symbol(ARMOR4_FIX_FIELD.into());
402        let final_level_field_key = arena.create_symbol(FINAL_LEVEL_FIELD.into());
403        let weapon_fix_field_key = arena.create_symbol(WEAPON_FIX_FIELD.into());
404        let armor1_id_field_key = arena.create_symbol(ARMOR1_ID_FIELD.into());
405        let id_field_key = arena.create_symbol(ID_FIELD.into());
406        let character_hue_field_key = arena.create_symbol(CHARACTER_HUE_FIELD.into());
407        let battler_name_field_key = arena.create_symbol(BATTLER_NAME_FIELD.into());
408        let armor3_fix_field_key = arena.create_symbol(ARMOR3_FIX_FIELD.into());
409
410        let initial_level_field_value = self.initial_level.into_value(arena)?;
411        let armor4_id_field_value = self.armor4_id.into_value(arena)?;
412        let weapon_id_field_value = self.weapon_id.into_value(arena)?;
413        let character_name_field_value = arena.create_string(self.character_name.into()).into();
414        let name_field_value = arena.create_string(self.name.into()).into();
415        let exp_inflation_field_value = self.exp_inflation.into_value(arena)?;
416        let parameters_field_value = self.parameters.into_value(arena)?;
417        let armor2_fix_field_value = self.armor2_fix.into_value(arena)?;
418        let class_id_field_value = self.class_id.into_value(arena)?;
419        let armor3_id_field_value = self.armor3_id.into_value(arena)?;
420        let armor1_fix_field_value = self.armor1_fix.into_value(arena)?;
421        let exp_basis_field_value = self.exp_basis.into_value(arena)?;
422        let armor2_id_field_value = self.armor2_id.into_value(arena)?;
423        let battler_hue_field_value = self.battler_hue.into_value(arena)?;
424        let armor4_fix_field_value = self.armor4_fix.into_value(arena)?;
425        let final_level_field_value = self.final_level.into_value(arena)?;
426        let weapon_fix_field_value = self.weapon_fix.into_value(arena)?;
427        let armor1_id_field_value = self.armor1_id.into_value(arena)?;
428        let id_field_value = self.id.into_value(arena)?;
429        let character_hue_field_value = self.character_hue.into_value(arena)?;
430        let battler_name_field_value = arena.create_string(self.battler_name.into()).into();
431        let armor3_fix_field_value = self.armor3_fix.into_value(arena)?;
432
433        let fields = vec![
434            (initial_level_field_key, initial_level_field_value),
435            (armor4_id_field_key, armor4_id_field_value),
436            (weapon_id_field_key, weapon_id_field_value),
437            (character_name_field_key, character_name_field_value),
438            (name_field_key, name_field_value),
439            (exp_inflation_field_key, exp_inflation_field_value),
440            (parameters_field_key, parameters_field_value),
441            (armor2_fix_field_key, armor2_fix_field_value),
442            (class_id_field_key, class_id_field_value),
443            (armor3_id_field_key, armor3_id_field_value),
444            (armor1_fix_field_key, armor1_fix_field_value),
445            (exp_basis_field_key, exp_basis_field_value),
446            (armor2_id_field_key, armor2_id_field_value),
447            (battler_hue_field_key, battler_hue_field_value),
448            (armor4_fix_field_key, armor4_fix_field_value),
449            (final_level_field_key, final_level_field_value),
450            (weapon_fix_field_key, weapon_fix_field_value),
451            (armor1_id_field_key, armor1_id_field_value),
452            (id_field_key, id_field_value),
453            (character_hue_field_key, character_hue_field_value),
454            (battler_name_field_key, battler_name_field_value),
455            (armor3_fix_field_key, armor3_fix_field_value),
456        ];
457
458        let object = arena.create_object(object_name, fields);
459
460        Ok(object.into())
461    }
462}