1use crate::settings::Settings;
4
5#[derive(Debug, Clone, Default)]
7pub struct Program {
8 pub settings: Option<Settings>,
9 pub global_variables: Vec<Variable>,
10 pub player_variables: Vec<Variable>,
11 pub subroutines: Vec<Subroutine>,
12 pub rules: Vec<Rule>,
13}
14
15impl Program {
16 pub fn new() -> Self {
17 Self::default()
18 }
19
20 pub fn global_variable(&mut self, variable: Variable) -> &mut Self {
21 self.global_variables.push(variable);
22 self
23 }
24
25 pub fn player_variable(&mut self, variable: Variable) -> &mut Self {
26 self.player_variables.push(variable);
27 self
28 }
29
30 pub fn subroutine(&mut self, subroutine: Subroutine) -> &mut Self {
31 self.subroutines.push(subroutine);
32 self
33 }
34
35 pub fn rule(&mut self, rule: Rule) -> &mut Self {
36 self.rules.push(rule);
37 self
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct Variable {
44 pub name: String,
45 pub index: Option<u32>,
47}
48
49impl Variable {
50 pub fn new(name: impl Into<String>) -> Self {
51 Self {
52 name: name.into(),
53 index: None,
54 }
55 }
56
57 pub fn with_index(name: impl Into<String>, index: u32) -> Self {
58 Self {
59 name: name.into(),
60 index: Some(index),
61 }
62 }
63}
64
65#[derive(Debug, Clone, PartialEq, Eq)]
67pub struct Subroutine {
68 pub name: String,
69 pub index: Option<u32>,
71}
72
73impl Subroutine {
74 pub fn new(name: impl Into<String>) -> Self {
75 Self {
76 name: name.into(),
77 index: None,
78 }
79 }
80
81 pub fn with_index(name: impl Into<String>, index: u32) -> Self {
82 Self {
83 name: name.into(),
84 index: Some(index),
85 }
86 }
87}
88
89#[derive(Debug, Clone)]
91pub struct Rule {
92 pub name: String,
93 pub disabled: bool,
94 pub event: Event,
95 pub conditions: Vec<Condition>,
96 pub actions: Vec<Action>,
97}
98
99impl Rule {
100 pub fn new(name: impl Into<String>, event: Event) -> Self {
101 Self {
102 name: name.into(),
103 disabled: false,
104 event,
105 conditions: Vec::new(),
106 actions: Vec::new(),
107 }
108 }
109
110 pub fn condition(mut self, condition: impl Into<Condition>) -> Self {
111 self.conditions.push(condition.into());
112 self
113 }
114
115 pub fn action(mut self, action: Action) -> Self {
116 self.actions.push(action);
117 self
118 }
119}
120
121#[derive(Debug, Clone)]
123pub struct Condition {
124 pub value: Value,
125 pub disabled: bool,
126}
127
128impl Condition {
129 pub fn new(value: Value) -> Self {
130 Self {
131 value,
132 disabled: false,
133 }
134 }
135
136 pub fn disabled(value: Value) -> Self {
137 Self {
138 value,
139 disabled: true,
140 }
141 }
142}
143
144impl From<Value> for Condition {
145 fn from(value: Value) -> Self {
146 Self::new(value)
147 }
148}
149
150#[derive(Debug, Clone, PartialEq, Eq)]
152pub enum Event {
153 Global,
154 EachPlayer,
155 EachPlayerWithFilters {
156 team: EventTeam,
157 target: EventTarget,
158 },
159 Player {
160 kind: PlayerEventKind,
161 team: EventTeam,
162 target: EventTarget,
163 },
164 Subroutine(String),
165}
166
167#[derive(Debug, Clone, Copy, PartialEq, Eq)]
168pub enum EventTeam {
169 All,
170 Team1,
171 Team2,
172}
173
174#[derive(Debug, Clone, PartialEq, Eq)]
175pub enum EventTarget {
176 All,
177 Slot(u8),
178 Hero(String),
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq)]
182pub enum PlayerEventKind {
183 DealtDamage,
184 DealtFinalBlow,
185 DealtHealing,
186 DealtKnockback,
187 Died,
188 EarnedElimination,
189 Joined,
190 Left,
191 ReceivedHealing,
192 ReceivedKnockback,
193 TookDamage,
194}
195
196#[derive(Debug, Clone)]
199pub enum Action {
200 SetGlobalVariable {
201 variable: String,
202 value: Value,
203 },
204 ModifyGlobalVariable {
205 variable: String,
206 op: ModifyOp,
207 value: Value,
208 },
209 SetPlayerVariable {
210 player: Value,
211 variable: String,
212 value: Value,
213 },
214 ModifyPlayerVariable {
215 player: Value,
216 variable: String,
217 op: ModifyOp,
218 value: Value,
219 },
220 AssignMember {
221 target: Value,
222 op: Option<ModifyOp>,
223 value: Value,
224 },
225 CallSubroutine {
226 subroutine: String,
227 },
228 If {
229 condition: Value,
230 },
231 ElseIf {
232 condition: Value,
233 },
234 Else,
235 While {
236 condition: Value,
237 },
238 ForGlobalVariable {
239 variable: String,
240 start: Value,
241 stop: Value,
242 step: Value,
243 },
244 ForPlayerVariable {
245 player: Value,
246 variable: String,
247 start: Value,
248 stop: Value,
249 step: Value,
250 },
251 End,
252 Disabled {
253 action: Box<Action>,
254 },
255 Call {
256 name: String,
257 args: Vec<Value>,
258 },
259}
260
261impl Action {
262 pub fn disabled(action: Action) -> Self {
264 Self::Disabled {
265 action: Box::new(action),
266 }
267 }
268
269 pub fn call(name: impl Into<String>, args: impl IntoIterator<Item = Value>) -> Self {
271 Self::Call {
272 name: name.into(),
273 args: args.into_iter().collect(),
274 }
275 }
276}
277
278#[derive(Debug, Clone, Copy, PartialEq, Eq)]
280pub enum ModifyOp {
281 Add,
282 Subtract,
283 Multiply,
284 Divide,
285 Modulo,
286 Min,
287 Max,
288 RaiseToPower,
289 AppendToArray,
290 RemoveFromArray,
291 RemoveFromArrayByIndex,
292}
293
294#[derive(Debug, Clone)]
296pub enum Value {
297 Number(f64),
298 String(String),
299 LocalizedString(String),
300 Bool(bool),
301 Null,
302 Array(Vec<Value>),
303 Vector {
304 x: Box<Value>,
305 y: Box<Value>,
306 z: Box<Value>,
307 },
308 Enum {
309 value_type: String,
310 value: String,
311 },
312 GlobalVariable(String),
313 PlayerVariable {
314 player: Box<Value>,
315 variable: String,
316 },
317 Subroutine(String),
318 EventPlayer,
319 Call {
320 name: String,
321 args: Vec<Value>,
322 },
323}
324
325impl Value {
326 pub fn number(value: f64) -> Self {
328 Self::Number(value)
329 }
330
331 pub fn string(value: impl Into<String>) -> Self {
333 Self::String(value.into())
334 }
335
336 pub fn global_variable(name: impl Into<String>) -> Self {
337 Self::GlobalVariable(name.into())
338 }
339
340 pub fn player_variable(player: Value, name: impl Into<String>) -> Self {
341 Self::PlayerVariable {
342 player: Box::new(player),
343 variable: name.into(),
344 }
345 }
346
347 pub fn call(name: impl Into<String>, args: impl IntoIterator<Item = Value>) -> Self {
349 Self::Call {
350 name: name.into(),
351 args: args.into_iter().collect(),
352 }
353 }
354}
355
356impl From<bool> for Value {
357 fn from(value: bool) -> Self {
358 Self::Bool(value)
359 }
360}
361
362impl From<f64> for Value {
363 fn from(value: f64) -> Self {
364 Self::Number(value)
365 }
366}
367
368impl From<f32> for Value {
369 fn from(value: f32) -> Self {
370 Self::Number(f64::from(value))
371 }
372}
373
374macro_rules! impl_integer_value {
375 ($($type:ty),+ $(,)?) => {
376 $(
377 impl From<$type> for Value {
378 fn from(value: $type) -> Self {
379 Self::Number(value as f64)
380 }
381 }
382 )+
383 };
384}
385
386impl_integer_value!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
387
388impl From<String> for Value {
389 fn from(value: String) -> Self {
390 Self::String(value)
391 }
392}
393
394impl From<&str> for Value {
395 fn from(value: &str) -> Self {
396 Self::String(value.to_string())
397 }
398}
399
400impl<T: Into<Value>> From<Vec<T>> for Value {
401 fn from(values: Vec<T>) -> Self {
402 Self::Array(values.into_iter().map(Into::into).collect())
403 }
404}
405
406impl<T: Into<Value>, const N: usize> From<[T; N]> for Value {
407 fn from(values: [T; N]) -> Self {
408 Self::Array(values.into_iter().map(Into::into).collect())
409 }
410}
411
412include!(concat!(env!("OUT_DIR"), "/typed_api.rs"));