wolfrpg_map_parser/db_parser/models/
common_event.rs

1pub mod argument;
2pub mod argument_type;
3pub mod run_condition;
4pub mod condition_type;
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8use crate::byte_utils::{as_u32_le, as_u32_vec, parse_string, parse_string_vec};
9use crate::command::Command;
10use crate::db_parser::common_event::run_condition::RunCondition;
11use crate::db_parser::models::common_event::argument::Argument;
12
13const EVENT_SIGNATURE: u8 = 0x8e;
14const END_SIGNATURE: u8 = 0x92;
15
16/// A common event, representing a common series of command that can be invoked from any event
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18#[derive(PartialEq, Clone)]
19pub struct CommonEvent {
20    id: u32,
21    run_condition: RunCondition,
22    event_name: String,
23    commands: Vec<Command>,
24    note: String,
25    arguments: Vec<Argument>,
26    color: u32,
27    var_names: Vec<String>,
28    return_name: String,
29    return_variable: u32
30}
31
32impl CommonEvent {
33    pub(crate) fn parse(bytes: &[u8]) -> (usize, Self) {
34        let mut offset: usize = 0;
35
36        let signature: u8 = bytes[offset];
37        offset += 1;
38
39        if signature != EVENT_SIGNATURE {
40            panic!("Invalid common event signature: {:02x}.", signature);
41        }
42
43        let id: u32 = as_u32_le(&bytes[offset..offset+4]);
44        offset += 4;
45
46        let condition_settings: u8 = bytes[offset];
47        offset += 1;
48        
49        let condition_variable: u32 = as_u32_le(&bytes[offset..offset+4]);
50        offset += 4;
51
52        let condition_value: u32 = as_u32_le(&bytes[offset..offset+4]);
53        offset += 4;
54        
55        let run_condition: RunCondition = RunCondition::new(
56            condition_settings,
57            condition_variable,
58            condition_value
59        );
60
61        let number_arguments_count: u8 = bytes[offset];
62        offset += 1;
63
64        let string_arguments_count: u8 = bytes[offset];
65        offset += 1;
66
67        let (bytes_read, event_name): (usize, String) = parse_string(&bytes[offset..]);
68        offset += bytes_read;
69
70        let command_count: u32 = as_u32_le(&bytes[offset..offset+4]);
71        offset += 4;
72
73        let (bytes_read, commands_read, commands): (usize, u32, Vec<Command>)
74            = Command::parse_multiple(&bytes[offset..]);
75        offset += bytes_read;
76
77        if commands_read != command_count {
78            panic!("Expected {} commands but only found {}.", command_count, commands_read);
79        }
80
81        // Unknown field
82        let (bytes_read, _): (usize, String) = parse_string(&bytes[offset..]);
83        offset += bytes_read;
84
85        let (bytes_read, note): (usize, String) = parse_string(&bytes[offset..]);
86        offset += bytes_read;
87
88        offset += 1; // Unknown, probably padding
89
90        let argument_names_count: usize = as_u32_le(&bytes[offset..offset+4]) as usize;
91        offset += 4;
92
93        let (bytes_read, argument_names): (usize, Vec<String>)
94            = parse_string_vec(&bytes[offset..], argument_names_count);
95        offset += bytes_read;
96
97        let argument_types_count: usize = as_u32_le(&bytes[offset..offset+4]) as usize;
98        offset += 4;
99
100        let argument_types: &[u8] = &bytes[offset..][..argument_types_count];
101        offset += argument_types_count;
102
103        let (bytes_read, db_options): (usize, Vec<Vec<String>>)
104            = Self::parse_db_options(&bytes[offset..]);
105        offset += bytes_read;
106
107        let (bytes_read, db_references): (usize, Vec<Vec<u32>>)
108            = Self::parse_db_references(&bytes[offset..]);
109        offset += bytes_read;
110
111        let len: usize = as_u32_le(&bytes[offset..offset+4]) as usize;
112        offset += 4;
113
114        let argument_values: Vec<u32> = as_u32_vec(&bytes[offset..][..len*4]);
115        offset += len * 4;
116
117        offset += 1; // Unknown, probably padding
118
119        let color: u32 = as_u32_le(&bytes[offset..offset+4]);
120        offset += 4;
121
122        let (bytes_read, var_names): (usize, Vec<String>)
123            = parse_string_vec(&bytes[offset..], 100);
124        offset += bytes_read;
125
126        // Unknown values, probably padding
127        offset += 1;
128        offset += 4 + as_u32_le(&bytes[offset..offset+4]) as usize;
129        offset += 1;
130
131        let (bytes_read, return_name): (usize, String)
132            = parse_string(&bytes[offset..]);
133        offset += bytes_read;
134
135        let return_variable: u32 = as_u32_le(&bytes[offset..offset+4]);
136        offset += 4;
137
138        let end_signature: u8 = bytes[offset];
139        offset += 1;
140
141        if end_signature != END_SIGNATURE {
142            panic!("Invalid common event end signature: {:02x}.", end_signature);
143        }
144
145        let arguments: Vec<Argument> = Self::pack_arguments(
146            number_arguments_count as usize,
147            string_arguments_count as usize,
148            argument_names,
149            argument_types,
150            argument_values,
151            db_options,
152            db_references
153        );
154
155        (offset, Self {
156            id,
157            run_condition,
158            event_name,
159            commands,
160            note,
161            arguments,
162            color,
163            var_names,
164            return_name,
165            return_variable
166        })
167    }
168
169    fn parse_db_options(bytes: &[u8]) -> (usize, Vec<Vec<String>>) {
170        let mut offset: usize = 0;
171
172        let db_option_count: usize = as_u32_le(&bytes[offset..offset+4]) as usize;
173        offset += 4;
174
175        let mut db_options: Vec<Vec<String>> = vec![];
176
177        for _ in 0..db_option_count {
178            let len: usize = as_u32_le(&bytes[offset..offset+4]) as usize;
179            offset += 4;
180
181            let (bytes_read, options): (usize, Vec<String>)
182                = parse_string_vec(&bytes[offset..], len);
183            offset += bytes_read;
184
185            db_options.push(options);
186        }
187
188        (offset, db_options)
189    }
190
191    fn parse_db_references(bytes: &[u8]) -> (usize, Vec<Vec<u32>>) {
192        let mut offset: usize = 0;
193
194        let db_references_count: usize = as_u32_le(&bytes[offset..offset+4]) as usize;
195        offset += 4;
196
197        let mut db_references: Vec<Vec<u32>> = vec![];
198
199        for _ in 0..db_references_count {
200            let len: usize = as_u32_le(&bytes[offset..offset+4]) as usize;
201            offset += 4;
202
203            let references: Vec<u32>
204                = as_u32_vec(&bytes[offset..][..len*4]);
205            offset += len*4;
206
207            db_references.push(references);
208        }
209
210        (offset, db_references)
211    }
212
213    fn pack_arguments(
214        number_argument_count: usize,
215        string_argument_count: usize,
216        argument_names: Vec<String>,
217        argument_types: &[u8],
218        default_values: Vec<u32>,
219        db_options: Vec<Vec<String>>,
220        db_references: Vec<Vec<u32>>
221    ) -> Vec<Argument> {
222        let mut arguments: Vec<Argument> = vec![];
223
224        for i in 0..number_argument_count {
225            let argument_name: String = argument_names[i].clone();
226            let argument_type: u8 = argument_types[i];
227            let default_value: u32 = default_values[i];
228            let db_options: Vec<String> = db_options[i].clone();
229            let db_references: Vec<u32> = db_references[i].clone();
230
231            arguments.push(Argument::new(
232                argument_type,
233                argument_name,
234                Some(default_value),
235                db_options,
236                db_references
237            ));
238        }
239
240        for i in 5..5+string_argument_count {
241            let argument_name: String = argument_names[i].clone();
242            let argument_type: u8 = argument_types[i];
243            let db_options: Vec<String> = db_options[i].clone();
244            let db_references: Vec<u32> = db_references[i].clone();
245
246            arguments.push(Argument::new(
247                argument_type,
248                argument_name,
249                None,
250                db_options,
251                db_references
252            ));
253        }
254
255        arguments
256    }
257
258    /// The ID of this common event in the database
259    pub fn id(&self) -> u32 {
260        self.id
261    }
262
263    /// The condition under which this event will run
264    pub fn run_condition(&self) -> &RunCondition {
265        &self.run_condition
266    }
267
268    /// The name of this event, which can be used for invoking it
269    pub fn event_name(&self) -> &str {
270        &self.event_name
271    }
272
273    /// The event script, in the form of a [`Command`] collection.
274    pub fn commands(&self) -> &Vec<Command> {
275        &self.commands
276    }
277
278    /// A developer note for this event
279    pub fn note(&self) -> &str {
280        &self.note
281    }
282
283    /// A list of arguments that can be passed when invoking this event
284    pub fn arguments(&self) -> &Vec<Argument> {
285        &self.arguments
286    }
287
288    /// The color of this event, for display purposes
289    pub fn color(&self) -> u32 {
290        self.color
291    }
292
293    /// A list of names for each of the 100 local variables available in this event.
294    pub fn var_names(&self) -> &Vec<String> {
295        &self.var_names
296    }
297
298    /// The name of the variable in which the return value will be put
299    pub fn return_name(&self) -> &str {
300        &self.return_name
301    }
302
303    /// The address of the variable in which the return value will be put
304    pub fn return_variable(&self) -> u32 {
305        self.return_variable
306    }
307}