1extern crate nalgebra as na;
15use crate::{
16 coalition::Side,
17 net::{PlayerId, SlotId, Ucid},
18 wrap_f, HooksLua, LuaEnv, String,
19};
20use anyhow::Result;
21use mlua::prelude::*;
22
23#[derive(Debug)]
24pub struct UserHooks<'lua> {
25 on_mission_load_begin: Option<mlua::Function<'lua>>,
26 on_mission_load_progress: Option<mlua::Function<'lua>>,
27 on_mission_load_end: Option<mlua::Function<'lua>>,
28 on_simulation_start: Option<mlua::Function<'lua>>,
29 on_simulation_stop: Option<mlua::Function<'lua>>,
30 on_simulation_frame: Option<mlua::Function<'lua>>,
31 on_simulation_pause: Option<mlua::Function<'lua>>,
32 on_simulation_resume: Option<mlua::Function<'lua>>,
33 on_player_connect: Option<mlua::Function<'lua>>,
34 on_player_disconnect: Option<mlua::Function<'lua>>,
35 on_player_start: Option<mlua::Function<'lua>>,
36 on_player_stop: Option<mlua::Function<'lua>>,
37 on_player_change_slot: Option<mlua::Function<'lua>>,
38 on_player_try_connect: Option<mlua::Function<'lua>>,
39 on_player_try_send_chat: Option<mlua::Function<'lua>>,
40 on_player_try_change_slot: Option<mlua::Function<'lua>>,
41 lua: &'lua Lua,
42}
43
44impl<'lua> UserHooks<'lua> {
45 pub fn new(lua: HooksLua<'lua>) -> Self {
46 Self {
47 on_mission_load_begin: None,
48 on_mission_load_progress: None,
49 on_mission_load_end: None,
50 on_simulation_start: None,
51 on_simulation_stop: None,
52 on_simulation_frame: None,
53 on_simulation_pause: None,
54 on_simulation_resume: None,
55 on_player_connect: None,
56 on_player_disconnect: None,
57 on_player_start: None,
58 on_player_stop: None,
59 on_player_change_slot: None,
60 on_player_try_change_slot: None,
61 on_player_try_connect: None,
62 on_player_try_send_chat: None,
63 lua: lua.inner(),
64 }
65 }
66
67 pub fn register(&mut self) -> Result<()> {
68 let Self {
69 on_mission_load_begin,
70 on_mission_load_progress,
71 on_mission_load_end,
72 on_simulation_start,
73 on_simulation_stop,
74 on_simulation_frame,
75 on_simulation_pause,
76 on_simulation_resume,
77 on_player_connect,
78 on_player_disconnect,
79 on_player_start,
80 on_player_stop,
81 on_player_change_slot,
82 on_player_try_connect,
83 on_player_try_send_chat,
84 on_player_try_change_slot,
85 lua: _,
86 } = self;
87 let tbl = self.lua.create_table()?;
88 if let Some(f) = on_mission_load_begin.take() {
89 tbl.set("onMissionLoadBegin", f)?;
90 }
91 if let Some(f) = on_mission_load_progress.take() {
92 tbl.set("onMissionLoadProgress", f)?;
93 }
94 if let Some(f) = on_mission_load_end.take() {
95 tbl.set("onMissionLoadEnd", f)?;
96 }
97 if let Some(f) = on_simulation_start.take() {
98 tbl.set("onSimulationStart", f)?;
99 }
100 if let Some(f) = on_simulation_stop.take() {
101 tbl.set("onSimulationStop", f)?;
102 }
103 if let Some(f) = on_simulation_frame.take() {
104 tbl.set("onSimulationFrame", f)?;
105 }
106 if let Some(f) = on_simulation_pause.take() {
107 tbl.set("onSimulationPause", f)?;
108 }
109 if let Some(f) = on_simulation_resume.take() {
110 tbl.set("onSimulationResume", f)?;
111 }
112 if let Some(f) = on_player_connect.take() {
113 tbl.set("onPlayerConnect", f)?;
114 }
115 if let Some(f) = on_player_disconnect.take() {
116 tbl.set("onPlayerDisconnect", f)?;
117 }
118 if let Some(f) = on_player_start.take() {
119 tbl.set("onPlayerStart", f)?;
120 }
121 if let Some(f) = on_player_stop.take() {
122 tbl.set("onPlayerStop", f)?;
123 }
124 if let Some(f) = on_player_change_slot.take() {
125 tbl.set("onPlayerChangeSlot", f)?;
126 }
127 if let Some(f) = on_player_try_connect.take() {
128 tbl.set("onPlayerTryConnect", f)?;
129 }
130 if let Some(f) = on_player_try_send_chat.take() {
131 tbl.set("onPlayerTrySendChat", f)?;
132 }
133 if let Some(f) = on_player_try_change_slot.take() {
134 tbl.set("onPlayerTryChangeSlot", f)?;
135 }
136 let dcs: mlua::Table = self.lua.globals().get("DCS")?;
137 Ok(dcs.call_function("setUserCallbacks", tbl)?)
138 }
139
140 pub fn on_mission_load_begin<F>(&mut self, f: F) -> Result<&mut Self>
141 where
142 F: Fn(HooksLua) -> Result<()> + 'static,
143 {
144 self.on_mission_load_begin =
145 Some(self.lua.create_function(move |lua, ()| {
146 wrap_f("on_mission_load_begin", HooksLua(lua), &f)
147 })?);
148 Ok(self)
149 }
150
151 pub fn on_mission_load_progress<F>(&mut self, f: F) -> Result<&mut Self>
153 where
154 F: Fn(HooksLua, String, String) -> Result<()> + 'static,
155 {
156 self.on_mission_load_progress = Some(self.lua.create_function(
157 move |lua, (progress, message): (String, String)| {
158 wrap_f("on_mission_load_progress", HooksLua(lua), |lua| {
159 f(lua, progress, message)
160 })
161 },
162 )?);
163 Ok(self)
164 }
165
166 pub fn on_mission_load_end<F>(&mut self, f: F) -> Result<&mut Self>
167 where
168 F: Fn(HooksLua) -> Result<()> + 'static,
169 {
170 self.on_mission_load_end =
171 Some(self.lua.create_function(move |lua, ()| {
172 wrap_f("on_mission_load_end", HooksLua(lua), &f)
173 })?);
174 Ok(self)
175 }
176
177 pub fn on_simulation_start<F>(&mut self, f: F) -> Result<&mut Self>
178 where
179 F: Fn(HooksLua) -> Result<()> + 'static,
180 {
181 self.on_simulation_start =
182 Some(self.lua.create_function(move |lua, ()| {
183 wrap_f("on_simulation_start", HooksLua(lua), &f)
184 })?);
185 Ok(self)
186 }
187
188 pub fn on_simulation_stop<F>(&mut self, f: F) -> Result<&mut Self>
189 where
190 F: Fn(HooksLua) -> Result<()> + 'static,
191 {
192 self.on_simulation_stop = Some(
193 self.lua
194 .create_function(move |lua, ()| wrap_f("on_simulation_stop", HooksLua(lua), &f))?,
195 );
196 Ok(self)
197 }
198
199 pub fn on_simulation_frame<F>(&mut self, f: F) -> Result<&mut Self>
200 where
201 F: Fn(HooksLua) -> Result<()> + 'static,
202 {
203 self.on_simulation_frame =
204 Some(self.lua.create_function(move |lua, ()| {
205 wrap_f("on_simulation_frame", HooksLua(lua), &f)
206 })?);
207 Ok(self)
208 }
209
210 pub fn on_simulation_pause<F>(&mut self, f: F) -> Result<&mut Self>
211 where
212 F: Fn(HooksLua) -> Result<()> + 'static,
213 {
214 self.on_simulation_pause =
215 Some(self.lua.create_function(move |lua, ()| {
216 wrap_f("on_simulation_pause", HooksLua(lua), &f)
217 })?);
218 Ok(self)
219 }
220
221 pub fn on_simulation_resume<F>(&mut self, f: F) -> Result<&mut Self>
222 where
223 F: Fn(HooksLua) -> Result<()> + 'static,
224 {
225 self.on_simulation_resume =
226 Some(self.lua.create_function(move |lua, ()| {
227 wrap_f("on_simulation_resume", HooksLua(lua), &f)
228 })?);
229 Ok(self)
230 }
231
232 pub fn on_player_connect<F>(&mut self, f: F) -> Result<&mut Self>
233 where
234 F: Fn(HooksLua, PlayerId) -> Result<()> + 'static,
235 {
236 self.on_player_connect = Some(self.lua.create_function(move |lua, id| {
237 wrap_f("on_player_connect", HooksLua(lua), |lua| f(lua, id))
238 })?);
239 Ok(self)
240 }
241
242 pub fn on_player_disconnect<F>(&mut self, f: F) -> Result<&mut Self>
243 where
244 F: Fn(HooksLua, PlayerId) -> Result<()> + 'static,
245 {
246 self.on_player_disconnect = Some(self.lua.create_function(move |lua, id| {
247 wrap_f("on_player_disconnect", HooksLua(lua), |lua| f(lua, id))
248 })?);
249 Ok(self)
250 }
251
252 pub fn on_player_start<F>(&mut self, f: F) -> Result<&mut Self>
253 where
254 F: Fn(HooksLua, PlayerId) -> Result<()> + 'static,
255 {
256 self.on_player_start = Some(self.lua.create_function(move |lua, id| {
257 wrap_f("on_player_start", HooksLua(lua), |lua| f(lua, id))
258 })?);
259 Ok(self)
260 }
261
262 pub fn on_player_stop<F>(&mut self, f: F) -> Result<&mut Self>
263 where
264 F: Fn(HooksLua, PlayerId) -> Result<()> + 'static,
265 {
266 self.on_player_stop = Some(self.lua.create_function(move |lua, id| {
267 wrap_f("on_player_stop", HooksLua(lua), |lua| f(lua, id))
268 })?);
269 Ok(self)
270 }
271
272 pub fn on_player_change_slot<F>(&mut self, f: F) -> Result<&mut Self>
273 where
274 F: Fn(HooksLua, PlayerId) -> Result<()> + 'static,
275 {
276 self.on_player_change_slot = Some(self.lua.create_function(move |lua, id| {
277 wrap_f("on_player_change_slot", HooksLua(lua), |lua| f(lua, id))
278 })?);
279 Ok(self)
280 }
281
282 pub fn on_player_try_connect<F>(&mut self, f: F) -> Result<&mut Self>
285 where
286 F: Fn(HooksLua, String, String, Ucid, PlayerId) -> Result<Option<String>> + 'static,
287 {
288 self.on_player_try_connect = Some(self.lua.create_function(
289 move |lua, (addr, name, ucid, id): (String, String, Ucid, PlayerId)| {
290 wrap_f("on_player_try_connect", HooksLua(lua), |lua| {
291 let mut rval = LuaMultiValue::new();
292 match f(lua, addr, name, ucid, id) {
293 Err(e) => return Err(e),
294 Ok(None) => rval.push_front(LuaValue::Boolean(true)),
295 Ok(Some(reason)) => {
296 rval.push_front(reason.into_lua(lua.inner())?);
297 rval.push_front(LuaValue::Boolean(false));
298 }
299 }
300 Ok(rval)
301 })
302 },
303 )?);
304 Ok(self)
305 }
306
307 pub fn on_player_try_send_chat<F>(&mut self, f: F) -> Result<&mut Self>
309 where
310 F: Fn(HooksLua, PlayerId, String, bool) -> Result<String> + 'static,
311 {
312 self.on_player_try_send_chat = Some(self.lua.create_function(
313 move |lua, (id, msg, all): (PlayerId, String, bool)| {
314 wrap_f("on_player_try_send_chat", HooksLua(lua), |lua| {
315 f(lua, id, msg, all)
316 })
317 },
318 )?);
319 Ok(self)
320 }
321
322 pub fn on_player_try_change_slot<F>(&mut self, f: F) -> Result<&mut Self>
324 where
325 F: Fn(HooksLua, PlayerId, Side, SlotId) -> Result<Option<bool>> + 'static,
326 {
327 self.on_player_try_change_slot = Some(self.lua.create_function(
328 move |lua, (id, side, slot): (PlayerId, Side, SlotId)| {
329 wrap_f("on_player_try_change_slot", HooksLua(lua), |lua| {
330 f(lua, id, side, slot)
331 })
332 },
333 )?);
334 Ok(self)
335 }
336}