1 /*
2  * Copyright (C) 2006-2019 Christopho, Solarus - http://www.solarus-games.org
3  *
4  * Solarus is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Solarus is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 #include "solarus/audio/Sound.h"
18 #include "solarus/core/CurrentQuest.h"
19 #include "solarus/core/Debug.h"
20 #include "solarus/core/Geometry.h"
21 #include "solarus/core/Equipment.h"
22 #include "solarus/core/EquipmentItem.h"
23 #include "solarus/core/Game.h"
24 #include "solarus/core/Map.h"
25 #include "solarus/core/Savegame.h"
26 #include "solarus/core/Timer.h"
27 #include "solarus/entities/Block.h"
28 #include "solarus/entities/CarriedObject.h"
29 #include "solarus/entities/Chest.h"
30 #include "solarus/entities/CustomEntity.h"
31 #include "solarus/entities/Destination.h"
32 #include "solarus/entities/Destructible.h"
33 #include "solarus/entities/DynamicTile.h"
34 #include "solarus/entities/Door.h"
35 #include "solarus/entities/Enemy.h"
36 #include "solarus/entities/Entities.h"
37 #include "solarus/entities/EntityTypeInfo.h"
38 #include "solarus/entities/GroundInfo.h"
39 #include "solarus/entities/Hero.h"
40 #include "solarus/entities/Npc.h"
41 #include "solarus/entities/Pickable.h"
42 #include "solarus/entities/Sensor.h"
43 #include "solarus/entities/Separator.h"
44 #include "solarus/entities/ShopTreasure.h"
45 #include "solarus/entities/Stairs.h"
46 #include "solarus/entities/Stream.h"
47 #include "solarus/entities/StreamAction.h"
48 #include "solarus/entities/Switch.h"
49 #include "solarus/entities/Teletransporter.h"
50 #include "solarus/entities/Tileset.h"
51 #include "solarus/graphics/Sprite.h"
52 #include "solarus/hero/CustomState.h"
53 #include "solarus/hero/HeroSprites.h"
54 #include "solarus/lua/ExportableToLuaPtr.h"
55 #include "solarus/lua/LuaContext.h"
56 #include "solarus/lua/LuaTools.h"
57 #include "solarus/movements/Movement.h"
58 #include <sstream>
59 
60 namespace Solarus {
61 
62 namespace {
63 
64 /**
65  * \brief Returns the Lua metatable names of each entity type.
66  * \return The Lua metatable name of each entity type.
67  */
get_entity_internal_type_names()68 const std::map<EntityType, std::string>& get_entity_internal_type_names() {
69 
70   static std::map<EntityType, std::string> result;
71   if (result.empty()) {
72     for (const auto& kvp : EnumInfoTraits<EntityType>::names) {
73       std::string internal_type_name = std::string("sol.") + kvp.second;
74       result.emplace(kvp.first, internal_type_name);
75     }
76   }
77 
78   return result;
79 }
80 /**
81  * \brief Returns a set of the Lua metatable names of all entity types.
82  * \return The Lua metatable name of all entity types.
83  */
get_entity_internal_type_names_set()84 const std::set<std::string>& get_entity_internal_type_names_set() {
85 
86   static std::set<std::string> result;
87   if (result.empty()) {
88     for (const auto& kvp : EnumInfoTraits<EntityType>::names) {
89       result.insert(LuaContext::get_entity_internal_type_name(kvp.first));
90     }
91   }
92 
93   return result;
94 }
95 
96 }
97 
98 /**
99  * \brief Initializes the map entity features provided to Lua.
100  */
register_entity_module()101 void LuaContext::register_entity_module() {
102 
103   // Methods common to all entity types.
104   std::vector<luaL_Reg> common_methods = {
105       { "get_type", entity_api_get_type },
106       { "get_map", entity_api_get_map },
107       { "get_game", entity_api_get_game },
108       { "get_name", entity_api_get_name },
109       { "exists", entity_api_exists },
110       { "remove", entity_api_remove },
111       { "is_enabled", entity_api_is_enabled },
112       { "set_enabled", entity_api_set_enabled },
113       { "get_size", entity_api_get_size },
114       { "get_origin", entity_api_get_origin },
115       { "get_position", entity_api_get_position },
116       { "set_position", entity_api_set_position },
117       { "get_center_position", entity_api_get_center_position },
118       { "get_facing_position", entity_api_get_facing_position },
119       { "get_facing_entity", entity_api_get_facing_entity },
120       { "get_ground_position", entity_api_get_ground_position },
121       { "get_ground_below", entity_api_get_ground_below },
122       { "get_bounding_box", entity_api_get_bounding_box },
123       { "get_max_bounding_box", entity_api_get_max_bounding_box },
124       { "overlaps", entity_api_overlaps },
125       { "get_distance", entity_api_get_distance },
126       { "get_angle", entity_api_get_angle },
127       { "get_direction4_to", entity_api_get_direction4_to },
128       { "get_direction8_to", entity_api_get_direction8_to },
129       { "snap_to_grid", entity_api_snap_to_grid },
130       { "bring_to_front", entity_api_bring_to_front },
131       { "bring_to_back", entity_api_bring_to_back },
132       { "is_drawn_in_y_order", entity_api_is_drawn_in_y_order },
133       { "set_drawn_in_y_order", entity_api_set_drawn_in_y_order },
134       { "get_optimization_distance", entity_api_get_optimization_distance },
135       { "set_optimization_distance", entity_api_set_optimization_distance },
136       { "is_in_same_region", entity_api_is_in_same_region },
137       { "test_obstacles", entity_api_test_obstacles },
138       { "get_sprite", entity_api_get_sprite },
139       { "get_sprites", entity_api_get_sprites },
140       { "create_sprite", entity_api_create_sprite },
141       { "remove_sprite", entity_api_remove_sprite },
142       { "bring_sprite_to_front", entity_api_bring_sprite_to_front },
143       { "bring_sprite_to_back", entity_api_bring_sprite_to_back },
144       { "is_visible", entity_api_is_visible },
145       { "set_visible", entity_api_set_visible },
146       { "get_movement", entity_api_get_movement },
147       { "stop_movement", entity_api_stop_movement },
148   };
149   if (CurrentQuest::is_format_at_least({ 1, 6 })) {
150     common_methods.insert(common_methods.end(), {
151         { "get_layer", entity_api_get_layer },
152         { "set_layer", entity_api_set_layer },
153         { "set_size", entity_api_set_size },
154         { "set_origin", entity_api_set_origin },
155         { "get_draw_override", entity_api_get_draw_override },
156         { "set_draw_override", entity_api_set_draw_override },
157         { "get_weight", entity_api_get_weight },
158         { "set_weight", entity_api_set_weight },
159         { "get_controlling_stream", entity_api_get_controlling_stream },
160         { "get_property", entity_api_get_property },
161         { "set_property", entity_api_set_property },
162         { "get_properties", entity_api_get_properties },
163         { "set_properties", entity_api_set_properties },
164     });
165   }
166 
167   // Metamethods of all entity types.
168   std::vector<luaL_Reg> metamethods = {
169       { "__gc", userdata_meta_gc },
170       { "__newindex", userdata_meta_newindex_as_table },
171       { "__index", userdata_meta_index_as_table },
172   };
173 
174   // Hero.
175   std::vector<luaL_Reg> hero_methods = {
176       { "teleport", hero_api_teleport },
177       { "get_direction", hero_api_get_direction },
178       { "set_direction", hero_api_set_direction },
179       { "get_walking_speed", hero_api_get_walking_speed },
180       { "set_walking_speed", hero_api_set_walking_speed },
181       { "save_solid_ground", hero_api_save_solid_ground },
182       { "reset_solid_ground", hero_api_reset_solid_ground },
183       { "get_solid_ground_position", hero_api_get_solid_ground_position },
184       { "get_animation", hero_api_get_animation },
185       { "set_animation", hero_api_set_animation },
186       { "get_tunic_sprite_id", hero_api_get_tunic_sprite_id },
187       { "set_tunic_sprite_id", hero_api_set_tunic_sprite_id },
188       { "get_sword_sprite_id", hero_api_get_sword_sprite_id },
189       { "set_sword_sprite_id", hero_api_set_sword_sprite_id },
190       { "get_sword_sound_id", hero_api_get_sword_sound_id },
191       { "set_sword_sound_id", hero_api_set_sword_sound_id },
192       { "get_shield_sprite_id", hero_api_get_shield_sprite_id },
193       { "set_shield_sprite_id", hero_api_set_shield_sprite_id },
194       { "is_blinking", hero_api_is_blinking },
195       { "set_blinking", hero_api_set_blinking },
196       { "is_invincible", hero_api_is_invincible },
197       { "set_invincible", hero_api_set_invincible },
198       { "freeze", hero_api_freeze },
199       { "unfreeze", hero_api_unfreeze },
200       { "walk", hero_api_walk },  // TODO use the more general movement:start
201       { "start_attack", hero_api_start_attack },
202       { "start_attack_loading", hero_api_start_attack_loading },
203       { "start_item", hero_api_start_item },
204       { "start_grabbing", hero_api_start_grabbing },
205       { "start_jumping", hero_api_start_jumping },
206       { "start_treasure", hero_api_start_treasure },
207       { "start_victory", hero_api_start_victory},
208       { "start_boomerang", hero_api_start_boomerang },
209       { "start_bow", hero_api_start_bow },
210       { "start_hookshot", hero_api_start_hookshot },
211       { "start_running", hero_api_start_running },
212       { "start_hurt", hero_api_start_hurt },
213       { "get_state", entity_api_get_state },
214       { "get_state_object", hero_api_get_state_object },
215   };
216   if (CurrentQuest::is_format_at_least({ 1, 6 })) {
217     hero_methods.insert(hero_methods.end(), {
218         { "get_carried_object", hero_api_get_carried_object },
219         { "start_state", hero_api_start_state },
220     });
221   }
222 
223   hero_methods.insert(hero_methods.end(), common_methods.begin(), common_methods.end());
224   register_type(
225       get_entity_internal_type_name(EntityType::HERO),
226       {},
227       hero_methods,
228       metamethods
229   );
230 
231   // Camera.
232   std::vector<luaL_Reg> camera_methods = {
233       { "get_position_on_screen", camera_api_get_position_on_screen },
234       { "set_position_on_screen", camera_api_set_position_on_screen },
235       { "get_state", entity_api_get_state },
236       { "start_tracking", camera_api_start_tracking },
237       { "start_manual", camera_api_start_manual },
238       { "get_position_to_track", camera_api_get_position_to_track },
239       { "get_tracked_entity", camera_api_get_tracked_entity },
240   };
241   if (CurrentQuest::is_format_at_most({ 1, 5 })) {
242     camera_methods.insert(camera_methods.end(), {
243         // Available to all entities since 1.6.
244         { "set_size", entity_api_set_size },
245     });
246   }
247   if (CurrentQuest::is_format_at_least({ 1, 6 })) {
248     common_methods.insert(common_methods.end(), {
249         { "get_surface", camera_api_get_surface },
250     });
251   }
252 
253   camera_methods.insert(camera_methods.end(), common_methods.begin(), common_methods.end());
254   register_type(
255       get_entity_internal_type_name(EntityType::CAMERA),
256       {},
257       camera_methods,
258       metamethods
259   );
260 
261   // Destination.
262   std::vector<luaL_Reg> destination_methods = {
263       { "get_starting_location_mode", destination_api_get_starting_location_mode },
264       { "set_starting_location_mode", destination_api_set_starting_location_mode },
265   };
266 
267   destination_methods.insert(destination_methods.end(), common_methods.begin(), common_methods.end());
268   register_type(
269       get_entity_internal_type_name(EntityType::DESTINATION),
270       {},
271       destination_methods,
272       metamethods
273   );
274 
275   // Teletransporter.
276   std::vector<luaL_Reg> teletransporter_methods = {
277       { "get_sound", teletransporter_api_get_sound },
278       { "set_sound", teletransporter_api_set_sound },
279       { "get_transition", teletransporter_api_get_transition },
280       { "set_transition", teletransporter_api_set_transition },
281       { "get_destination_map", teletransporter_api_get_destination_map },
282       { "set_destination_map", teletransporter_api_set_destination_map},
283       { "get_destination_name", teletransporter_api_get_destination_name },
284       { "set_destination_name", teletransporter_api_set_destination_name },
285   };
286 
287   teletransporter_methods.insert(teletransporter_methods.end(), common_methods.begin(), common_methods.end());
288   register_type(
289       get_entity_internal_type_name(EntityType::TELETRANSPORTER),
290       {},
291       teletransporter_methods,
292       metamethods
293   );
294 
295   // NPC.
296   std::vector<luaL_Reg> npc_methods = {
297       { "is_traversable", npc_api_is_traversable },
298       { "set_traversable", npc_api_set_traversable },
299   };
300 
301   npc_methods.insert(npc_methods.end(), common_methods.begin(), common_methods.end());
302   register_type(
303       get_entity_internal_type_name(EntityType::NPC),
304       {},
305       npc_methods,
306       metamethods
307   );
308 
309   // Chest.
310   std::vector<luaL_Reg> chest_methods = {
311       { "is_open", chest_api_is_open },
312       { "set_open", chest_api_set_open },
313       { "get_treasure", chest_api_get_treasure },
314       { "set_treasure", chest_api_set_treasure },
315   };
316 
317   chest_methods.insert(chest_methods.end(), common_methods.begin(), common_methods.end());
318   register_type(
319       get_entity_internal_type_name(EntityType::CHEST),
320       {},
321       chest_methods,
322       metamethods
323   );
324 
325   // Block.
326   std::vector<luaL_Reg> block_methods = {
327       { "reset", block_api_reset },
328       { "is_pushable", block_api_is_pushable },
329       { "set_pushable", block_api_set_pushable },
330       { "is_pullable", block_api_is_pullable },
331       { "set_pullable", block_api_set_pullable },
332       { "get_maximum_moves", block_api_get_maximum_moves },
333       { "set_maximum_moves", block_api_set_maximum_moves },
334   };
335   if (CurrentQuest::is_format_at_least({ 1, 6 })) {
336     block_methods.insert(block_methods.end(), {
337       { "get_max_moves", block_api_get_max_moves },
338       { "set_max_moves", block_api_set_max_moves },
339     });
340   }
341 
342   block_methods.insert(block_methods.end(), common_methods.begin(), common_methods.end());
343   register_type(
344       get_entity_internal_type_name(EntityType::BLOCK),
345       {},
346       block_methods,
347       metamethods
348   );
349 
350   // Switch.
351   std::vector<luaL_Reg> switch_methods = {
352       { "is_activated", switch_api_is_activated },
353       { "set_activated", switch_api_set_activated },
354       { "is_locked", switch_api_is_locked },
355       { "set_locked", switch_api_set_locked },
356       { "is_walkable", switch_api_is_walkable },
357   };
358 
359   switch_methods.insert(switch_methods.end(), common_methods.begin(), common_methods.end());
360   register_type(
361       get_entity_internal_type_name(EntityType::SWITCH),
362       {},
363       switch_methods,
364       metamethods
365   );
366 
367   // Stream.
368   std::vector<luaL_Reg> stream_methods = {
369       { "get_direction", stream_api_get_direction },
370       { "set_direction", stream_api_set_direction },
371       { "get_speed", stream_api_get_speed },
372       { "set_speed", stream_api_set_speed },
373       { "get_allow_movement", stream_api_get_allow_movement },
374       { "set_allow_movement", stream_api_set_allow_movement },
375       { "get_allow_attack", stream_api_get_allow_attack },
376       { "set_allow_attack", stream_api_set_allow_attack },
377       { "get_allow_item", stream_api_get_allow_item },
378       { "set_allow_item", stream_api_set_allow_item },
379   };
380 
381   stream_methods.insert(stream_methods.end(), common_methods.begin(), common_methods.end());
382   register_type(
383       get_entity_internal_type_name(EntityType::STREAM),
384       {},
385       stream_methods,
386       metamethods
387   );
388 
389   // Door.
390   std::vector<luaL_Reg> door_methods = {
391       { "is_open", door_api_is_open },
392       { "is_opening", door_api_is_opening },
393       { "is_closed", door_api_is_closed },
394       { "is_closing", door_api_is_closing },
395   };
396   if (CurrentQuest::is_format_at_least({ 1, 6 })) {
397     door_methods.insert(door_methods.end(), {
398         { "open", door_api_open },
399         { "close", door_api_close },
400         { "set_open", door_api_set_open },
401     });
402   }
403 
404   door_methods.insert(door_methods.end(), common_methods.begin(), common_methods.end());
405   register_type(
406       get_entity_internal_type_name(EntityType::DOOR),
407       {},
408       door_methods,
409       metamethods
410   );
411 
412 
413   // Stairs.
414   std::vector<luaL_Reg> stairs_methods = {
415   };
416   if (CurrentQuest::is_format_at_least({ 1, 6 })) {
417     stairs_methods.insert(stairs_methods.end(), {
418         { "get_direction", stairs_api_get_direction },
419         { "is_inner", stairs_api_is_inner },
420     });
421   }
422 
423   stairs_methods.insert(stairs_methods.end(), common_methods.begin(), common_methods.end());
424   register_type(
425       get_entity_internal_type_name(EntityType::STAIRS),
426       {},
427       stairs_methods,
428       metamethods
429   );
430 
431   // Pickable.
432   std::vector<luaL_Reg> pickable_methods = {
433       { "has_layer_independent_collisions", entity_api_has_layer_independent_collisions },
434       { "set_layer_independent_collisions", entity_api_set_layer_independent_collisions },
435       { "get_followed_entity", pickable_api_get_followed_entity },
436       { "get_falling_height", pickable_api_get_falling_height },
437       { "get_treasure", pickable_api_get_treasure },
438   };
439 
440   pickable_methods.insert(pickable_methods.end(), common_methods.begin(), common_methods.end());
441   register_type(
442       get_entity_internal_type_name(EntityType::PICKABLE),
443       {},
444       pickable_methods,
445       metamethods
446   );
447 
448   // Destructible.
449   std::vector<luaL_Reg> destructible_methods = {
450       { "get_treasure", destructible_api_get_treasure },
451       { "set_treasure", destructible_api_set_treasure },
452       { "get_destruction_sound", destructible_api_get_destruction_sound },
453       { "set_destruction_sound", destructible_api_set_destruction_sound },
454       { "get_can_be_cut", destructible_api_get_can_be_cut },
455       { "set_can_be_cut", destructible_api_set_can_be_cut },
456       { "get_can_explode", destructible_api_get_can_explode },
457       { "set_can_explode", destructible_api_set_can_explode },
458       { "get_can_regenerate", destructible_api_get_can_regenerate },
459       { "set_can_regenerate", destructible_api_set_can_regenerate },
460       { "get_damage_on_enemies", destructible_api_get_damage_on_enemies },
461       { "set_damage_on_enemies", destructible_api_set_damage_on_enemies },
462       { "get_modified_ground", destructible_api_get_modified_ground },
463   };
464   if (CurrentQuest::is_format_at_most({ 1, 5 })) {
465     destructible_methods.insert(destructible_methods.end(), {
466         // Available to all entities since 1.6.
467         { "get_weight", entity_api_get_weight },
468         { "set_weight", entity_api_set_weight },
469     });
470   }
471 
472   destructible_methods.insert(destructible_methods.end(), common_methods.begin(), common_methods.end());
473   register_type(
474       get_entity_internal_type_name(EntityType::DESTRUCTIBLE),
475       {},
476       destructible_methods,
477       metamethods
478   );
479 
480   // Carried object.
481   std::vector<luaL_Reg> carried_object_methods = {
482   };
483   if (CurrentQuest::is_format_at_least({ 1, 6 })) {
484     carried_object_methods.insert(carried_object_methods.end(), {
485         { "get_carrier", carried_object_api_get_carrier },
486         { "get_destruction_sound", carried_object_api_get_destruction_sound },
487         { "set_destruction_sound", carried_object_api_set_destruction_sound },
488         { "get_damage_on_enemies", carried_object_api_get_damage_on_enemies },
489         { "set_damage_on_enemies", carried_object_api_set_damage_on_enemies },
490     });
491   }
492 
493   carried_object_methods.insert(carried_object_methods.end(), common_methods.begin(), common_methods.end());
494   register_type(
495       get_entity_internal_type_name(EntityType::CARRIED_OBJECT),
496       {},
497       carried_object_methods,
498       metamethods
499   );
500 
501   // Dynamic tile.
502   std::vector<luaL_Reg> dynamic_tile_methods = {
503       { "get_pattern_id", dynamic_tile_api_get_pattern_id },
504       { "get_modified_ground", dynamic_tile_api_get_modified_ground },
505       { "get_tileset", dynamic_tile_api_get_tileset },
506       { "set_tileset", dynamic_tile_api_set_tileset },
507   };
508 
509   dynamic_tile_methods.insert(dynamic_tile_methods.end(), common_methods.begin(), common_methods.end());
510   register_type(
511       get_entity_internal_type_name(EntityType::DYNAMIC_TILE),
512       {},
513       dynamic_tile_methods,
514       metamethods
515   );
516 
517   // Enemy.
518   std::vector<luaL_Reg> enemy_methods = {
519       { "get_breed", enemy_api_get_breed },
520       { "get_life", enemy_api_get_life },
521       { "set_life", enemy_api_set_life },
522       { "add_life", enemy_api_add_life },
523       { "remove_life", enemy_api_remove_life },
524       { "get_damage", enemy_api_get_damage },
525       { "set_damage", enemy_api_set_damage },
526       { "is_pushed_back_when_hurt", enemy_api_is_pushed_back_when_hurt },
527       { "set_pushed_back_when_hurt", enemy_api_set_pushed_back_when_hurt },
528       { "get_push_hero_on_sword", enemy_api_get_push_hero_on_sword },
529       { "set_push_hero_on_sword", enemy_api_set_push_hero_on_sword },
530       { "get_can_hurt_hero_running", enemy_api_get_can_hurt_hero_running },
531       { "set_can_hurt_hero_running", enemy_api_set_can_hurt_hero_running },
532       { "get_hurt_style", enemy_api_get_hurt_style },
533       { "set_hurt_style", enemy_api_set_hurt_style },
534       { "get_can_attack", enemy_api_get_can_attack },
535       { "set_can_attack", enemy_api_set_can_attack },
536       { "get_minimum_shield_needed", enemy_api_get_minimum_shield_needed },
537       { "set_minimum_shield_needed", enemy_api_set_minimum_shield_needed },
538       { "get_attack_consequence", enemy_api_get_attack_consequence },
539       { "set_attack_consequence", enemy_api_set_attack_consequence },
540       { "get_attack_consequence_sprite", enemy_api_get_attack_consequence_sprite },
541       { "set_attack_consequence_sprite", enemy_api_set_attack_consequence_sprite },
542       { "set_default_attack_consequences", enemy_api_set_default_attack_consequences },
543       { "set_default_attack_consequences_sprite", enemy_api_set_default_attack_consequences_sprite },
544       { "set_invincible", enemy_api_set_invincible },
545       { "set_invincible_sprite", enemy_api_set_invincible_sprite },
546       { "has_layer_independent_collisions", entity_api_has_layer_independent_collisions },
547       { "set_layer_independent_collisions", entity_api_set_layer_independent_collisions },
548       { "get_treasure", enemy_api_get_treasure },
549       { "set_treasure", enemy_api_set_treasure },
550       { "is_traversable", enemy_api_is_traversable },
551       { "set_traversable", enemy_api_set_traversable },
552       { "get_obstacle_behavior", enemy_api_get_obstacle_behavior },
553       { "set_obstacle_behavior", enemy_api_set_obstacle_behavior },
554       { "restart", enemy_api_restart },
555       { "hurt", enemy_api_hurt },
556       { "immobilize", enemy_api_immobilize },
557       { "create_enemy", enemy_api_create_enemy },
558   };
559   if (CurrentQuest::is_format_at_most({ 1, 5 })) {
560     enemy_methods.insert(enemy_methods.end(), {
561         // Available to all entities since 1.6.
562         { "set_size", entity_api_set_size },
563         { "set_origin", entity_api_set_origin },
564         { "create_sprite", entity_api_create_sprite },
565         { "remove_sprite", entity_api_remove_sprite },
566     });
567   }
568   if (CurrentQuest::is_format_at_least({ 1, 6 })) {
569     enemy_methods.insert(enemy_methods.end(), {
570         { "get_dying_sprite_id", enemy_api_get_dying_sprite_id },
571         { "set_dying_sprite_id", enemy_api_set_dying_sprite_id },
572         { "is_immobilized", enemy_api_is_immobilized },
573         { "get_attacking_collision_mode", enemy_api_get_attacking_collision_mode },
574         { "set_attacking_collision_mode", enemy_api_set_attacking_collision_mode },
575     });
576   }
577 
578   enemy_methods.insert(enemy_methods.end(), common_methods.begin(), common_methods.end());
579   register_type(
580       get_entity_internal_type_name(EntityType::ENEMY),
581       {},
582       enemy_methods,
583       metamethods
584   );
585 
586   // Custom entity.
587   std::vector<luaL_Reg> custom_entity_methods = {
588       { "get_model", custom_entity_api_get_model },
589       { "set_size", entity_api_set_size },
590       { "set_origin", entity_api_set_origin },
591       { "get_direction", custom_entity_api_get_direction },
592       { "set_direction", custom_entity_api_set_direction },
593       { "set_traversable_by", custom_entity_api_set_traversable_by },
594       { "set_can_traverse", custom_entity_api_set_can_traverse },
595       { "can_traverse_ground", custom_entity_api_can_traverse_ground },
596       { "set_can_traverse_ground", custom_entity_api_set_can_traverse_ground },
597       { "add_collision_test", custom_entity_api_add_collision_test },
598       { "clear_collision_tests", custom_entity_api_clear_collision_tests },
599       { "has_layer_independent_collisions", entity_api_has_layer_independent_collisions },
600       { "set_layer_independent_collisions", entity_api_set_layer_independent_collisions },
601       { "get_modified_ground", custom_entity_api_get_modified_ground },
602       { "set_modified_ground", custom_entity_api_set_modified_ground },
603   };
604   if (CurrentQuest::is_format_at_most({ 1, 5 })) {
605     // Available to all entities since 1.6.
606     custom_entity_methods.insert(custom_entity_methods.end(), {
607         { "set_size", entity_api_set_size },
608         { "set_origin", entity_api_set_origin },
609         { "is_drawn_in_y_order", entity_api_is_drawn_in_y_order },
610         { "set_drawn_in_y_order", entity_api_set_drawn_in_y_order },
611         { "create_sprite", entity_api_create_sprite },
612         { "remove_sprite", entity_api_remove_sprite },
613     });
614   }
615   if (CurrentQuest::is_format_at_least({ 1, 6 })) {
616     custom_entity_methods.insert(custom_entity_methods.end(), {
617         { "is_tiled", custom_entity_api_is_tiled },
618         { "set_tiled", custom_entity_api_set_tiled },
619         { "get_follow_streams", custom_entity_api_get_follow_streams },
620         { "set_follow_streams", custom_entity_api_set_follow_streams },
621     });
622   }
623 
624   custom_entity_methods.insert(custom_entity_methods.end(), common_methods.begin(), common_methods.end());
625   register_type(
626       get_entity_internal_type_name(EntityType::CUSTOM),
627       {},
628       custom_entity_methods,
629       metamethods
630   );
631 
632   // Also register all other types of entities that have no specific methods.
633   register_type(get_entity_internal_type_name(EntityType::TILE), {}, common_methods, metamethods);
634   register_type(get_entity_internal_type_name(EntityType::JUMPER), {}, common_methods, metamethods);
635   register_type(get_entity_internal_type_name(EntityType::SENSOR), {}, common_methods, metamethods);
636   register_type(get_entity_internal_type_name(EntityType::SEPARATOR), {}, common_methods, metamethods);
637   register_type(get_entity_internal_type_name(EntityType::WALL), {}, common_methods, metamethods);
638   register_type(get_entity_internal_type_name(EntityType::CRYSTAL), {}, common_methods, metamethods);
639   register_type(get_entity_internal_type_name(EntityType::CRYSTAL_BLOCK), {}, common_methods, metamethods);
640   register_type(get_entity_internal_type_name(EntityType::SHOP_TREASURE), {}, common_methods, metamethods);
641   register_type(get_entity_internal_type_name(EntityType::BOMB), {}, common_methods, metamethods);
642   register_type(get_entity_internal_type_name(EntityType::EXPLOSION), {}, common_methods, metamethods);
643   register_type(get_entity_internal_type_name(EntityType::FIRE), {}, common_methods, metamethods);
644   register_type(get_entity_internal_type_name(EntityType::ARROW), {}, common_methods, metamethods);
645   register_type(get_entity_internal_type_name(EntityType::HOOKSHOT), {}, common_methods, metamethods);
646   register_type(get_entity_internal_type_name(EntityType::BOOMERANG), {}, common_methods, metamethods);
647 }
648 
649 /**
650  * \brief Returns whether a value is a userdata of type entity.
651  * \param l A Lua context.
652  * \param index An index in the stack.
653  * \return true if the value at this index is a entity.
654  */
is_entity(lua_State * l,int index)655 bool LuaContext::is_entity(lua_State* l, int index) {
656 
657   // We could return is_hero() || is_tile() || is_dynamic_tile() || ...
658   // but this would be tedious, costly and error prone.
659 
660   void* udata = lua_touserdata(l, index);
661   if (udata == nullptr) {
662     // This is not a userdata.
663     return false;
664   }
665 
666   if (!lua_getmetatable(l, index)) {
667     // The userdata has no metatable.
668     return false;
669   }
670 
671   // Get the name of the Solarus type from this userdata.
672   lua_pushstring(l, "__solarus_type");
673   lua_rawget(l, -2);
674   if (!lua_isstring(l, -1)) {
675     // This is probably a userdata from some library other than Solarus.
676     lua_pop(l, 2);
677     return false;
678   }
679 
680   // Check if the type name is one of the entity type names.
681   const std::string& type_name = lua_tostring(l, -1);
682   lua_pop(l, 2);
683 
684   return get_entity_internal_type_names_set().find(type_name) != get_entity_internal_type_names_set().end();
685 }
686 
687 /**
688  * \brief Checks that the userdata at the specified index of the stack is an
689  * entity and returns it.
690  * \param l A Lua context.
691  * \param index An index in the stack.
692  * \return The entity.
693  */
check_entity(lua_State * l,int index)694 EntityPtr LuaContext::check_entity(lua_State* l, int index) {
695 
696   if (is_entity(l, index)) {
697     const ExportableToLuaPtr& userdata = *(static_cast<ExportableToLuaPtr*>(
698       lua_touserdata(l, index)
699     ));
700     return std::static_pointer_cast<Entity>(userdata);
701   }
702   else {
703     LuaTools::type_error(l, index, "entity");
704   }
705 }
706 
707 /**
708  * \brief Pushes an entity userdata onto the stack.
709  *
710  * If the entity or its map does not exist anymore, pushes nil.
711  *
712  * \param l A Lua context.
713  * \param entity An entity.
714  */
push_entity(lua_State * l,Entity & entity)715 void LuaContext::push_entity(lua_State* l, Entity& entity) {
716 
717   push_userdata(l, entity);
718 }
719 
720 /**
721  * \brief Pushes a list of entities as an iterator onto the stack.
722  *
723  * The iterator is pushed onto the stack as one value of type function.
724  *
725  * \param l A Lua context.
726  * \param entity A list of entities. The iterator preserves their order.
727  */
push_entity_iterator(lua_State * l,const EntityVector & entities)728 void LuaContext::push_entity_iterator(lua_State* l, const EntityVector& entities) {
729 
730   // Create a Lua table with the list of entities, preserving their order.
731   int i = 0;
732   lua_newtable(l);
733   for (const EntityPtr& entity: entities) {
734     ++i;
735     lua_pushinteger(l, i);
736     push_entity(l, *entity);
737     lua_rawset(l, -3);
738   }
739 
740   lua_pushinteger(l, entities.size());
741   lua_pushinteger(l, 1);
742   // 3 upvalues: entities table, size, current index.
743 
744   lua_pushcclosure(l, l_entity_iterator_next, 3);
745 }
746 
747 /**
748  * \brief Returns the Lua metatable name corresponding to a type of map entity.
749  * \param entity_type A type of map entity.
750  * \return The corresponding Lua metatable name, e.g. "sol.enemy".
751  */
get_entity_internal_type_name(EntityType entity_type)752 const std::string& LuaContext::get_entity_internal_type_name(
753     EntityType entity_type) {
754 
755   const std::map<EntityType, std::string>& names = get_entity_internal_type_names();
756   const auto& it = names.find(entity_type);
757   SOLARUS_ASSERT(it != names.end(), "Missing entity internal type name");
758 
759   return it->second;
760 }
761 
762 /**
763  * \brief Closure of an iterator over a list of sprites and their names.
764  *
765  * This closure expects 3 upvalues in this order:
766  * - An array of { name, sprite } pairs.
767  * - The size of the array (for performance).
768  * - The current index in the array.
769  *
770  * \param l The Lua context that is calling this function.
771  * \return Number of values to return to Lua.
772  */
l_named_sprite_iterator_next(lua_State * l)773 int LuaContext::l_named_sprite_iterator_next(lua_State* l) {
774 
775   return state_boundary_handle(l, [&] {
776 
777     // Get upvalues.
778     const int table_index = lua_upvalueindex(1);
779     const int size = lua_tointeger(l, lua_upvalueindex(2));
780     int index = lua_tointeger(l, lua_upvalueindex(3));
781 
782     if (index > size) {
783       // Finished.
784       return 0;
785     }
786 
787     // Get the next value.
788     lua_rawgeti(l, table_index, index);   // pair
789     lua_rawgeti(l, -1, 1);                // pair name
790     lua_rawgeti(l, -2, 2);                // pair name sprite
791 
792     // Increment index.
793     ++index;
794     lua_pushinteger(l, index);
795     lua_replace(l, lua_upvalueindex(3));
796 
797     return 2;
798   });
799 }
800 
801 /**
802  * \brief Pushes a list of sprites and their names as an iterator onto the stack.
803  *
804  * The iterator is pushed onto the stack as one value of type function.
805  *
806  * \param l A Lua context.
807  * \param sprites A list of sprites and their names. The iterator preserves their order.
808  */
push_named_sprite_iterator(lua_State * l,const std::vector<Entity::NamedSprite> & sprites)809 void LuaContext::push_named_sprite_iterator(
810     lua_State* l,
811     const std::vector<Entity::NamedSprite>& sprites
812 ) {
813   // Create a Lua table with the list of name-sprite pairs, preserving their order.
814   int i = 0;
815   lua_newtable(l);
816                                                  // sprites
817   for (const Entity::NamedSprite& named_sprite: sprites) {
818     if (named_sprite.removed) {
819       continue;
820     }
821     ++i;
822     lua_newtable(l);                             // sprites pair
823     push_string(l, named_sprite.name);           // sprites pair name
824     lua_rawseti(l, -2, 1);                       // sprites pair
825     push_sprite(l, *named_sprite.sprite);        // sprites pair sprite
826     lua_rawseti(l, -2, 2);                       // sprites pair
827 
828     lua_rawseti(l, -2, i);                       // sprites
829   }
830 
831   lua_pushinteger(l, i);
832   lua_pushinteger(l, 1);
833   // 3 upvalues: sprites table, size, current index.
834 
835   lua_pushcclosure(l, l_named_sprite_iterator_next, 3);
836 }
837 
838 /**
839  * \brief Calls the draw override function of an entity.
840  * \param draw_override The draw override function.
841  * \param entity The entity to draw.
842  * \param camera The camera where to draw the entity.
843  */
do_entity_draw_override_function(const ScopedLuaRef & draw_override,Entity & entity,Camera & camera)844 void LuaContext::do_entity_draw_override_function(
845     const ScopedLuaRef& draw_override,
846     Entity& entity,
847     Camera& camera
848 ) {
849   push_ref(current_l, draw_override);
850   push_entity(current_l, entity);
851   push_camera(current_l, camera);
852   call_function(2, 0, "entity draw override");
853 }
854 
855 /**
856  * \brief Implementation of entity:get_type().
857  * \param l The Lua context that is calling this function.
858  * \return Number of values to return to Lua.
859  */
entity_api_get_type(lua_State * l)860 int LuaContext::entity_api_get_type(lua_State* l) {
861 
862   return state_boundary_handle(l, [&] {
863     const Entity& entity = *check_entity(l, 1);
864 
865     const std::string& type_name = enum_to_name(entity.get_type());
866     push_string(l, type_name);
867     return 1;
868   });
869 }
870 
871 /**
872  * \brief Implementation of entity:get_map().
873  * \param l The Lua context that is calling this function.
874  * \return Number of values to return to Lua.
875  */
entity_api_get_map(lua_State * l)876 int LuaContext::entity_api_get_map(lua_State* l) {
877 
878   return state_boundary_handle(l, [&] {
879     Entity& entity = *check_entity(l, 1);
880 
881     push_map(l, entity.get_map());
882     return 1;
883   });
884 }
885 
886 /**
887  * \brief Implementation of entity:get_game().
888  * \param l The Lua context that is calling this function.
889  * \return Number of values to return to Lua.
890  */
entity_api_get_game(lua_State * l)891 int LuaContext::entity_api_get_game(lua_State* l) {
892 
893   return state_boundary_handle(l, [&] {
894     Entity& entity = *check_entity(l, 1);
895 
896     push_game(l, entity.get_game().get_savegame());
897     return 1;
898   });
899 }
900 
901 /**
902  * \brief Implementation of entity:get_name().
903  * \param l The Lua context that is calling this function.
904  * \return Number of values to return to Lua.
905  */
entity_api_get_name(lua_State * l)906 int LuaContext::entity_api_get_name(lua_State* l) {
907 
908   return state_boundary_handle(l, [&] {
909     const Entity& entity = *check_entity(l, 1);
910 
911     const std::string& name = entity.get_name();
912     if (name.empty()) {
913       lua_pushnil(l);
914     }
915     else {
916       push_string(l, name);
917     }
918     return 1;
919   });
920 }
921 
922 /**
923  * \brief Implementation of entity:exists().
924  * \param l The Lua context that is calling this function.
925  * \return Number of values to return to Lua.
926  */
entity_api_exists(lua_State * l)927 int LuaContext::entity_api_exists(lua_State* l) {
928 
929   return state_boundary_handle(l, [&] {
930     const Entity& entity = *check_entity(l, 1);
931 
932     lua_pushboolean(l, !entity.is_being_removed());
933     return 1;
934   });
935 }
936 
937 /**
938  * \brief Implementation of entity:remove().
939  * \param l The Lua context that is calling this function.
940  * \return Number of values to return to Lua.
941  */
entity_api_remove(lua_State * l)942 int LuaContext::entity_api_remove(lua_State* l) {
943 
944   return state_boundary_handle(l, [&] {
945     Entity& entity = *check_entity(l, 1);
946 
947     entity.remove_from_map();
948 
949     return 0;
950   });
951 }
952 
953 /**
954  * \brief Implementation of entity:is_enabled().
955  * \param l The Lua context that is calling this function.
956  * \return Number of values to return to Lua.
957  */
entity_api_is_enabled(lua_State * l)958 int LuaContext::entity_api_is_enabled(lua_State* l) {
959 
960   return state_boundary_handle(l, [&] {
961     const Entity& entity = *check_entity(l, 1);
962 
963     lua_pushboolean(l, entity.is_enabled());
964     return 1;
965   });
966 }
967 
968 /**
969  * \brief Implementation of entity:set_enabled().
970  * \param l The Lua context that is calling this function.
971  * \return Number of values to return to Lua.
972  */
entity_api_set_enabled(lua_State * l)973 int LuaContext::entity_api_set_enabled(lua_State* l) {
974 
975   return state_boundary_handle(l, [&] {
976     Entity& entity = *check_entity(l, 1);
977     bool enabled = LuaTools::opt_boolean(l, 2, true);
978 
979     entity.set_enabled(enabled);
980 
981     return 0;
982   });
983 }
984 
985 /**
986  * \brief Implementation of entity:get_size().
987  * \param l The Lua context that is calling this function.
988  * \return Number of values to return to Lua.
989  */
entity_api_get_size(lua_State * l)990 int LuaContext::entity_api_get_size(lua_State* l) {
991 
992   return state_boundary_handle(l, [&] {
993     const Entity& entity = *check_entity(l, 1);
994 
995     lua_pushinteger(l, entity.get_width());
996     lua_pushinteger(l, entity.get_height());
997     return 2;
998   });
999 }
1000 
1001 /**
1002  * \brief Implementation of entity:set_size().
1003  * \param l The Lua context that is calling this function.
1004  * \return Number of values to return to Lua.
1005  */
entity_api_set_size(lua_State * l)1006 int LuaContext::entity_api_set_size(lua_State* l) {
1007 
1008   return state_boundary_handle(l, [&] {
1009     Entity& entity = *check_entity(l, 1);
1010     int width = LuaTools::check_int(l, 2);
1011     int height = LuaTools::check_int(l, 3);
1012 
1013     if (width <= 0) {
1014       std::ostringstream oss;
1015       oss << "Invalid width: " << width << ": should be positive";
1016       LuaTools::arg_error(l, 2, oss.str());
1017     }
1018     if (height <= 0) {
1019       std::ostringstream oss;
1020       oss << "Invalid height: " << height << ": should be positive";
1021       LuaTools::arg_error(l, 3, oss.str());
1022     }
1023 
1024     entity.set_size(width, height);
1025     entity.notify_position_changed();
1026 
1027     return 0;
1028   });
1029 }
1030 
1031 /**
1032  * \brief Implementation of entity:get_origin().
1033  * \param l The Lua context that is calling this function.
1034  * \return Number of values to return to Lua.
1035  */
entity_api_get_origin(lua_State * l)1036 int LuaContext::entity_api_get_origin(lua_State* l) {
1037 
1038   return state_boundary_handle(l, [&] {
1039     const Entity& entity = *check_entity(l, 1);
1040 
1041     const Point& origin = entity.get_origin();
1042 
1043     lua_pushinteger(l, origin.x);
1044     lua_pushinteger(l, origin.y);
1045     return 2;
1046   });
1047 }
1048 
1049 /**
1050  * \brief Implementation of enemy:set_origin().
1051  * \param l The Lua context that is calling this function.
1052  * \return Number of values to return to Lua.
1053  */
entity_api_set_origin(lua_State * l)1054 int LuaContext::entity_api_set_origin(lua_State* l) {
1055 
1056   return state_boundary_handle(l, [&] {
1057     Entity& entity = *check_entity(l, 1);
1058     int x = LuaTools::check_int(l, 2);
1059     int y = LuaTools::check_int(l, 3);
1060 
1061     entity.set_origin(x, y);
1062     entity.notify_position_changed();
1063 
1064     return 0;
1065   });
1066 }
1067 
1068 /**
1069  * \brief Implementation of entity:get_position().
1070  * \param l The Lua context that is calling this function.
1071  * \return Number of values to return to Lua.
1072  */
entity_api_get_position(lua_State * l)1073 int LuaContext::entity_api_get_position(lua_State* l) {
1074   return state_boundary_handle(l, [&] {
1075     const Entity& entity = *check_entity(l, 1);
1076 
1077     lua_pushinteger(l, entity.get_x());
1078     lua_pushinteger(l, entity.get_y());
1079     lua_pushinteger(l, entity.get_layer());
1080     return 3;
1081   });
1082 }
1083 
1084 /**
1085  * \brief Implementation of entity:set_position().
1086  * \param l The Lua context that is calling this function.
1087  * \return Number of values to return to Lua.
1088  */
entity_api_set_position(lua_State * l)1089 int LuaContext::entity_api_set_position(lua_State* l) {
1090 
1091   return state_boundary_handle(l, [&] {
1092     Entity& entity = *check_entity(l, 1);
1093     int x = LuaTools::check_int(l, 2);
1094     int y = LuaTools::check_int(l, 3);
1095     int layer = LuaTools::opt_layer(l, 4, entity.get_map(), entity.get_layer());
1096 
1097     Entities& entities = entity.get_map().get_entities();
1098     entity.set_xy(x, y);
1099     entities.set_entity_layer(entity, layer);
1100     entity.notify_position_changed();
1101 
1102     return 0;
1103   });
1104 }
1105 
1106 /**
1107  * \brief Implementation of entity:get_center_position().
1108  * \param l The Lua context that is calling this function.
1109  * \return Number of values to return to Lua.
1110  */
entity_api_get_center_position(lua_State * l)1111 int LuaContext::entity_api_get_center_position(lua_State* l) {
1112 
1113   return state_boundary_handle(l, [&] {
1114     const Entity& entity = *check_entity(l, 1);
1115 
1116     const Point& center_point = entity.get_center_point();
1117     lua_pushinteger(l, center_point.x);
1118     lua_pushinteger(l, center_point.y);
1119     lua_pushinteger(l, entity.get_layer());
1120     return 3;
1121   });
1122 }
1123 
1124 /**
1125  * \brief Implementation of entity:get_facing_position().
1126  * \param l The Lua context that is calling this function.
1127  * \return Number of values to return to Lua.
1128  */
entity_api_get_facing_position(lua_State * l)1129 int LuaContext::entity_api_get_facing_position(lua_State* l) {
1130 
1131   return state_boundary_handle(l, [&] {
1132     const Entity& entity = *check_entity(l, 1);
1133 
1134     const Point& facing_point = entity.get_facing_point();
1135     lua_pushinteger(l, facing_point.x);
1136     lua_pushinteger(l, facing_point.y);
1137     lua_pushinteger(l, entity.get_layer());
1138     return 3;
1139   });
1140 }
1141 
1142 /**
1143  * \brief Implementation of entity:get_facing_entity().
1144  * \param l The Lua context that is calling this function.
1145  * \return Number of values to return to Lua.
1146  */
entity_api_get_facing_entity(lua_State * l)1147 int LuaContext::entity_api_get_facing_entity(lua_State* l) {
1148 
1149   return state_boundary_handle(l, [&] {
1150     Entity& entity = *check_entity(l, 1);
1151 
1152     Entity* facing_entity = entity.get_facing_entity();
1153     if (facing_entity == nullptr) {
1154       lua_pushnil(l);
1155     }
1156     else {
1157       push_entity(l, *facing_entity);
1158     }
1159     return 1;
1160   });
1161 }
1162 
1163 /**
1164  * \brief Implementation of entity:get_ground_position().
1165  * \param l The Lua context that is calling this function.
1166  * \return Number of values to return to Lua.
1167  */
entity_api_get_ground_position(lua_State * l)1168 int LuaContext::entity_api_get_ground_position(lua_State* l) {
1169 
1170   return state_boundary_handle(l, [&] {
1171     const Entity& entity = *check_entity(l, 1);
1172 
1173     const Point& ground_point = entity.get_ground_point();
1174     lua_pushinteger(l, ground_point.x);
1175     lua_pushinteger(l, ground_point.y);
1176     lua_pushinteger(l, entity.get_layer());
1177     return 3;
1178   });
1179 }
1180 
1181 /**
1182  * \brief Implementation of entity:get_ground_below().
1183  * \param l The Lua context that is calling this function.
1184  * \return Number of values to return to Lua.
1185  */
entity_api_get_ground_below(lua_State * l)1186 int LuaContext::entity_api_get_ground_below(lua_State* l) {
1187 
1188   return state_boundary_handle(l, [&] {
1189     const Entity& entity = *check_entity(l, 1);
1190 
1191     Ground ground = entity.get_ground_below();
1192 
1193     push_string(l, enum_to_name(ground));
1194     return 1;
1195   });
1196 }
1197 
1198 /**
1199  * \brief Implementation of entity:get_bounding_box().
1200  * \param l The Lua context that is calling this function.
1201  * \return Number of values to return to Lua.
1202  */
entity_api_get_bounding_box(lua_State * l)1203 int LuaContext::entity_api_get_bounding_box(lua_State* l) {
1204 
1205   return state_boundary_handle(l, [&] {
1206     const Entity& entity = *check_entity(l, 1);
1207 
1208     const Rectangle& bounding_box = entity.get_bounding_box();
1209     lua_pushinteger(l, bounding_box.get_x());
1210     lua_pushinteger(l, bounding_box.get_y());
1211     lua_pushinteger(l, bounding_box.get_width());
1212     lua_pushinteger(l, bounding_box.get_height());
1213     return 4;
1214   });
1215 }
1216 
1217 /**
1218  * \brief Implementation of entity:get_max_bounding_box().
1219  * \param l The Lua context that is calling this function.
1220  * \return Number of values to return to Lua.
1221  */
entity_api_get_max_bounding_box(lua_State * l)1222 int LuaContext::entity_api_get_max_bounding_box(lua_State* l) {
1223 
1224   return state_boundary_handle(l, [&] {
1225     const Entity& entity = *check_entity(l, 1);
1226 
1227     const Rectangle& max_bounding_box = entity.get_max_bounding_box();
1228     lua_pushinteger(l, max_bounding_box.get_x());
1229     lua_pushinteger(l, max_bounding_box.get_y());
1230     lua_pushinteger(l, max_bounding_box.get_width());
1231     lua_pushinteger(l, max_bounding_box.get_height());
1232     return 4;
1233   });
1234 }
1235 
1236 /**
1237  * \brief Implementation of entity:get_layer().
1238  * \param l The Lua context that is calling this function.
1239  * \return Number of values to return to Lua.
1240  */
entity_api_get_layer(lua_State * l)1241 int LuaContext::entity_api_get_layer(lua_State* l) {
1242 
1243   return state_boundary_handle(l, [&] {
1244     const Entity& entity = *check_entity(l, 1);
1245 
1246     lua_pushinteger(l, entity.get_layer());
1247     return 1;
1248   });
1249 }
1250 
1251 /**
1252  * \brief Implementation of entity:set_layer().
1253  * \param l The Lua context that is calling this function.
1254  * \return Number of values to return to Lua.
1255  */
entity_api_set_layer(lua_State * l)1256 int LuaContext::entity_api_set_layer(lua_State* l) {
1257 
1258   return state_boundary_handle(l, [&] {
1259     Entity& entity = *check_entity(l, 1);
1260     int layer = LuaTools::check_layer(l, 2, entity.get_map());
1261 
1262     Entities& entities = entity.get_map().get_entities();
1263     entities.set_entity_layer(entity, layer);
1264     entity.notify_position_changed();
1265 
1266     return 0;
1267   });
1268 }
1269 
1270 /**
1271  * \brief Implementation of entity:overlaps().
1272  * \param l The Lua context that is calling this function.
1273  * \return Number of values to return to Lua.
1274  */
entity_api_overlaps(lua_State * l)1275 int LuaContext::entity_api_overlaps(lua_State* l) {
1276 
1277   return state_boundary_handle(l, [&] {
1278     Entity& entity = *check_entity(l, 1);
1279 
1280     bool overlaps = false;
1281     if (is_entity(l, 2)) {
1282       Entity& other_entity = *check_entity(l, 2);
1283       std::string collision_mode_name = LuaTools::opt_string(l, 3, "overlapping");
1284       SpritePtr entity_sprite;
1285       SpritePtr other_entity_sprite;
1286 
1287       CollisionMode collision_mode = CollisionMode::COLLISION_NONE;
1288       if (collision_mode_name == "overlapping") {
1289         collision_mode = CollisionMode::COLLISION_OVERLAPPING;
1290       }
1291       else if (collision_mode_name == "containing") {
1292         collision_mode = CollisionMode::COLLISION_CONTAINING;
1293       }
1294       else if (collision_mode_name == "origin") {
1295         collision_mode = CollisionMode::COLLISION_ORIGIN;
1296       }
1297       else if (collision_mode_name == "facing") {
1298         collision_mode = CollisionMode::COLLISION_FACING;
1299       }
1300       else if (collision_mode_name == "touching") {
1301         collision_mode = CollisionMode::COLLISION_TOUCHING;
1302       }
1303       else if (collision_mode_name == "center") {
1304         collision_mode = CollisionMode::COLLISION_CENTER;
1305       }
1306       else if (collision_mode_name == "sprite") {
1307         collision_mode = CollisionMode::COLLISION_SPRITE;
1308         if (!lua_isnoneornil(l, 4)) {
1309           entity_sprite = check_sprite(l, 4);
1310         }
1311         if (!lua_isnoneornil(l, 5)) {
1312           other_entity_sprite = check_sprite(l, 5);
1313         }
1314       }
1315       else {
1316         LuaTools::arg_error(l, 3,
1317             std::string("Invalid name '") + collision_mode_name + "'"
1318         );
1319       }
1320 
1321       overlaps = entity.test_collision(other_entity, collision_mode, entity_sprite, other_entity_sprite);
1322     }
1323     else if (lua_isnumber(l, 2)) {
1324       int x = LuaTools::check_int(l, 2);
1325       int y = LuaTools::check_int(l, 3);
1326       int width = LuaTools::opt_int(l, 4, 1);
1327       int height = LuaTools::opt_int(l, 5, 1);
1328       overlaps = entity.overlaps(Rectangle(x, y, width, height));
1329     }
1330     else {
1331       LuaTools::type_error(l, 2, "entity or integer");
1332     }
1333 
1334     lua_pushboolean(l, overlaps);
1335     return 1;
1336   });
1337 }
1338 
1339 /**
1340  * \brief Implementation of entity:snap_to_grid().
1341  * \param l The Lua context that is calling this function.
1342  * \return Number of values to return to Lua.
1343  */
entity_api_snap_to_grid(lua_State * l)1344 int LuaContext::entity_api_snap_to_grid(lua_State* l) {
1345 
1346   return state_boundary_handle(l, [&] {
1347     Entity& entity = *check_entity(l, 1);
1348 
1349     entity.set_aligned_to_grid();
1350 
1351     return 0;
1352   });
1353 }
1354 
1355 /**
1356  * \brief Implementation of entity:get_distance().
1357  * \param l The Lua context that is calling this function.
1358  * \return Number of values to return to Lua.
1359  */
entity_api_get_distance(lua_State * l)1360 int LuaContext::entity_api_get_distance(lua_State* l) {
1361 
1362   return state_boundary_handle(l, [&] {
1363     const Entity& entity = *check_entity(l, 1);
1364     int distance;
1365     if (lua_gettop(l) >= 3) {
1366       int x = LuaTools::check_number(l, 2);
1367       int y = LuaTools::check_number(l, 3);
1368       distance = entity.get_distance(x, y);
1369     }
1370     else {
1371       const Entity& other_entity = *check_entity(l, 2);
1372       distance = entity.get_distance(other_entity);
1373     }
1374 
1375     lua_pushinteger(l, distance);
1376     return 1;
1377   });
1378 }
1379 
1380 /**
1381  * \brief Implementation of entity:get_angle().
1382  * \param l The Lua context that is calling this function.
1383  * \return Number of values to return to Lua.
1384  */
entity_api_get_angle(lua_State * l)1385 int LuaContext::entity_api_get_angle(lua_State* l) {
1386 
1387   return state_boundary_handle(l, [&] {
1388     const Entity& entity = *check_entity(l, 1);
1389     double angle;
1390     if (lua_gettop(l) >= 3) {
1391       int x = LuaTools::check_number(l, 2);
1392       int y = LuaTools::check_number(l, 3);
1393       angle = entity.get_angle(x, y);
1394     }
1395     else {
1396       const Entity& other_entity = *check_entity(l, 2);
1397       angle = entity.get_angle(other_entity);
1398     }
1399 
1400     lua_pushnumber(l, angle);
1401     return 1;
1402   });
1403 }
1404 
1405 /**
1406  * \brief Implementation of entity:get_direction4_to().
1407  * \param l The Lua context that is calling this function.
1408  * \return Number of values to return to Lua.
1409  */
entity_api_get_direction4_to(lua_State * l)1410 int LuaContext::entity_api_get_direction4_to(lua_State* l) {
1411 
1412   return state_boundary_handle(l, [&] {
1413     const Entity& entity = *check_entity(l, 1);
1414     double angle;
1415     if (lua_gettop(l) >= 3) {
1416       int x = LuaTools::check_number(l, 2);
1417       int y = LuaTools::check_number(l, 3);
1418       angle = entity.get_angle(x, y);
1419     }
1420     else {
1421       const Entity& other_entity = *check_entity(l, 2);
1422       angle = entity.get_angle(other_entity);
1423     }
1424 
1425     // Convert from radians.
1426     int direction4 = (angle + Geometry::PI_OVER_4) / Geometry::PI_OVER_2;
1427 
1428     // Normalize.
1429     direction4 = (direction4 + 4) % 4;
1430 
1431     lua_pushnumber(l, direction4);
1432     return 1;
1433   });
1434 }
1435 
1436 /**
1437  * \brief Implementation of entity:get_direction8_to().
1438  * \param l The Lua context that is calling this function.
1439  * \return Number of values to return to Lua.
1440  */
entity_api_get_direction8_to(lua_State * l)1441 int LuaContext::entity_api_get_direction8_to(lua_State* l) {
1442 
1443   return state_boundary_handle(l, [&] {
1444     const Entity& entity = *check_entity(l, 1);
1445     double angle;
1446     if (lua_gettop(l) >= 3) {
1447       int x = LuaTools::check_number(l, 2);
1448       int y = LuaTools::check_number(l, 3);
1449       angle = entity.get_angle(x, y);
1450     }
1451     else {
1452       const Entity& other_entity = *check_entity(l, 2);
1453       angle = entity.get_angle(other_entity);
1454     }
1455 
1456     // Convert from radians.
1457     int direction8 = (angle + Geometry::PI_OVER_4 / 2) / Geometry::PI_OVER_4;
1458 
1459     // Normalize.
1460     direction8 = (direction8 + 8) % 8;
1461 
1462     lua_pushnumber(l, direction8);
1463     return 1;
1464   });
1465 }
1466 
1467 /**
1468  * \brief Implementation of entity:bring_to_front().
1469  * \param l The Lua context that is calling this function.
1470  * \return Number of values to return to Lua.
1471  */
entity_api_bring_to_front(lua_State * l)1472 int LuaContext::entity_api_bring_to_front(lua_State* l) {
1473 
1474   return state_boundary_handle(l, [&] {
1475     Entity& entity = *check_entity(l, 1);
1476 
1477     entity.get_map().get_entities().bring_to_front(entity);
1478 
1479     return 0;
1480   });
1481 }
1482 
1483 /**
1484  * \brief Implementation of entity:bring_to_back().
1485  * \param l The Lua context that is calling this function.
1486  * \return Number of values to return to Lua.
1487  */
entity_api_bring_to_back(lua_State * l)1488 int LuaContext::entity_api_bring_to_back(lua_State* l) {
1489 
1490   return state_boundary_handle(l, [&] {
1491     Entity& entity = *check_entity(l, 1);
1492 
1493     entity.get_map().get_entities().bring_to_back(entity);
1494 
1495     return 0;
1496   });
1497 }
1498 
1499 /**
1500  * \brief Implementation of entity:is_drawn_in_y_order().
1501  * \param l The Lua context that is calling this function.
1502  * \return Number of values to return to Lua.
1503  */
entity_api_is_drawn_in_y_order(lua_State * l)1504 int LuaContext::entity_api_is_drawn_in_y_order(lua_State* l) {
1505 
1506   return state_boundary_handle(l, [&] {
1507     const Entity& entity = *check_entity(l, 1);
1508 
1509     lua_pushboolean(l, entity.is_drawn_in_y_order());
1510     return 1;
1511   });
1512 }
1513 
1514 /**
1515  * \brief Implementation of entity:set_drawn_in_y_order().
1516  * \param l The Lua context that is calling this function.
1517  * \return Number of values to return to Lua.
1518  */
entity_api_set_drawn_in_y_order(lua_State * l)1519 int LuaContext::entity_api_set_drawn_in_y_order(lua_State* l) {
1520 
1521   return state_boundary_handle(l, [&] {
1522     Entity& entity = *check_entity(l, 1);
1523     bool y_order = LuaTools::opt_boolean(l, 2, true);
1524 
1525     entity.set_drawn_in_y_order(y_order);
1526 
1527     return 0;
1528   });
1529 }
1530 
1531 /**
1532  * \brief Implementation of entity:get_sprite().
1533  * \param l The Lua context that is calling this function.
1534  * \return Number of values to return to Lua.
1535  */
entity_api_get_sprite(lua_State * l)1536 int LuaContext::entity_api_get_sprite(lua_State* l) {
1537 
1538   return state_boundary_handle(l, [&] {
1539     Entity& entity = *check_entity(l, 1);
1540     std::string sprite_name = LuaTools::opt_string(l, 2 ,"");
1541 
1542     const SpritePtr& sprite = entity.get_sprite(sprite_name);
1543     if (sprite != nullptr) {
1544       push_sprite(l, *sprite);
1545     }
1546     else {
1547       lua_pushnil(l);
1548     }
1549     return 1;
1550   });
1551 }
1552 
1553 /**
1554  * \brief Implementation of entity:get_sprites().
1555  * \param l The Lua context that is calling this function.
1556  * \return Number of values to return to Lua.
1557  */
entity_api_get_sprites(lua_State * l)1558 int LuaContext::entity_api_get_sprites(lua_State* l) {
1559 
1560   return state_boundary_handle(l, [&] {
1561     Entity& entity = *check_entity(l, 1);
1562 
1563     const std::vector<Entity::NamedSprite> named_sprites = entity.get_named_sprites();
1564     push_named_sprite_iterator(l, named_sprites);
1565     return 1;
1566   });
1567 }
1568 
1569 /**
1570  * \brief Implementation of entity:create_sprite().
1571  * \param l The Lua context that is calling this function.
1572  * \return Number of values to return to Lua.
1573  */
entity_api_create_sprite(lua_State * l)1574 int LuaContext::entity_api_create_sprite(lua_State* l) {
1575 
1576   return state_boundary_handle(l, [&] {
1577     Entity& entity = *check_entity(l, 1);
1578     const std::string& animation_set_id = LuaTools::check_string(l, 2);
1579     const std::string& sprite_name = LuaTools::opt_string(l, 3, "");
1580 
1581     if (!sprite_name.empty() &&
1582         entity.get_sprite(sprite_name) != nullptr) {
1583       LuaTools::arg_error(l, 3, "This entity already has a sprite named '" + sprite_name + "'");
1584     }
1585 
1586     const SpritePtr& sprite = entity.create_sprite(animation_set_id, sprite_name);
1587     sprite->enable_pixel_collisions();
1588 
1589     //if entity is already on a map, notify the sprite that tileset is there
1590     if(entity.is_on_map()){
1591       const Map& map = entity.get_map();
1592       sprite->set_tileset(map.get_tileset());
1593     }
1594 
1595     if (entity.is_suspended()) {
1596       sprite->set_suspended(true);
1597     }
1598 
1599     push_sprite(l, *sprite);
1600     return 1;
1601   });
1602 }
1603 
1604 /**
1605  * \brief Implementation of entity:remove_sprite().
1606  * \param l The Lua context that is calling this function.
1607  * \return Number of values to return to Lua.
1608  */
entity_api_remove_sprite(lua_State * l)1609 int LuaContext::entity_api_remove_sprite(lua_State* l) {
1610 
1611   return state_boundary_handle(l, [&] {
1612     Entity& entity = *check_entity(l, 1);
1613 
1614     if (lua_gettop(l) >= 2) {
1615       Sprite& sprite = *check_sprite(l, 2);
1616       bool success = entity.remove_sprite(sprite);
1617       if (!success) {
1618         LuaTools::arg_error(l, 2, "This sprite does not belong to this entity");
1619       }
1620     }
1621     else {
1622       const SpritePtr& sprite = entity.get_sprite();
1623       if (sprite == nullptr) {
1624         LuaTools::error(l, "This entity has no sprite");
1625       }
1626       entity.remove_sprite(*sprite);
1627     }
1628 
1629     return 0;
1630   });
1631 }
1632 
1633 /**
1634  * \brief Implementation of entity:bring_sprite_to_front().
1635  * \param l The Lua context that is calling this function.
1636  * \return Number of values to return to Lua.
1637  */
entity_api_bring_sprite_to_front(lua_State * l)1638 int LuaContext::entity_api_bring_sprite_to_front(lua_State* l) {
1639 
1640   return state_boundary_handle(l, [&] {
1641     Entity& entity = *check_entity(l, 1);
1642     Sprite& sprite = *check_sprite(l, 2);
1643     bool success = entity.bring_sprite_to_front(sprite);
1644     if (!success) {
1645       LuaTools::arg_error(l, 2, "This sprite does not belong to this entity");
1646     }
1647 
1648     return 0;
1649   });
1650 }
1651 
1652 /**
1653  * \brief Implementation of entity:bring_sprite_to_back().
1654  * \param l The Lua context that is calling this function.
1655  * \return Number of values to return to Lua.
1656  */
entity_api_bring_sprite_to_back(lua_State * l)1657 int LuaContext::entity_api_bring_sprite_to_back(lua_State* l) {
1658 
1659   return state_boundary_handle(l, [&] {
1660     Entity& entity = *check_entity(l, 1);
1661     Sprite& sprite = *check_sprite(l, 2);
1662     bool success = entity.bring_sprite_to_back(sprite);
1663     if (!success) {
1664       LuaTools::arg_error(l, 2, "This sprite does not belong to this entity");
1665     }
1666 
1667     return 0;
1668   });
1669 }
1670 
1671 /**
1672  * \brief Implementation of entity:is_visible().
1673  * \param l The Lua context that is calling this function.
1674  * \return Number of values to return to Lua.
1675  */
entity_api_is_visible(lua_State * l)1676 int LuaContext::entity_api_is_visible(lua_State* l) {
1677 
1678   return state_boundary_handle(l, [&] {
1679     const Entity& entity = *check_entity(l, 1);
1680 
1681     lua_pushboolean(l, entity.is_visible());
1682     return 1;
1683   });
1684 }
1685 
1686 /**
1687  * \brief Implementation of entity:set_visible().
1688  * \param l The Lua context that is calling this function.
1689  * \return Number of values to return to Lua.
1690  */
entity_api_set_visible(lua_State * l)1691 int LuaContext::entity_api_set_visible(lua_State* l) {
1692 
1693   return state_boundary_handle(l, [&] {
1694     Entity& entity = *check_entity(l, 1);
1695     bool visible = LuaTools::opt_boolean(l, 2, true);
1696 
1697     entity.set_visible(visible);
1698 
1699     return 0;
1700   });
1701 }
1702 
1703 /**
1704  * \brief Implementation of entity:get_draw_override().
1705  * \param l The Lua context that is calling this function.
1706  * \return Number of values to return to Lua.
1707  */
entity_api_get_draw_override(lua_State * l)1708 int LuaContext::entity_api_get_draw_override(lua_State* l) {
1709 
1710   return state_boundary_handle(l, [&] {
1711     const Entity& entity = *check_entity(l, 1);
1712 
1713     ScopedLuaRef draw_override = entity.get_draw_override();
1714     if (draw_override.is_empty()) {
1715       lua_pushnil(l);
1716     }
1717     else {
1718       push_ref(l, draw_override);
1719     }
1720     return 1;
1721   });
1722 }
1723 
1724 /**
1725  * \brief Implementation of entity:set_draw_override().
1726  * \param l The Lua context that is calling this function.
1727  * \return Number of values to return to Lua.
1728  */
entity_api_set_draw_override(lua_State * l)1729 int LuaContext::entity_api_set_draw_override(lua_State* l) {
1730 
1731   return state_boundary_handle(l, [&] {
1732     Entity& entity = *check_entity(l, 1);
1733     ScopedLuaRef draw_override;
1734     if (lua_gettop(l) >= 2) {
1735       if (lua_isfunction(l, 2)) {
1736         draw_override = LuaTools::check_function(l, 2);
1737       }
1738       else if (!lua_isnil(l, 2)) {
1739         LuaTools::type_error(l, 2, "function or nil");
1740       }
1741     }
1742 
1743     entity.set_draw_override(draw_override);
1744 
1745     return 0;
1746   });
1747 }
1748 
1749 /**
1750  * \brief Implementation of entity:get_weight().
1751  * \param l The Lua context that is calling this function.
1752  * \return Number of values to return to Lua.
1753  */
entity_api_get_weight(lua_State * l)1754 int LuaContext::entity_api_get_weight(lua_State* l) {
1755 
1756   return state_boundary_handle(l, [&] {
1757     const Entity& entity = *check_entity(l, 1);
1758 
1759     int weight = entity.get_weight();
1760 
1761     lua_pushinteger(l, weight);
1762     return 1;
1763   });
1764 }
1765 
1766 /**
1767  * \brief Implementation of entity:set_weight().
1768  * \param l The Lua context that is calling this function.
1769  * \return Number of values to return to Lua.
1770  */
entity_api_set_weight(lua_State * l)1771 int LuaContext::entity_api_set_weight(lua_State* l) {
1772 
1773   return state_boundary_handle(l, [&] {
1774     Entity& entity = *check_entity(l, 1);
1775     int weight = LuaTools::check_int(l, 2);
1776 
1777     entity.set_weight(weight);
1778 
1779     return 0;
1780   });
1781 }
1782 
1783 /**
1784  * \brief Implementation of entity:entity_api_get_controlling_stream().
1785  * \param l The Lua context that is calling this function.
1786  * \return Number of values to return to Lua.
1787  */
entity_api_get_controlling_stream(lua_State * l)1788 int LuaContext::entity_api_get_controlling_stream(lua_State* l) {
1789 
1790   return state_boundary_handle(l, [&] {
1791     Entity& entity = *check_entity(l, 1);
1792 
1793     StreamAction* stream_action = entity.get_stream_action();
1794     if (stream_action == nullptr) {
1795       lua_pushnil(l);
1796     }
1797     else {
1798       push_stream(l, stream_action->get_stream());
1799     }
1800     return 1;
1801   });
1802 }
1803 
1804 /**
1805  * \brief Implementation of entity:get_movement().
1806  * \param l The Lua context that is calling this function.
1807  * \return Number of values to return to Lua.
1808  */
entity_api_get_movement(lua_State * l)1809 int LuaContext::entity_api_get_movement(lua_State* l) {
1810 
1811   return state_boundary_handle(l, [&] {
1812     Entity& entity = *check_entity(l, 1);
1813 
1814     const std::shared_ptr<Movement>& movement = entity.get_movement();
1815     if (movement == nullptr) {
1816       lua_pushnil(l);
1817     }
1818     else {
1819       push_userdata(l, *movement);
1820     }
1821 
1822     return 1;
1823   });
1824 }
1825 
1826 /**
1827  * \brief Implementation of entity:stop_movement().
1828  * \param l The Lua context that is calling this function.
1829  * \return Number of values to return to Lua.
1830  */
entity_api_stop_movement(lua_State * l)1831 int LuaContext::entity_api_stop_movement(lua_State* l) {
1832 
1833   Entity& entity = *check_entity(l, 1);
1834 
1835   entity.clear_movement();
1836 
1837   return 0;
1838 }
1839 
1840 /**
1841  * \brief Implementation of
1842  * pickable:has_layer_independent_collisions() and
1843  * enemy:has_layer_independent_collisions().
1844  * \param l The Lua context that is calling this function.
1845  * \return Number of values to return to Lua.
1846  */
entity_api_has_layer_independent_collisions(lua_State * l)1847 int LuaContext::entity_api_has_layer_independent_collisions(lua_State* l) {
1848 
1849   return state_boundary_handle(l, [&] {
1850     const Entity& entity = *check_entity(l, 1);
1851 
1852     bool independent = entity.has_layer_independent_collisions();
1853 
1854     lua_pushboolean(l, independent);
1855     return 1;
1856   });
1857 }
1858 
1859 /**
1860  * \brief Implementation of
1861  * pickable:set_layer_independent_collisions() and
1862  * enemy:set_layer_independent_collisions().
1863  * \param l The Lua context that is calling this function.
1864  * \return Number of values to return to Lua.
1865  */
entity_api_set_layer_independent_collisions(lua_State * l)1866 int LuaContext::entity_api_set_layer_independent_collisions(lua_State* l) {
1867 
1868   return state_boundary_handle(l, [&] {
1869     Entity& entity = *check_entity(l, 1);
1870     bool independent = LuaTools::opt_boolean(l, 2, true);
1871 
1872     entity.set_layer_independent_collisions(independent);
1873 
1874     return 0;
1875   });
1876 }
1877 
1878 /**
1879  * \brief Implementation of entity:test_obstacles().
1880  * \param l The Lua context that is calling this function.
1881  * \return Number of values to return to Lua.
1882  */
entity_api_test_obstacles(lua_State * l)1883 int LuaContext::entity_api_test_obstacles(lua_State* l) {
1884 
1885   return state_boundary_handle(l, [&] {
1886     Entity& entity = *check_entity(l, 1);
1887     int dx = LuaTools::opt_int(l, 2, 0);
1888     int dy = LuaTools::opt_int(l, 3, 0);
1889     int layer = entity.get_layer();
1890     if (lua_gettop(l) >= 4) {
1891       layer = LuaTools::check_layer(l, 4, entity.get_map());
1892     }
1893 
1894     Rectangle bounding_box = entity.get_bounding_box();
1895     bounding_box.add_xy(dx, dy);
1896 
1897     lua_pushboolean(l, entity.get_map().test_collision_with_obstacles(
1898         layer, bounding_box, entity));
1899     return 1;
1900   });
1901 }
1902 
1903 /**
1904  * \brief Implementation of entity:get_optimization_distance().
1905  * \param l The Lua context that is calling this function.
1906  * \return Number of values to return to Lua.
1907  */
entity_api_get_optimization_distance(lua_State * l)1908 int LuaContext::entity_api_get_optimization_distance(lua_State* l) {
1909 
1910   return state_boundary_handle(l, [&] {
1911     const Entity& entity = *check_entity(l, 1);
1912 
1913     lua_pushinteger(l, entity.get_optimization_distance());
1914     return 1;
1915   });
1916 }
1917 
1918 /**
1919  * \brief Implementation of entity:set_optimization_distance().
1920  * \param l The Lua context that is calling this function.
1921  * \return Number of values to return to Lua.
1922  */
entity_api_set_optimization_distance(lua_State * l)1923 int LuaContext::entity_api_set_optimization_distance(lua_State* l) {
1924 
1925   return state_boundary_handle(l, [&] {
1926     Entity& entity = *check_entity(l, 1);
1927     int distance = LuaTools::check_int(l, 2);
1928 
1929     entity.set_optimization_distance(distance);
1930 
1931     return 0;
1932   });
1933 }
1934 
1935 /**
1936  * \brief Implementation of entity:is_in_same_region().
1937  * \param l The Lua context that is calling this function.
1938  * \return Number of values to return to Lua.
1939  */
entity_api_is_in_same_region(lua_State * l)1940 int LuaContext::entity_api_is_in_same_region(lua_State* l) {
1941 
1942   return state_boundary_handle(l, [&] {
1943     const Entity& entity = *check_entity(l, 1);
1944     const Entity& other_entity = *check_entity(l, 2);
1945 
1946     lua_pushboolean(l, entity.is_in_same_region(other_entity));
1947     return 1;
1948   });
1949 }
1950 
1951 /**
1952  * \brief Implementation of hero:get_state() and camera:get_state().
1953  * \param l The Lua context that is calling this function.
1954  * \return Number of values to return to Lua.
1955  */
entity_api_get_state(lua_State * l)1956 int LuaContext::entity_api_get_state(lua_State* l) {
1957 
1958   return state_boundary_handle(l, [&] {
1959     const Entity& entity = *check_entity(l, 1);
1960 
1961     std::string state_name = entity.get_state_name();
1962     if (state_name.empty()) {
1963       lua_pushnil(l);
1964       return 1;
1965     }
1966 
1967     push_string(l, state_name);
1968     if (state_name == "custom") {
1969       CustomState& state = *std::static_pointer_cast<CustomState>(entity.get_state());
1970       push_state(l, state);
1971       return 2;
1972     }
1973     return 1;
1974   });
1975 }
1976 
1977 /**
1978  * \brief Implementation of entity:get_property().
1979  * \param l The Lua context that is calling this function.
1980  * \return Number of values to return to Lua.
1981  */
entity_api_get_property(lua_State * l)1982 int LuaContext::entity_api_get_property(lua_State* l) {
1983 
1984   return state_boundary_handle(l, [&] {
1985     const Entity& entity = *check_entity(l, 1);
1986     const std::string& key = LuaTools::check_string(l, 2);
1987 
1988     if (!entity.has_user_property(key)) {
1989       lua_pushnil(l);
1990     }
1991     else {
1992       const std::string& value = entity.get_user_property_value(key);
1993       push_string(l, value);
1994     }
1995     return 1;
1996   });
1997 }
1998 
1999 /**
2000  * \brief Implementation of entity:set_property().
2001  * \param l The Lua context that is calling this function.
2002  * \return Number of values to return to Lua.
2003  */
entity_api_set_property(lua_State * l)2004 int LuaContext::entity_api_set_property(lua_State* l) {
2005 
2006   return state_boundary_handle(l, [&] {
2007     Entity& entity = *check_entity(l, 1);
2008     const std::string& key = LuaTools::check_string(l, 2);
2009 
2010     if (lua_isnil(l, 3)) {
2011       entity.remove_user_property(key);
2012     }
2013     else {
2014       const std::string& value = LuaTools::check_string(l, 3);
2015 
2016       if (!EntityData::is_user_property_key_valid(key)) {
2017         LuaTools::arg_error(l, 2, "Invalid property key: '" + key + "'");
2018       }
2019       entity.set_user_property_value(key, value);
2020     }
2021 
2022     return 0;
2023   });
2024 }
2025 
2026 /**
2027  * \brief Implementation of entity:get_properties().
2028  * \param l The Lua context that is calling this function.
2029  * \return Number of values to return to Lua.
2030  */
entity_api_get_properties(lua_State * l)2031 int LuaContext::entity_api_get_properties(lua_State* l) {
2032 
2033   return state_boundary_handle(l, [&] {
2034     const Entity& entity = *check_entity(l, 1);
2035 
2036     const std::vector<Entity::UserProperty>& properties = entity.get_user_properties();
2037     lua_createtable(l, properties.size(), 0);
2038     int i = 1;
2039     for (const Entity::UserProperty& property : properties) {
2040       lua_createtable(l, 0, 2);
2041       push_string(l, property.first);
2042       lua_setfield(l, -2, "key");
2043       push_string(l, property.second);
2044       lua_setfield(l, -2, "value");
2045       lua_rawseti(l, -2, i);
2046       ++i;
2047     }
2048 
2049     return 1;
2050   });
2051 }
2052 
2053 /**
2054  * \brief Implementation of entity:set_properties().
2055  * \param l The Lua context that is calling this function.
2056  * \return Number of values to return to Lua.
2057  */
entity_api_set_properties(lua_State * l)2058 int LuaContext::entity_api_set_properties(lua_State* l) {
2059 
2060   return state_boundary_handle(l, [&] {
2061     Entity& entity = *check_entity(l, 1);
2062     LuaTools::check_type(l, 2, LUA_TTABLE);
2063 
2064     entity.set_user_properties({});
2065     lua_pushnil(l);
2066     while (lua_next(l, 2) != 0) {
2067       LuaTools::check_type(l, -1, LUA_TTABLE);
2068       const std::string& key = LuaTools::check_string_field(l, -1, "key");
2069       const std::string& value = LuaTools::check_string_field(l, -1, "value");
2070       if (entity.has_user_property(key)) {
2071         LuaTools::error(l, "Duplicate property '" + key + "'");
2072       }
2073       if (!EntityData::is_user_property_key_valid(key)) {
2074         LuaTools::error(l, "Invalid property key: '" + key + "'");
2075       }
2076       entity.set_user_property_value(key, value);
2077       lua_pop(l, 1);
2078     }
2079 
2080     return 1;
2081   });
2082 }
2083 
2084 /**
2085  * \brief Returns whether a value is a userdata of type hero.
2086  * \param l A Lua context.
2087  * \param index An index in the stack.
2088  * \return \c true if the value at this index is a hero.
2089  */
is_hero(lua_State * l,int index)2090 bool LuaContext::is_hero(lua_State* l, int index) {
2091   return is_userdata(l, index, get_entity_internal_type_name(EntityType::HERO));
2092 }
2093 
2094 /**
2095  * \brief Checks that the userdata at the specified index of the stack is a
2096  * hero and returns it.
2097  * \param l A Lua context.
2098  * \param index An index in the stack.
2099  * \return The hero.
2100  */
check_hero(lua_State * l,int index)2101 std::shared_ptr<Hero> LuaContext::check_hero(lua_State* l, int index) {
2102   return std::static_pointer_cast<Hero>(check_userdata(
2103       l, index, get_entity_internal_type_name(EntityType::HERO)
2104   ));
2105 }
2106 
2107 /**
2108  * \brief Pushes a hero userdata onto the stack.
2109  * \param l A Lua context.
2110  * \param hero A hero.
2111  */
push_hero(lua_State * l,Hero & hero)2112 void LuaContext::push_hero(lua_State* l, Hero& hero) {
2113   push_userdata(l, hero);
2114 }
2115 
2116 /**
2117  * \brief Implementation of hero:teleport().
2118  * \param l The Lua context that is calling this function.
2119  * \return Number of values to return to Lua.
2120  */
hero_api_teleport(lua_State * l)2121 int LuaContext::hero_api_teleport(lua_State* l) {
2122 
2123   return state_boundary_handle(l, [&] {
2124     Hero& hero = *check_hero(l, 1);
2125     Game& game = hero.get_game();
2126     const std::string& map_id = LuaTools::check_string(l, 2);
2127     const std::string& destination_name = LuaTools::opt_string(l, 3, "");
2128     Transition::Style transition_style = LuaTools::opt_enum<Transition::Style>(
2129         l, 4, game.get_default_transition_style());
2130 
2131     if (!CurrentQuest::resource_exists(ResourceType::MAP, map_id)) {
2132       LuaTools::arg_error(l, 2, std::string("No such map: '") + map_id + "'");
2133     }
2134 
2135     game.set_current_map(map_id, destination_name, transition_style);
2136 
2137     return 0;
2138   });
2139 }
2140 
2141 /**
2142  * \brief Implementation of hero:get_direction().
2143  * \param l The Lua context that is calling this function.
2144  * \return Number of values to return to Lua.
2145  */
hero_api_get_direction(lua_State * l)2146 int LuaContext::hero_api_get_direction(lua_State* l) {
2147 
2148   return state_boundary_handle(l, [&] {
2149     const Hero& hero = *check_hero(l, 1);
2150 
2151     lua_pushinteger(l, hero.get_animation_direction());
2152     return 1;
2153   });
2154 }
2155 
2156 /**
2157  * \brief Implementation of hero:set_direction().
2158  * \param l The Lua context that is calling this function.
2159  * \return Number of values to return to Lua.
2160  */
hero_api_set_direction(lua_State * l)2161 int LuaContext::hero_api_set_direction(lua_State* l) {
2162 
2163   return state_boundary_handle(l, [&] {
2164     Hero& hero = *check_hero(l, 1);
2165     int direction = LuaTools::check_int(l, 2);
2166 
2167     hero.set_animation_direction(direction);
2168 
2169     return 0;
2170   });
2171 }
2172 
2173 /**
2174  * \brief Implementation of hero:get_walking_speed().
2175  * \param l The Lua context that is calling this function.
2176  * \return Number of values to return to Lua.
2177  */
hero_api_get_walking_speed(lua_State * l)2178 int LuaContext::hero_api_get_walking_speed(lua_State* l) {
2179 
2180   return state_boundary_handle(l, [&] {
2181     const Hero& hero = *check_hero(l, 1);
2182 
2183     lua_pushinteger(l, hero.get_normal_walking_speed());
2184     return 1;
2185   });
2186 }
2187 
2188 /**
2189  * \brief Implementation of hero:set_walking_speed().
2190  * \param l The Lua context that is calling this function.
2191  * \return Number of values to return to Lua.
2192  */
hero_api_set_walking_speed(lua_State * l)2193 int LuaContext::hero_api_set_walking_speed(lua_State* l) {
2194 
2195   return state_boundary_handle(l, [&] {
2196     Hero& hero = *check_hero(l, 1);
2197     int normal_walking_speed = LuaTools::check_int(l, 2);
2198 
2199     hero.set_normal_walking_speed(normal_walking_speed);
2200 
2201     return 0;
2202   });
2203 }
2204 
2205 /**
2206  * \brief Implementation of hero:save_solid_ground().
2207  * \param l The Lua context that is calling this function.
2208  * \return Number of values to return to Lua.
2209  */
hero_api_save_solid_ground(lua_State * l)2210 int LuaContext::hero_api_save_solid_ground(lua_State* l) {
2211 
2212   return state_boundary_handle(l, [&] {
2213     Hero& hero = *check_hero(l, 1);
2214 
2215     ScopedLuaRef callback;
2216     if (lua_gettop(l) == 2) {
2217       // Function parameter.
2218       if (lua_isnil(l, 2)) {
2219         hero.reset_target_solid_ground_callback();
2220         return 0;
2221       }
2222       else {
2223         callback = LuaTools::check_function(l, 2);
2224       }
2225     }
2226     else {
2227       // Coordinates and layer.
2228       int x = 0;
2229       int y = 0;
2230       int layer = 0;
2231       if (lua_gettop(l) >= 2) {
2232         x = LuaTools::check_int(l, 2);
2233         y = LuaTools::check_int(l, 3);
2234         layer = LuaTools::check_layer(l, 4, hero.get_map());
2235       }
2236       else {
2237         x = hero.get_x();
2238         y = hero.get_y();
2239         layer = hero.get_layer();
2240       }
2241       callback = hero.make_solid_ground_callback(Point(x, y), layer);
2242     }
2243     hero.set_target_solid_ground_callback(callback);
2244 
2245     return 0;
2246   });
2247 }
2248 
2249 /**
2250  * \brief Implementation of hero:reset_solid_ground().
2251  * \param l The Lua context that is calling this function.
2252  * \return Number of values to return to Lua.
2253  */
hero_api_reset_solid_ground(lua_State * l)2254 int LuaContext::hero_api_reset_solid_ground(lua_State* l) {
2255 
2256   return state_boundary_handle(l, [&] {
2257     Hero& hero = *check_hero(l, 1);
2258 
2259     hero.reset_target_solid_ground_callback();
2260 
2261     return 0;
2262   });
2263 }
2264 
2265 /**
2266  * \brief Implementation of hero:get_solid_ground().
2267  * \param l The Lua context that is calling this function.
2268  * \return Number of values to return to Lua.
2269  */
hero_api_get_solid_ground_position(lua_State * l)2270 int LuaContext::hero_api_get_solid_ground_position(lua_State* l) {
2271 
2272   return state_boundary_handle(l, [&] {
2273     const Hero& hero = *check_hero(l, 1);
2274 
2275     Point xy;
2276     int layer = 0;
2277 
2278     const ScopedLuaRef& solid_ground_callback = hero.get_target_solid_ground_callback();
2279     if (!solid_ground_callback.is_empty()) {
2280       // Coordinates memorized by hero:save_solid_ground().
2281       //TODO verify if this call is coroutine friendly
2282       solid_ground_callback.push(l);
2283       bool success = LuaTools::call_function(l,0,3,"Solid ground callback");
2284       if (!success) {
2285         // Fallback: use the last solid ground position.
2286         xy = hero.get_last_solid_ground_coords();
2287         layer = hero.get_last_solid_ground_layer();
2288         lua_pushinteger(l, xy.x);
2289         lua_pushinteger(l, xy.y);
2290         lua_pushinteger(l, layer);
2291         return 3;
2292       }
2293       else {
2294         // Normal case: use the result of the function.
2295         return 3;
2296       }
2297     }
2298     else if (hero.get_last_solid_ground_coords().x != -1) {
2299       xy = hero.get_last_solid_ground_coords();
2300       layer = hero.get_last_solid_ground_layer();
2301       // Last solid ground coordinates.
2302       lua_pushinteger(l, xy.x);
2303       lua_pushinteger(l, xy.y);
2304       lua_pushinteger(l, layer);
2305       return 3;
2306     }
2307     else {
2308       // No solid ground coordinates.
2309       // Maybe the map started in water.
2310       lua_pushnil(l);
2311       return 1;
2312     }
2313   });
2314 }
2315 
2316 /**
2317  * \brief Implementation of hero:get_animation().
2318  * \param l The Lua context that is calling this function.
2319  * \return Number of values to return to Lua.
2320  */
hero_api_get_animation(lua_State * l)2321 int LuaContext::hero_api_get_animation(lua_State* l) {
2322 
2323   return state_boundary_handle(l, [&] {
2324     Hero& hero = *check_hero(l, 1);
2325 
2326     const std::string& animation = hero.get_hero_sprites().get_tunic_animation();
2327 
2328     push_string(l, animation);
2329     return 1;
2330   });
2331 }
2332 
2333 /**
2334  * \brief Implementation of hero:set_animation().
2335  * \param l The Lua context that is calling this function.
2336  * \return Number of values to return to Lua.
2337  */
hero_api_set_animation(lua_State * l)2338 int LuaContext::hero_api_set_animation(lua_State* l) {
2339 
2340   return state_boundary_handle(l, [&] {
2341     Hero& hero = *check_hero(l, 1);
2342     const std::string& animation = LuaTools::check_string(l, 2);
2343     const ScopedLuaRef& callback_ref = LuaTools::opt_function(l, 3);
2344 
2345     HeroSprites& sprites = hero.get_hero_sprites();
2346     if (!sprites.has_tunic_animation(animation)) {
2347       LuaTools::arg_error(l, 2,
2348           std::string("No such animation in tunic sprite: '") + animation + "'"
2349       );
2350     }
2351 
2352     sprites.set_animation(animation, callback_ref);
2353 
2354     return 0;
2355   });
2356 }
2357 
2358 /**
2359  * \brief Implementation of hero:get_tunic_sprite_id().
2360  * \param l The Lua context that is calling this function.
2361  * \return Number of values to return to Lua.
2362  */
hero_api_get_tunic_sprite_id(lua_State * l)2363 int LuaContext::hero_api_get_tunic_sprite_id(lua_State* l) {
2364 
2365   return state_boundary_handle(l, [&] {
2366     Hero& hero = *check_hero(l, 1);
2367 
2368     const std::string& sprite_id = hero.get_hero_sprites().get_tunic_sprite_id();
2369 
2370     push_string(l, sprite_id);
2371     return 1;
2372   });
2373 }
2374 
2375 /**
2376  * \brief Implementation of hero:set_tunic_sprite_id().
2377  * \param l The Lua context that is calling this function.
2378  * \return Number of values to return to Lua.
2379  */
hero_api_set_tunic_sprite_id(lua_State * l)2380 int LuaContext::hero_api_set_tunic_sprite_id(lua_State* l) {
2381 
2382   return state_boundary_handle(l, [&] {
2383     Hero& hero = *check_hero(l, 1);
2384     const std::string& sprite_id = LuaTools::check_string(l, 2);
2385 
2386     // TODO check the existence of the sprite animation set
2387     // (see also sol.sprite.create()).
2388     hero.get_hero_sprites().set_tunic_sprite_id(sprite_id);
2389 
2390     return 0;
2391   });
2392 }
2393 
2394 /**
2395  * \brief Implementation of hero:get_sword_sprite_id().
2396  * \param l The Lua context that is calling this function.
2397  * \return Number of values to return to Lua.
2398  */
hero_api_get_sword_sprite_id(lua_State * l)2399 int LuaContext::hero_api_get_sword_sprite_id(lua_State* l) {
2400 
2401   return state_boundary_handle(l, [&] {
2402     Hero& hero = *check_hero(l, 1);
2403 
2404     const std::string& sprite_id = hero.get_hero_sprites().get_sword_sprite_id();
2405 
2406     push_string(l, sprite_id);
2407     return 1;
2408   });
2409 }
2410 
2411 /**
2412  * \brief Implementation of hero:set_sword_sprite_id().
2413  * \param l The Lua context that is calling this function.
2414  * \return Number of values to return to Lua.
2415  */
hero_api_set_sword_sprite_id(lua_State * l)2416 int LuaContext::hero_api_set_sword_sprite_id(lua_State* l) {
2417 
2418   return state_boundary_handle(l, [&] {
2419     Hero& hero = *check_hero(l, 1);
2420     const std::string& sprite_id = LuaTools::check_string(l, 2);
2421 
2422     hero.get_hero_sprites().set_sword_sprite_id(sprite_id);
2423 
2424     return 0;
2425   });
2426 }
2427 
2428 /**
2429  * \brief Implementation of hero:get_sword_sound_id().
2430  * \param l The Lua context that is calling this function.
2431  * \return Number of values to return to Lua.
2432  */
hero_api_get_sword_sound_id(lua_State * l)2433 int LuaContext::hero_api_get_sword_sound_id(lua_State* l) {
2434 
2435   return state_boundary_handle(l, [&] {
2436     Hero& hero = *check_hero(l, 1);
2437 
2438     const std::string& sound_id = hero.get_hero_sprites().get_sword_sound_id();
2439 
2440     push_string(l, sound_id);
2441     return 1;
2442   });
2443 }
2444 
2445 /**
2446  * \brief Implementation of hero:set_sword_sound_id().
2447  * \param l The Lua context that is calling this function.
2448  * \return Number of values to return to Lua.
2449  */
hero_api_set_sword_sound_id(lua_State * l)2450 int LuaContext::hero_api_set_sword_sound_id(lua_State* l) {
2451 
2452   return state_boundary_handle(l, [&] {
2453     Hero& hero = *check_hero(l, 1);
2454     const std::string& sound_id = LuaTools::check_string(l, 2);
2455 
2456     hero.get_hero_sprites().set_sword_sound_id(sound_id);
2457 
2458     return 0;
2459   });
2460 }
2461 
2462 /**
2463  * \brief Implementation of hero:get_shield_sprite_id().
2464  * \param l The Lua context that is calling this function.
2465  * \return Number of values to return to Lua.
2466  */
hero_api_get_shield_sprite_id(lua_State * l)2467 int LuaContext::hero_api_get_shield_sprite_id(lua_State* l) {
2468 
2469   return state_boundary_handle(l, [&] {
2470     Hero& hero = *check_hero(l, 1);
2471 
2472     const std::string& sprite_id = hero.get_hero_sprites().get_shield_sprite_id();
2473 
2474     push_string(l, sprite_id);
2475     return 1;
2476   });
2477 }
2478 
2479 /**
2480  * \brief Implementation of hero:set_shield_sprite_id().
2481  * \param l The Lua context that is calling this function.
2482  * \return Number of values to return to Lua.
2483  */
hero_api_set_shield_sprite_id(lua_State * l)2484 int LuaContext::hero_api_set_shield_sprite_id(lua_State* l) {
2485 
2486   return state_boundary_handle(l, [&] {
2487     Hero& hero = *check_hero(l, 1);
2488     const std::string& sprite_id = LuaTools::check_string(l, 2);
2489 
2490     hero.get_hero_sprites().set_shield_sprite_id(sprite_id);
2491 
2492     return 0;
2493   });
2494 }
2495 
2496 /**
2497  * \brief Implementation of hero:is_blinking().
2498  * \param l The Lua context that is calling this function.
2499  * \return Number of values to return to Lua.
2500  */
hero_api_is_blinking(lua_State * l)2501 int LuaContext::hero_api_is_blinking(lua_State* l) {
2502 
2503   return state_boundary_handle(l, [&] {
2504     Hero& hero = *check_hero(l, 1);
2505 
2506     lua_pushboolean(l, hero.get_hero_sprites().is_blinking());
2507     return 1;
2508   });
2509 }
2510 
2511 /**
2512  * \brief Implementation of hero:set_blinking().
2513  * \param l The Lua context that is calling this function.
2514  * \return Number of values to return to Lua.
2515  */
hero_api_set_blinking(lua_State * l)2516 int LuaContext::hero_api_set_blinking(lua_State* l) {
2517 
2518   return state_boundary_handle(l, [&] {
2519     Hero& hero = *check_hero(l, 1);
2520     bool blinking = LuaTools::opt_boolean(l, 2, true);
2521     uint32_t duration = LuaTools::opt_int(l, 3, 0);
2522 
2523     if (blinking) {
2524       hero.get_hero_sprites().blink(duration);
2525     }
2526     else {
2527       hero.get_hero_sprites().stop_blinking();
2528     }
2529 
2530     return 0;
2531   });
2532 }
2533 
2534 /**
2535  * \brief Implementation of hero:is_invincible().
2536  * \param l The Lua context that is calling this function.
2537  * \return Number of values to return to Lua.
2538  */
hero_api_is_invincible(lua_State * l)2539 int LuaContext::hero_api_is_invincible(lua_State* l) {
2540 
2541   return state_boundary_handle(l, [&] {
2542     const Hero& hero = *check_hero(l, 1);
2543 
2544     lua_pushboolean(l, hero.is_invincible());
2545     return 1;
2546   });
2547 }
2548 
2549 /**
2550  * \brief Implementation of hero:set_invincible().
2551  * \param l The Lua context that is calling this function.
2552  * \return Number of values to return to Lua.
2553  */
hero_api_set_invincible(lua_State * l)2554 int LuaContext::hero_api_set_invincible(lua_State* l) {
2555 
2556   return state_boundary_handle(l, [&] {
2557     Hero& hero = *check_hero(l, 1);
2558     bool invincible = LuaTools::opt_boolean(l, 2, true);
2559     uint32_t duration = LuaTools::opt_int(l, 3, 0);
2560 
2561     hero.set_invincible(invincible, duration);
2562 
2563     return 0;
2564   });
2565 }
2566 
2567 /**
2568  * \brief Implementation of hero:get_carried_object().
2569  * \param l The Lua context that is calling this function.
2570  * \return Number of values to return to Lua.
2571  */
hero_api_get_carried_object(lua_State * l)2572 int LuaContext::hero_api_get_carried_object(lua_State* l) {
2573 
2574   return state_boundary_handle(l, [&] {
2575     Hero& hero = *check_hero(l, 1);
2576 
2577     const std::shared_ptr<CarriedObject>& carried_object = hero.get_carried_object();
2578     if (carried_object == nullptr) {
2579       lua_pushnil(l);
2580     }
2581     else {
2582       push_carried_object(l, *carried_object);
2583     }
2584     return 1;
2585   });
2586 }
2587 
2588 /**
2589  * \brief Implementation of hero:freeze().
2590  * \param l The Lua context that is calling this function.
2591  * \return Number of values to return to Lua.
2592  */
hero_api_freeze(lua_State * l)2593 int LuaContext::hero_api_freeze(lua_State* l) {
2594 
2595   return state_boundary_handle(l, [&] {
2596     Hero& hero = *check_hero(l, 1);
2597 
2598     hero.start_frozen();
2599 
2600     return 0;
2601   });
2602 }
2603 
2604 /**
2605  * \brief Implementation of hero:unfreeze().
2606  * \param l The Lua context that is calling this function.
2607  * \return Number of values to return to Lua.
2608  */
hero_api_unfreeze(lua_State * l)2609 int LuaContext::hero_api_unfreeze(lua_State* l) {
2610 
2611   return state_boundary_handle(l, [&] {
2612     Hero& hero = *check_hero(l, 1);
2613 
2614     hero.start_state_from_ground();
2615 
2616     return 0;
2617   });
2618 }
2619 
2620 /**
2621  * \brief Implementation of hero:walk().
2622  * \param l The Lua context that is calling this function.
2623  * \return Number of values to return to Lua.
2624  */
hero_api_walk(lua_State * l)2625 int LuaContext::hero_api_walk(lua_State* l) {
2626 
2627   return state_boundary_handle(l, [&] {
2628     Hero& hero = *check_hero(l, 1);
2629     const std::string& path = LuaTools::check_string(l, 2);
2630     bool loop = LuaTools::opt_boolean(l, 3, false);
2631     bool ignore_obstacles = LuaTools::opt_boolean(l, 4, false);
2632 
2633     hero.start_forced_walking(path, loop, ignore_obstacles);
2634 
2635     return 0;
2636   });
2637 }
2638 
2639 /**
2640  * \brief Implementation of hero:start_attack().
2641  * \param l The Lua context that is calling this function.
2642  * \return Number of values to return to Lua.
2643  */
hero_api_start_attack(lua_State * l)2644 int LuaContext::hero_api_start_attack(lua_State* l) {
2645 
2646   return state_boundary_handle(l, [&] {
2647     Hero& hero = *check_hero(l, 1);
2648 
2649     if (hero.can_start_sword()) {
2650       hero.start_sword();
2651     }
2652 
2653     return 0;
2654   });
2655 }
2656 
2657 /**
2658  * \brief Implementation of hero:start_attack_loading().
2659  * \param l The Lua context that is calling this function.
2660  * \return Number of values to return to Lua.
2661  */
hero_api_start_attack_loading(lua_State * l)2662 int LuaContext::hero_api_start_attack_loading(lua_State* l) {
2663 
2664   return state_boundary_handle(l, [&] {
2665     Hero& hero = *check_hero(l, 1);
2666     int spin_attack_delay = LuaTools::opt_int(l, 2, 1000);
2667 
2668     if (hero.can_start_sword()) {
2669       hero.start_sword_loading(spin_attack_delay);
2670     }
2671 
2672     return 0;
2673   });
2674 }
2675 
2676 /**
2677  * \brief Implementation of hero:start_item().
2678  * \param l The Lua context that is calling this function.
2679  * \return Number of values to return to Lua.
2680  */
hero_api_start_item(lua_State * l)2681 int LuaContext::hero_api_start_item(lua_State* l) {
2682 
2683   return state_boundary_handle(l, [&] {
2684     Hero& hero = *check_hero(l, 1);
2685     EquipmentItem& item = *check_item(l, 2);
2686 
2687     if (!item.is_saved()) {
2688       LuaTools::arg_error(l, 2,
2689           std::string("Cannot use item '" + item.get_name() + "': this item is not saved"));
2690     }
2691     if (hero.can_start_item(item)) {
2692       hero.start_item(item);
2693     }
2694 
2695     return 0;
2696   });
2697 }
2698 
2699 /**
2700  * \brief Implementation of hero:start_grabbing().
2701  * \param l The Lua context that is calling this function.
2702  * \return Number of values to return to Lua.
2703  */
hero_api_start_grabbing(lua_State * l)2704 int LuaContext::hero_api_start_grabbing(lua_State* l) {
2705 
2706   return state_boundary_handle(l, [&] {
2707     Hero& hero = *check_hero(l, 1);
2708 
2709     if (hero.get_equipment().has_ability(Ability::GRAB)) {
2710       hero.start_grabbing();
2711     }
2712 
2713     return 0;
2714   });
2715 }
2716 
2717 /**
2718  * \brief Implementation of hero:start_jumping().
2719  * \param l The Lua context that is calling this function.
2720  * \return Number of values to return to Lua.
2721  */
hero_api_start_jumping(lua_State * l)2722 int LuaContext::hero_api_start_jumping(lua_State* l) {
2723 
2724   return state_boundary_handle(l, [&] {
2725     Hero& hero = *check_hero(l, 1);
2726     int direction = LuaTools::check_int(l, 2);
2727     int length = LuaTools::check_int(l, 3);
2728     bool ignore_obstacles = LuaTools::opt_boolean(l, 4, false);
2729 
2730     hero.start_jumping(direction, length, ignore_obstacles, false);
2731 
2732     return 0;
2733   });
2734 }
2735 
2736 /**
2737  * \brief Implementation of hero:start_treasure().
2738  * \param l The Lua context that is calling this function.
2739  * \return Number of values to return to Lua.
2740  */
hero_api_start_treasure(lua_State * l)2741 int LuaContext::hero_api_start_treasure(lua_State* l) {
2742 
2743   return state_boundary_handle(l, [&] {
2744     Hero& hero = *check_hero(l, 1);
2745     const std::string& item_name = LuaTools::check_string(l, 2);
2746     int variant = LuaTools::opt_int(l, 3, 1);
2747     const std::string& savegame_variable = LuaTools::opt_string(l, 4, "");
2748 
2749     if (!savegame_variable.empty()
2750         && !LuaTools::is_valid_lua_identifier(savegame_variable)) {
2751       LuaTools::arg_error(l, 4, std::string(
2752           "savegame variable identifier expected, got '") +
2753           savegame_variable + "'");
2754     }
2755 
2756     if (!hero.get_game().get_equipment().item_exists(item_name)) {
2757       LuaTools::arg_error(l, 2, std::string("No such item: '") + item_name + "'");
2758     }
2759 
2760     Treasure treasure(hero.get_game(), item_name, variant, savegame_variable);
2761     if (treasure.is_found()) {
2762       LuaTools::arg_error(l, 4, "This treasure is already found");
2763     }
2764     if (!treasure.is_obtainable()) {
2765       LuaTools::arg_error(l, 4, "This treasure is not obtainable");
2766     }
2767 
2768     const ScopedLuaRef& callback_ref = LuaTools::opt_function(l, 5);
2769 
2770     hero.start_treasure(treasure, callback_ref);
2771 
2772     return 0;
2773   });
2774 }
2775 
2776 /**
2777  * \brief Implementation of hero:start_victory().
2778  * \param l The Lua context that is calling this function.
2779  * \return Number of values to return to Lua.
2780  */
hero_api_start_victory(lua_State * l)2781 int LuaContext::hero_api_start_victory(lua_State* l) {
2782 
2783   return state_boundary_handle(l, [&] {
2784     Hero& hero = *check_hero(l, 1);
2785     ScopedLuaRef callback_ref = LuaTools::opt_function(l, 2);
2786 
2787     hero.start_victory(callback_ref);
2788 
2789     return 0;
2790   });
2791 }
2792 
2793 /**
2794  * \brief Implementation of hero:start_boomerang().
2795  * \param l The Lua context that is calling this function.
2796  * \return Number of values to return to Lua.
2797  */
hero_api_start_boomerang(lua_State * l)2798 int LuaContext::hero_api_start_boomerang(lua_State* l) {
2799 
2800   return state_boundary_handle(l, [&] {
2801     Hero& hero = *check_hero(l, 1);
2802     int max_distance = LuaTools::check_int(l, 2);
2803     int speed = LuaTools::check_int(l, 3);
2804     const std::string& tunic_preparing_animation = LuaTools::check_string(l, 4);
2805     const std::string& sprite_name = LuaTools::check_string(l, 5);
2806 
2807     hero.start_boomerang(max_distance, speed,
2808         tunic_preparing_animation, sprite_name);
2809 
2810     return 0;
2811   });
2812 }
2813 
2814 /**
2815  * \brief Implementation of hero:start_bow().
2816  * \param l The Lua context that is calling this function.
2817  * \return Number of values to return to Lua.
2818  */
hero_api_start_bow(lua_State * l)2819 int LuaContext::hero_api_start_bow(lua_State* l) {
2820 
2821   return state_boundary_handle(l, [&] {
2822     Hero& hero = *check_hero(l, 1);
2823 
2824     hero.start_bow();
2825 
2826     return 0;
2827   });
2828 }
2829 
2830 /**
2831  * \brief Implementation of hero:start_hookshot().
2832  * \param l The Lua context that is calling this function.
2833  * \return Number of values to return to Lua.
2834  */
hero_api_start_hookshot(lua_State * l)2835 int LuaContext::hero_api_start_hookshot(lua_State* l) {
2836 
2837   return state_boundary_handle(l, [&] {
2838     Hero& hero = *check_hero(l, 1);
2839 
2840     hero.start_hookshot();
2841 
2842     return 0;
2843   });
2844 }
2845 
2846 /**
2847  * \brief Implementation of hero:start_running().
2848  * \param l The Lua context that is calling this function.
2849  * \return Number of values to return to Lua.
2850  */
hero_api_start_running(lua_State * l)2851 int LuaContext::hero_api_start_running(lua_State* l) {
2852 
2853   return state_boundary_handle(l, [&] {
2854     Hero& hero = *check_hero(l, 1);
2855 
2856     hero.start_running();
2857 
2858     return 0;
2859   });
2860 }
2861 
2862 /**
2863  * \brief Implementation of hero:start_hurt().
2864  * \param l The Lua context that is calling this function.
2865  * \return Number of values to return to Lua.
2866  */
hero_api_start_hurt(lua_State * l)2867 int LuaContext::hero_api_start_hurt(lua_State* l) {
2868 
2869   return state_boundary_handle(l, [&] {
2870     // There are three possible prototypes:
2871     // - hero:start_hurt(damage)
2872     // - hero:start_hurt(source_x, source_y, damage)
2873     // - hero:start_hurt(source_entity, [source_sprite], damage)
2874     Hero& hero = *check_hero(l, 1);
2875 
2876     if (lua_gettop(l) <= 2) {
2877       // hero:start_hurt(damage)
2878       int damage = LuaTools::check_int(l, 2);
2879       hero.hurt(damage);
2880     }
2881     else if (lua_isnumber(l, 2)) {
2882       // hero:start_hurt(source_x, source_y, damage)
2883       int source_x = LuaTools::check_int(l, 2);
2884       int source_y = LuaTools::check_int(l, 3);
2885       int damage = LuaTools::check_int(l, 4);
2886       hero.hurt(Point(source_x, source_y), damage);
2887     }
2888     else {
2889       // hero:start_hurt(source_entity, [source_sprite], damage)
2890       Entity& source_entity = *check_entity(l, 2);
2891       SpritePtr source_sprite;
2892       int index = 3;
2893       if (is_sprite(l, 3)) {
2894         source_sprite = check_sprite(l, 3);
2895         index = 4;
2896       }
2897       int damage = LuaTools::check_int(l, index);
2898       hero.hurt(source_entity, source_sprite.get(), damage);
2899     }
2900 
2901     return 0;
2902   });
2903 }
2904 
2905 /**
2906  * \brief Implementation of hero:start_state().
2907  * \param l The Lua context that is calling this function.
2908  * \return Number of values to return to Lua.
2909  */
hero_api_start_state(lua_State * l)2910 int LuaContext::hero_api_start_state(lua_State* l) {
2911 
2912   return state_boundary_handle(l, [&] {
2913     Hero& hero = *check_hero(l, 1);
2914     std::shared_ptr<CustomState> state = check_state(l, 2);
2915 
2916     if (state->is_current_state()) {
2917       LuaTools::arg_error(l, 1, "This state is already active");
2918     }
2919     hero.start_custom_state(state);
2920 
2921     return 0;
2922   });
2923 }
2924 
2925 /**
2926  * \brief Implementation of hero:get_state_object().
2927  * \param l The Lua context that is calling this function.
2928  * \return Number of values to return to Lua.
2929  */
hero_api_get_state_object(lua_State * l)2930 int LuaContext::hero_api_get_state_object(lua_State* l) {
2931 
2932   return state_boundary_handle(l, [&] {
2933     const Hero& hero = *check_hero(l, 1);
2934 
2935     if (hero.get_state_name() != "custom") {
2936       lua_pushnil(l);
2937     }
2938     else {
2939       push_state(l, *std::static_pointer_cast<CustomState>(hero.get_state()));
2940     }
2941     return 1;
2942   });
2943 }
2944 
2945 /**
2946  * \brief Notifies Lua that the hero is brandishing a treasure.
2947  *
2948  * Lua then manages the treasure's dialog if any.
2949  *
2950  * \param treasure The treasure being brandished.
2951  * \param callback_ref Lua ref to a function to call when the
2952  * treasure's dialog finishes (possibly an empty ref).
2953  */
notify_hero_brandish_treasure(const Treasure & treasure,const ScopedLuaRef & callback_ref)2954 void LuaContext::notify_hero_brandish_treasure(
2955     const Treasure& treasure,
2956     const ScopedLuaRef& callback_ref
2957 ) {
2958   // This is getting tricky. We will define our own dialog callback
2959   // that will do some work and call callback_ref.
2960   std::ostringstream oss;
2961   oss << "_treasure." << treasure.get_item_name() << "." << treasure.get_variant();
2962   const std::string& dialog_id = oss.str();
2963   Game& game = treasure.get_game();
2964 
2965   push_item(current_l, treasure.get_item());
2966   lua_pushinteger(current_l, treasure.get_variant());
2967   push_string(current_l, treasure.get_savegame_variable());
2968   push_ref(current_l, callback_ref);
2969   lua_pushcclosure(current_l, l_treasure_brandish_finished, 4);
2970   const ScopedLuaRef& treasure_callback_ref = create_ref();
2971 
2972   if (!CurrentQuest::dialog_exists(dialog_id)) {
2973     // No treasure dialog: keep brandishing the treasure for some delay
2974     // and then execute the callback.
2975     TimerPtr timer = std::make_shared<Timer>(3000);
2976     push_map(current_l, game.get_current_map());
2977     add_timer(timer, -1, treasure_callback_ref);
2978     lua_pop(current_l, 1);
2979   }
2980   else {
2981     // A treasure dialog exists. Show it and then execute the callback.
2982     game.start_dialog(dialog_id, ScopedLuaRef(), treasure_callback_ref);
2983   }
2984 }
2985 
2986 /**
2987  * \brief Callback function executed after the animation of brandishing
2988  * a treasure.
2989  *
2990  * Upvalues: item, variant, savegame variable, callback/nil.
2991  *
2992  * \param l The Lua context that is calling this function.
2993  * \return Number of values to return to Lua.
2994  */
l_treasure_brandish_finished(lua_State * l)2995 int LuaContext::l_treasure_brandish_finished(lua_State* l) {
2996 
2997   return state_boundary_handle(l, [&] {
2998     LuaContext& lua_context = get();
2999 
3000     // The treasure's dialog is over.
3001     EquipmentItem& item = *check_item(l, lua_upvalueindex(1));
3002     int treasure_variant = LuaTools::check_int(l, lua_upvalueindex(2));
3003     const std::string& treasure_savegame_variable =
3004         LuaTools::check_string(l, lua_upvalueindex(3));
3005     lua_pushvalue(l, lua_upvalueindex(4));
3006 
3007     // Check upvalues. Any error here would be the fault of the C++ side
3008     // because the user cannot call this function.
3009     Debug::check_assertion(item.get_game() != nullptr,
3010         "Equipment item without game");
3011 
3012     Debug::check_assertion(lua_isnil(l, -1) || lua_isfunction(l, -1),
3013         "Expected function or nil for treasure callback");
3014 
3015     Game& game = *item.get_game();
3016     Hero& hero = *game.get_hero();
3017     const Treasure treasure(game, item.get_name(), treasure_variant, treasure_savegame_variable);
3018 
3019     // Notify the Lua item and the Lua map.
3020     if (!lua_isnil(l, -1)) {
3021       // There is a user callback for this treasure.
3022       lua_context.call_function(0, 0, "treasure callback");
3023     }
3024     lua_context.item_on_obtained(item, treasure);
3025     lua_context.map_on_obtained_treasure(game.get_current_map(), treasure);
3026 
3027     if (hero.is_brandishing_treasure()) {
3028       // The script may have changed the hero's state.
3029       // If not, stop the treasure state.
3030       hero.start_free();
3031     }
3032 
3033     return 0;
3034   });
3035 }
3036 
3037 /**
3038  * \brief Returns whether a value is a userdata of type camera.
3039  * \param l A Lua context.
3040  * \param index An index in the stack.
3041  * \return \c true if the value at this index is a camera.
3042  */
is_camera(lua_State * l,int index)3043 bool LuaContext::is_camera(lua_State* l, int index) {
3044   return is_userdata(l, index, get_entity_internal_type_name(EntityType::CAMERA));
3045 }
3046 
3047 /**
3048  * \brief Checks that the userdata at the specified index of the stack is a
3049  * camera and returns it.
3050  * \param l A Lua context.
3051  * \param index An index in the stack.
3052  * \return The camera.
3053  */
check_camera(lua_State * l,int index)3054 std::shared_ptr<Camera> LuaContext::check_camera(lua_State* l, int index) {
3055   return std::static_pointer_cast<Camera>(check_userdata(
3056       l, index, get_entity_internal_type_name(EntityType::CAMERA)
3057   ));
3058 }
3059 
3060 /**
3061  * \brief Pushes a camera userdata onto the stack.
3062  * \param l A Lua context.
3063  * \param camera A camera.
3064  */
push_camera(lua_State * l,Camera & camera)3065 void LuaContext::push_camera(lua_State* l, Camera& camera) {
3066   push_userdata(l, camera);
3067 }
3068 
3069 /**
3070  * \brief Implementation of camera:get_position_on_screen().
3071  * \param l The Lua context that is calling this function.
3072  * \return Number of values to return to Lua.
3073  */
camera_api_get_position_on_screen(lua_State * l)3074 int LuaContext::camera_api_get_position_on_screen(lua_State* l) {
3075 
3076   return state_boundary_handle(l, [&] {
3077     const Camera& camera = *check_camera(l, 1);
3078 
3079     const Point& position_on_screen = camera.get_position_on_screen();
3080 
3081     lua_pushinteger(l, position_on_screen.x);
3082     lua_pushinteger(l, position_on_screen.y);
3083 
3084     return 2;
3085   });
3086 }
3087 
3088 /**
3089  * \brief Implementation of camera:set_position_on_screen().
3090  * \param l The Lua context that is calling this function.
3091  * \return Number of values to return to Lua.
3092  */
camera_api_set_position_on_screen(lua_State * l)3093 int LuaContext::camera_api_set_position_on_screen(lua_State* l) {
3094 
3095   return state_boundary_handle(l, [&] {
3096     Camera& camera = *check_camera(l, 1);
3097     int x = LuaTools::check_int(l, 2);
3098     int y = LuaTools::check_int(l, 3);
3099 
3100     camera.set_position_on_screen({ x, y });
3101 
3102     return 0;
3103   });
3104 }
3105 
3106 /**
3107  * \brief Implementation of camera:start_tracking().
3108  * \param l The Lua context that is calling this function.
3109  * \return Number of values to return to Lua.
3110  */
camera_api_start_tracking(lua_State * l)3111 int LuaContext::camera_api_start_tracking(lua_State* l) {
3112 
3113   return state_boundary_handle(l, [&] {
3114     Camera& camera = *check_camera(l, 1);
3115     EntityPtr entity = check_entity(l, 2);
3116 
3117     camera.start_tracking(entity);
3118 
3119     return 0;
3120   });
3121 }
3122 
3123 /**
3124  * \brief Implementation of camera:start_manual().
3125  * \param l The Lua context that is calling this function.
3126  * \return Number of values to return to Lua.
3127  */
camera_api_start_manual(lua_State * l)3128 int LuaContext::camera_api_start_manual(lua_State* l) {
3129 
3130   return state_boundary_handle(l, [&] {
3131     Camera& camera = *check_camera(l, 1);
3132 
3133     camera.start_manual();
3134 
3135     return 0;
3136   });
3137 }
3138 
3139 /**
3140  * \brief Implementation of camera:get_position_to_track().
3141  * \param l The Lua context that is calling this function.
3142  * \return Number of values to return to Lua.
3143  */
camera_api_get_position_to_track(lua_State * l)3144 int LuaContext::camera_api_get_position_to_track(lua_State* l) {
3145 
3146   return state_boundary_handle(l, [&] {
3147     const Camera& camera = *check_camera(l, 1);
3148 
3149     Point xy;
3150     if (lua_isnumber(l, 2)) {
3151       xy.x = LuaTools::check_int(l, 2);
3152       xy.y = LuaTools::check_int(l, 3);
3153     }
3154     else if (is_entity(l, 2)) {
3155       const Entity& entity = *check_entity(l, 2);
3156       xy = entity.get_center_point();
3157     }
3158     else {
3159       LuaTools::type_error(l, 2, "number or entity");
3160     }
3161     const Point& position_to_track = camera.get_position_to_track(xy);
3162 
3163     lua_pushinteger(l, position_to_track.x);
3164     lua_pushinteger(l, position_to_track.y);
3165 
3166     return 2;
3167   });
3168 }
3169 
3170 /**
3171  * \brief Implementation of camera:get_tracked_entity().
3172  * \param l The Lua context that is calling this function.
3173  * \return Number of values to return to Lua.
3174  */
camera_api_get_tracked_entity(lua_State * l)3175 int LuaContext::camera_api_get_tracked_entity(lua_State* l) {
3176 
3177   return state_boundary_handle(l, [&] {
3178     const Camera& camera = *check_camera(l, 1);
3179 
3180     EntityPtr entity = camera.get_tracked_entity();
3181     if (entity == nullptr) {
3182       lua_pushnil(l);
3183     }
3184     else {
3185       push_entity(l, *entity);
3186     }
3187     return 1;
3188   });
3189 }
3190 
3191 /**
3192  * \brief Implementation of camera:get_surface().
3193  * \param l The Lua context that is calling this function.
3194  * \return Number of values to return to Lua.
3195  */
camera_api_get_surface(lua_State * l)3196 int LuaContext::camera_api_get_surface(lua_State* l) {
3197 
3198   return state_boundary_handle(l, [&] {
3199     const Camera& camera = *check_camera(l, 1);
3200 
3201     SurfacePtr surface = camera.get_surface();
3202     if (surface == nullptr) {
3203       lua_pushnil(l);
3204     }
3205     else {
3206       push_surface(l, *surface);
3207     }
3208     return 1;
3209   });
3210 }
3211 
3212 /**
3213  * \brief Returns whether a value is a userdata of type destination.
3214  * \param l A Lua context.
3215  * \param index An index in the stack.
3216  * \return \c true if the value at this index is an destination.
3217  */
is_destination(lua_State * l,int index)3218 bool LuaContext::is_destination(lua_State* l, int index) {
3219   return is_userdata(l, index, get_entity_internal_type_name(EntityType::DESTINATION));
3220 }
3221 
3222 /**
3223  * \brief Checks that the userdata at the specified index of the stack is a
3224  * destination and returns it.
3225  * \param l A Lua context.
3226  * \param index An index in the stack.
3227  * \return The destination.
3228  */
check_destination(lua_State * l,int index)3229 std::shared_ptr<Destination> LuaContext::check_destination(lua_State* l, int index) {
3230   return std::static_pointer_cast<Destination>(check_userdata(
3231       l, index, get_entity_internal_type_name(EntityType::DESTINATION)
3232   ));
3233 }
3234 
3235 /**
3236  * \brief Pushes an destination userdata onto the stack.
3237  * \param l A Lua context.
3238  * \param destination A destination.
3239  */
push_destination(lua_State * l,Destination & destination)3240 void LuaContext::push_destination(lua_State* l, Destination& destination) {
3241   push_userdata(l, destination);
3242 }
3243 
3244 /**
3245  * \brief Implementation of destination:get_starting_location_mode().
3246  * \param l The Lua context that is calling this function.
3247  * \return Number of values to return to Lua.
3248  */
destination_api_get_starting_location_mode(lua_State * l)3249 int LuaContext::destination_api_get_starting_location_mode(lua_State* l) {
3250 
3251   return state_boundary_handle(l, [&] {
3252     const Destination& destination = *check_destination(l, 1);
3253 
3254     StartingLocationMode mode = destination.get_starting_location_mode();
3255 
3256     push_string(l, enum_to_name(mode));
3257     return 1;
3258   });
3259 }
3260 
3261 /**
3262  * \brief Implementation of destination:set_starting_location_mode().
3263  * \param l The Lua context that is calling this function.
3264  * \return Number of values to return to Lua.
3265  */
destination_api_set_starting_location_mode(lua_State * l)3266 int LuaContext::destination_api_set_starting_location_mode(lua_State* l) {
3267 
3268   return state_boundary_handle(l, [&] {
3269     Destination& destination = *check_destination(l, 1);
3270     StartingLocationMode mode = StartingLocationMode::WHEN_WORLD_CHANGES;
3271 
3272     if (lua_gettop(l) == 1) {
3273       LuaTools::type_error(l, 2, "string or nil");
3274     }
3275     if (!lua_isnil(l, 2)) {
3276       mode = LuaTools::check_enum<StartingLocationMode>(l, 2);
3277     }
3278 
3279     destination.set_starting_location_mode(mode);
3280     return 0;
3281   });
3282 }
3283 
3284 /**
3285  * \brief Returns whether a value is a userdata of type teletransporter.
3286  * \param l A Lua context.
3287  * \param index An index in the stack.
3288  * \return \c true if the value at this index is an teletransporter.
3289  */
is_teletransporter(lua_State * l,int index)3290 bool LuaContext::is_teletransporter(lua_State* l, int index) {
3291   return is_userdata(l, index, get_entity_internal_type_name(EntityType::TELETRANSPORTER));
3292 }
3293 
3294 /**
3295  * \brief Checks that the userdata at the specified index of the stack is a
3296  * teletransporter and returns it.
3297  * \param l A Lua context.
3298  * \param index An index in the stack.
3299  * \return The teletransporter.
3300  */
check_teletransporter(lua_State * l,int index)3301 std::shared_ptr<Teletransporter> LuaContext::check_teletransporter(lua_State* l, int index) {
3302   return std::static_pointer_cast<Teletransporter>(check_userdata(
3303       l, index, get_entity_internal_type_name(EntityType::TELETRANSPORTER)
3304   ));
3305 }
3306 
3307 /**
3308  * \brief Pushes an teletransporter userdata onto the stack.
3309  * \param l A Lua context.
3310  * \param teletransporter A teletransporter.
3311  */
push_teletransporter(lua_State * l,Teletransporter & teletransporter)3312 void LuaContext::push_teletransporter(lua_State* l, Teletransporter& teletransporter) {
3313   push_userdata(l, teletransporter);
3314 }
3315 
3316 /**
3317  * \brief Implementation of teletransporter:get_sound().
3318  * \param l The Lua context that is calling this function.
3319  * \return Number of values to return to Lua.
3320  */
teletransporter_api_get_sound(lua_State * l)3321 int LuaContext::teletransporter_api_get_sound(lua_State* l) {
3322 
3323   return state_boundary_handle(l, [&] {
3324     const Teletransporter& teletransporter = *check_teletransporter(l, 1);
3325 
3326     const std::string& sound_id = teletransporter.get_sound_id();
3327 
3328     if (sound_id.empty()) {
3329       lua_pushnil(l);
3330     }
3331     else {
3332       push_string(l, sound_id);
3333     }
3334     return 1;
3335   });
3336 }
3337 
3338 /**
3339  * \brief Implementation of teletransporter:set_sound().
3340  * \param l The Lua context that is calling this function.
3341  * \return Number of values to return to Lua.
3342  */
teletransporter_api_set_sound(lua_State * l)3343 int LuaContext::teletransporter_api_set_sound(lua_State* l) {
3344 
3345   return state_boundary_handle(l, [&] {
3346     Teletransporter& teletransporter = *check_teletransporter(l, 1);
3347 
3348     std::string sound_id;
3349     if (lua_gettop(l) > 1) {
3350       sound_id = LuaTools::check_string(l, 2);
3351     }
3352 
3353     teletransporter.set_sound_id(sound_id);
3354     return 0;
3355   });
3356 }
3357 
3358 /**
3359  * \brief Implementation of teletransporter:get_transition().
3360  * \param l The Lua context that is calling this function.
3361  * \return Number of values to return to Lua.
3362  */
teletransporter_api_get_transition(lua_State * l)3363 int LuaContext::teletransporter_api_get_transition(lua_State* l) {
3364 
3365   return state_boundary_handle(l, [&] {
3366     const Teletransporter& teletransporter = *check_teletransporter(l, 1);
3367 
3368     push_string(l, enum_to_name(teletransporter.get_transition_style()));
3369     return 1;
3370   });
3371 }
3372 
3373 /**
3374  * \brief Implementation of teletransporter:set_transition().
3375  * \param l The Lua context that is calling this function.
3376  * \return Number of values to return to Lua.
3377  */
teletransporter_api_set_transition(lua_State * l)3378 int LuaContext::teletransporter_api_set_transition(lua_State* l) {
3379 
3380   return state_boundary_handle(l, [&] {
3381     Teletransporter& teletransporter = *check_teletransporter(l, 1);
3382     Transition::Style transition_style = LuaTools::check_enum<Transition::Style>(
3383         l, 2
3384     );
3385 
3386     teletransporter.set_transition_style(transition_style);
3387 
3388     return 0;
3389   });
3390 }
3391 
3392 /**
3393  * \brief Implementation of teletransporter:get_destination_map().
3394  * \param l The Lua context that is calling this function.
3395  * \return Number of values to return to Lua.
3396  */
teletransporter_api_get_destination_map(lua_State * l)3397 int LuaContext::teletransporter_api_get_destination_map(lua_State* l) {
3398 
3399   return state_boundary_handle(l, [&] {
3400     const Teletransporter& teletransporter = *check_teletransporter(l, 1);
3401 
3402     const std::string& map_id = teletransporter.get_destination_map_id();
3403 
3404     push_string(l, map_id);
3405     return 1;
3406   });
3407 }
3408 
3409 /**
3410  * \brief Implementation of teletransporter:set_destination_map().
3411  * \param l The Lua context that is calling this function.
3412  * \return Number of values to return to Lua.
3413  */
teletransporter_api_set_destination_map(lua_State * l)3414 int LuaContext::teletransporter_api_set_destination_map(lua_State* l) {
3415 
3416   return state_boundary_handle(l, [&] {
3417     Teletransporter& teletransporter = *check_teletransporter(l, 1);
3418     const std::string& map_id = LuaTools::check_string(l, 2);
3419 
3420     teletransporter.set_destination_map_id(map_id);
3421 
3422     return 0;
3423   });
3424 }
3425 
3426 /**
3427  * \brief Implementation of teletransporter:get_destination_name().
3428  * \param l The Lua context that is calling this function.
3429  * \return Number of values to return to Lua.
3430  */
teletransporter_api_get_destination_name(lua_State * l)3431 int LuaContext::teletransporter_api_get_destination_name(lua_State* l) {
3432 
3433   return state_boundary_handle(l, [&] {
3434     const Teletransporter& teletransporter = *check_teletransporter(l, 1);
3435 
3436     const std::string& destination_name = teletransporter.get_destination_name();
3437 
3438     push_string(l, destination_name);
3439     return 1;
3440   });
3441 }
3442 
3443 /**
3444  * \brief Implementation of teletransporter:set_destination_name().
3445  * \param l The Lua context that is calling this function.
3446  * \return Number of values to return to Lua.
3447  */
teletransporter_api_set_destination_name(lua_State * l)3448 int LuaContext::teletransporter_api_set_destination_name(lua_State* l) {
3449 
3450   return state_boundary_handle(l, [&] {
3451     Teletransporter& teletransporter = *check_teletransporter(l, 1);
3452     const std::string& destination_name = LuaTools::check_string(l, 2);
3453 
3454     teletransporter.set_destination_name(destination_name);
3455 
3456     return 0;
3457   });
3458 }
3459 
3460 /**
3461  * \brief Returns whether a value is a userdata of type NPC.
3462  * \param l A Lua context.
3463  * \param index An index in the stack.
3464  * \return \c true if the value at this index is an NPC.
3465  */
is_npc(lua_State * l,int index)3466 bool LuaContext::is_npc(lua_State* l, int index) {
3467   return is_userdata(l, index, get_entity_internal_type_name(EntityType::NPC));
3468 }
3469 
3470 /**
3471  * \brief Checks that the userdata at the specified index of the stack is an
3472  * NPC and returns it.
3473  * \param l A Lua context.
3474  * \param index An index in the stack.
3475  * \return The NPC.
3476  */
check_npc(lua_State * l,int index)3477 std::shared_ptr<Npc> LuaContext::check_npc(lua_State* l, int index) {
3478   return std::static_pointer_cast<Npc>(check_userdata(
3479       l, index, get_entity_internal_type_name(EntityType::NPC))
3480   );
3481 }
3482 
3483 /**
3484  * \brief Pushes an NPC userdata onto the stack.
3485  * \param l A Lua context.
3486  * \param npc An NPC.
3487  */
push_npc(lua_State * l,Npc & npc)3488 void LuaContext::push_npc(lua_State* l, Npc& npc) {
3489   push_userdata(l, npc);
3490 }
3491 
3492 /**
3493  * \brief Implementation of npc:is_traversable().
3494  * \param l The Lua context that is calling this function.
3495  * \return Number of values to return to Lua.
3496  */
npc_api_is_traversable(lua_State * l)3497 int LuaContext::npc_api_is_traversable(lua_State* l) {
3498 
3499   return state_boundary_handle(l, [&] {
3500     const Npc& npc = *check_npc(l, 1);
3501 
3502     lua_pushboolean(l, npc.is_traversable());
3503     return 1;
3504   });
3505 }
3506 
3507 /**
3508  * \brief Implementation of npc:set_traversable().
3509  * \param l The Lua context that is calling this function.
3510  * \return Number of values to return to Lua.
3511  */
npc_api_set_traversable(lua_State * l)3512 int LuaContext::npc_api_set_traversable(lua_State* l) {
3513 
3514   return state_boundary_handle(l, [&] {
3515     Npc& npc = *check_npc(l, 1);
3516 
3517     bool traversable = LuaTools::opt_boolean(l, 2, true);
3518 
3519     npc.set_traversable(traversable);
3520 
3521     return 0;
3522   });
3523 }
3524 
3525 /**
3526  * \brief Returns whether a value is a userdata of type chest.
3527  * \param l A Lua context.
3528  * \param index An index in the stack.
3529  * \return \c true if the value at this index is a chest.
3530  */
is_chest(lua_State * l,int index)3531 bool LuaContext::is_chest(lua_State* l, int index) {
3532   return is_userdata(l, index, get_entity_internal_type_name(EntityType::CHEST));
3533 }
3534 
3535 /**
3536  * \brief Checks that the userdata at the specified index of the stack is a
3537  * chest and returns it.
3538  * \param l A Lua context.
3539  * \param index An index in the stack.
3540  * \return The chest.
3541  */
check_chest(lua_State * l,int index)3542 std::shared_ptr<Chest> LuaContext::check_chest(lua_State* l, int index) {
3543   return std::static_pointer_cast<Chest>(check_userdata(
3544       l, index, get_entity_internal_type_name(EntityType::CHEST)
3545   ));
3546 }
3547 
3548 /**
3549  * \brief Pushes a chest userdata onto the stack.
3550  * \param l A Lua context.
3551  * \param chest A chest.
3552  */
push_chest(lua_State * l,Chest & chest)3553 void LuaContext::push_chest(lua_State* l, Chest& chest) {
3554   push_userdata(l, chest);
3555 }
3556 
3557 /**
3558  * \brief Implementation of chest:is_open().
3559  * \param l The Lua context that is calling this function.
3560  * \return Number of values to return to Lua.
3561  */
chest_api_is_open(lua_State * l)3562 int LuaContext::chest_api_is_open(lua_State* l) {
3563 
3564   return state_boundary_handle(l, [&] {
3565     const Chest& chest = *check_chest(l, 1);
3566 
3567     lua_pushboolean(l, chest.is_open());
3568     return 1;
3569   });
3570 }
3571 
3572 /**
3573  * \brief Implementation of chest:set_open().
3574  * \param l The Lua context that is calling this function.
3575  * \return Number of values to return to Lua.
3576  */
chest_api_set_open(lua_State * l)3577 int LuaContext::chest_api_set_open(lua_State* l) {
3578 
3579   return state_boundary_handle(l, [&] {
3580     Chest& chest = *check_chest(l, 1);
3581     bool open = LuaTools::opt_boolean(l, 2, true);
3582 
3583     chest.set_open(open);
3584 
3585     return 0;
3586   });
3587 }
3588 
3589 /**
3590  * \brief Implementation of chest:get_treasure().
3591  * \param l The Lua context that is calling this function.
3592  * \return Number of values to return to Lua.
3593  */
chest_api_get_treasure(lua_State * l)3594 int LuaContext::chest_api_get_treasure(lua_State* l) {
3595 
3596   return state_boundary_handle(l, [&] {
3597     const Chest& chest = *check_chest(l, 1);
3598     const Treasure& treasure = chest.get_treasure();
3599 
3600     if (treasure.is_empty()) {
3601       // No treasure.
3602       lua_pushnil(l);
3603       lua_pushnil(l);
3604     }
3605     else {
3606       push_string(l, treasure.get_item_name());
3607       lua_pushinteger(l, treasure.get_variant());
3608     }
3609     if (!treasure.is_saved()) {
3610       lua_pushnil(l);
3611     }
3612     else {
3613       push_string(l, treasure.get_savegame_variable());
3614     }
3615     return 3;
3616   });
3617 }
3618 
3619 /**
3620  * \brief Implementation of chest:set_treasure().
3621  * \param l The Lua context that is calling this function.
3622  * \return Number of values to return to Lua.
3623  */
chest_api_set_treasure(lua_State * l)3624 int LuaContext::chest_api_set_treasure(lua_State* l) {
3625 
3626   return state_boundary_handle(l, [&] {
3627     Chest& chest = *check_chest(l, 1);
3628     std::string item_name;
3629     int variant = 1;
3630     std::string savegame_variable;
3631 
3632     if (lua_gettop(l) >= 2 && !lua_isnil(l, 2)) {
3633       item_name = LuaTools::check_string(l, 2);
3634     }
3635     if (lua_gettop(l) >= 3 && !lua_isnil(l, 3)) {
3636       variant = LuaTools::check_int(l, 3);
3637     }
3638     if (lua_gettop(l) >= 4 && !lua_isnil(l, 4)) {
3639       savegame_variable = LuaTools::check_string(l, 4);
3640     }
3641 
3642     if (!savegame_variable.empty()
3643         && !LuaTools::is_valid_lua_identifier(savegame_variable)) {
3644       LuaTools::arg_error(l, 4,
3645           std::string("savegame variable identifier expected, got '")
3646       + savegame_variable + "'");
3647     }
3648 
3649     Treasure treasure(chest.get_game(), item_name, variant, savegame_variable);
3650     chest.set_treasure(treasure);
3651 
3652     return 0;
3653   });
3654 }
3655 
3656 /**
3657  * \brief Returns whether a value is a userdata of type block.
3658  * \param l A Lua context.
3659  * \param index An index in the stack.
3660  * \return \c true if the value at this index is a block.
3661  */
is_block(lua_State * l,int index)3662 bool LuaContext::is_block(lua_State* l, int index) {
3663   return is_userdata(l, index, get_entity_internal_type_name(EntityType::BLOCK));
3664 }
3665 
3666 /**
3667  * \brief Checks that the userdata at the specified index of the stack is a
3668  * block and returns it.
3669  * \param l A Lua context.
3670  * \param index An index in the stack.
3671  * \return The block.
3672  */
check_block(lua_State * l,int index)3673 std::shared_ptr<Block> LuaContext::check_block(lua_State* l, int index) {
3674   return std::static_pointer_cast<Block>(check_userdata(
3675       l, index, get_entity_internal_type_name(EntityType::BLOCK)
3676   ));
3677 }
3678 
3679 /**
3680  * \brief Pushes a block userdata onto the stack.
3681  * \param l A Lua context.
3682  * \param block A block.
3683  */
push_block(lua_State * l,Block & block)3684 void LuaContext::push_block(lua_State* l, Block& block) {
3685   push_userdata(l, block);
3686 }
3687 
3688 /**
3689  * \brief Implementation of block:reset().
3690  * \param l The Lua context that is calling this function.
3691  * \return Number of values to return to Lua.
3692  */
block_api_reset(lua_State * l)3693 int LuaContext::block_api_reset(lua_State* l) {
3694 
3695   return state_boundary_handle(l, [&] {
3696     Block& block = *check_block(l, 1);
3697 
3698     block.reset();
3699 
3700     return 0;
3701   });
3702 }
3703 
3704 /**
3705  * \brief Implementation of block:is_pushable().
3706  * \param l The Lua context that is calling this function.
3707  * \return Number of values to return to Lua.
3708  */
block_api_is_pushable(lua_State * l)3709 int LuaContext::block_api_is_pushable(lua_State* l) {
3710 
3711   return state_boundary_handle(l, [&] {
3712     const Block& block = *check_block(l, 1);
3713 
3714     lua_pushboolean(l, block.is_pushable());
3715     return 1;
3716   });
3717 }
3718 
3719 /**
3720  * \brief Implementation of block:set_pushable().
3721  * \param l The Lua context that is calling this function.
3722  * \return Number of values to return to Lua.
3723  */
block_api_set_pushable(lua_State * l)3724 int LuaContext::block_api_set_pushable(lua_State* l) {
3725 
3726   return state_boundary_handle(l, [&] {
3727     Block& block = *check_block(l, 1);
3728     bool pushable = LuaTools::opt_boolean(l, 2, true);
3729 
3730     block.set_pushable(pushable);
3731 
3732     return 0;
3733   });
3734 }
3735 
3736 /**
3737  * \brief Implementation of block:is_pullable().
3738  * \param l The Lua context that is calling this function.
3739  * \return Number of values to return to Lua.
3740  */
block_api_is_pullable(lua_State * l)3741 int LuaContext::block_api_is_pullable(lua_State* l) {
3742 
3743   return state_boundary_handle(l, [&] {
3744     const Block& block = *check_block(l, 1);
3745 
3746     lua_pushboolean(l, block.is_pullable());
3747     return 1;
3748   });
3749 }
3750 
3751 /**
3752  * \brief Implementation of block:set_pullable().
3753  * \param l The Lua context that is calling this function.
3754  * \return Number of values to return to Lua.
3755  */
block_api_set_pullable(lua_State * l)3756 int LuaContext::block_api_set_pullable(lua_State* l) {
3757 
3758   return state_boundary_handle(l, [&] {
3759     Block& block = *check_block(l, 1);
3760     bool pullable = LuaTools::opt_boolean(l, 2, true);
3761 
3762     block.set_pullable(pullable);
3763 
3764     return 0;
3765   });
3766 }
3767 
3768 /**
3769  * \brief Implementation of block:get_max_moves().
3770  * \param l The Lua context that is calling this function.
3771  * \return Number of values to return to Lua.
3772  */
block_api_get_max_moves(lua_State * l)3773 int LuaContext::block_api_get_max_moves(lua_State* l) {
3774 
3775   return state_boundary_handle(l, [&] {
3776     const Block& block = *check_block(l, 1);
3777 
3778     const int max_moves = block.get_max_moves();
3779 
3780     if (max_moves == -1) {
3781       // -1 means no maximum.
3782       lua_pushnil(l);
3783     }
3784     else {
3785       lua_pushinteger(l, max_moves);
3786     }
3787     return 1;
3788   });
3789 }
3790 
3791 /**
3792  * \brief Implementation of block:set_max_moves().
3793  * \param l The Lua context that is calling this function.
3794  * \return Number of values to return to Lua.
3795  */
block_api_set_max_moves(lua_State * l)3796 int LuaContext::block_api_set_max_moves(lua_State* l) {
3797 
3798   return state_boundary_handle(l, [&] {
3799     Block& block = *check_block(l, 1);
3800     if (lua_type(l, 2) != LUA_TNUMBER && lua_type(l, 2) != LUA_TNIL) {
3801       LuaTools::type_error(l, 2, "number or nil");
3802     }
3803 
3804     if (lua_isnumber(l, 2)) {
3805       const int max_moves = LuaTools::check_int(l, 2);
3806       if (max_moves < 0) {
3807         LuaTools::arg_error(l, 2, "max_moves should be 0, positive or nil");
3808       }
3809       block.set_max_moves(max_moves);
3810     }
3811     else if (lua_isnil(l, 2)) {
3812       // -1 means no maximum in C++.
3813       block.set_max_moves(-1);
3814     }
3815 
3816     return 0;
3817   });
3818 }
3819 
3820 /**
3821  * \brief Implementation of block:get_maximum_moves().
3822  * \param l The Lua context that is calling this function.
3823  * \return Number of values to return to Lua.
3824  */
block_api_get_maximum_moves(lua_State * l)3825 int LuaContext::block_api_get_maximum_moves(lua_State* l) {
3826 
3827   get().warning_deprecated(
3828       { 1, 5 },
3829       "block:get_maximum_moves()",
3830       "Use block:get_max_moves() instead.");
3831   return block_api_get_max_moves(l);
3832 }
3833 
3834 /**
3835  * \brief Implementation of block:set_maximum_moves().
3836  * \param l The Lua context that is calling this function.
3837  * \return Number of values to return to Lua.
3838  */
block_api_set_maximum_moves(lua_State * l)3839 int LuaContext::block_api_set_maximum_moves(lua_State* l) {
3840 
3841   get().warning_deprecated(
3842       { 1, 5 },
3843       "block:set_maximum_moves()",
3844       "Use block:set_max_moves() instead.");
3845   return block_api_set_max_moves(l);
3846 }
3847 
3848 /**
3849  * \brief Returns whether a value is a userdata of type switch.
3850  * \param l A Lua context.
3851  * \param index An index in the stack.
3852  * \return \c true if the value at this index is a switch.
3853  */
is_switch(lua_State * l,int index)3854 bool LuaContext::is_switch(lua_State* l, int index) {
3855   return is_userdata(l, index, get_entity_internal_type_name(EntityType::SWITCH));
3856 }
3857 
3858 /**
3859  * \brief Checks that the userdata at the specified index of the stack is a
3860  * switch and returns it.
3861  * \param l A Lua context.
3862  * \param index An index in the stack.
3863  * \return The switch.
3864  */
check_switch(lua_State * l,int index)3865 std::shared_ptr<Switch> LuaContext::check_switch(lua_State* l, int index) {
3866   return std::static_pointer_cast<Switch>(check_userdata(
3867       l, index, get_entity_internal_type_name(EntityType::SWITCH)
3868   ));
3869 }
3870 
3871 /**
3872  * \brief Pushes a switch userdata onto the stack.
3873  * \param l A Lua context.
3874  * \param sw A switch.
3875  */
push_switch(lua_State * l,Switch & sw)3876 void LuaContext::push_switch(lua_State* l, Switch& sw) {
3877   push_userdata(l, sw);
3878 }
3879 
3880 /**
3881  * \brief Implementation of switch:is_activated().
3882  * \param l The Lua context that is calling this function.
3883  * \return Number of values to return to Lua.
3884  */
switch_api_is_activated(lua_State * l)3885 int LuaContext::switch_api_is_activated(lua_State* l) {
3886 
3887   return state_boundary_handle(l, [&] {
3888     const Switch& sw = *check_switch(l, 1);
3889 
3890     lua_pushboolean(l, sw.is_activated());
3891     return 1;
3892   });
3893 }
3894 
3895 /**
3896  * \brief Implementation of switch:set_activated().
3897  * \param l The Lua context that is calling this function.
3898  * \return Number of values to return to Lua.
3899  */
switch_api_set_activated(lua_State * l)3900 int LuaContext::switch_api_set_activated(lua_State* l) {
3901 
3902   return state_boundary_handle(l, [&] {
3903     Switch& sw = *check_switch(l, 1);
3904     bool activated = LuaTools::opt_boolean(l, 2, true);
3905 
3906     sw.set_activated(activated);
3907 
3908     return 0;
3909   });
3910 }
3911 
3912 /**
3913  * \brief Implementation of switch:is_locked().
3914  * \param l The Lua context that is calling this function.
3915  * \return Number of values to return to Lua.
3916  */
switch_api_is_locked(lua_State * l)3917 int LuaContext::switch_api_is_locked(lua_State* l) {
3918 
3919   return state_boundary_handle(l, [&] {
3920     const Switch& sw = *check_switch(l, 1);
3921 
3922     lua_pushboolean(l, sw.is_locked());
3923     return 1;
3924   });
3925 }
3926 
3927 /**
3928  * \brief Implementation of switch:set_locked().
3929  * \param l The Lua context that is calling this function.
3930  * \return Number of values to return to Lua.
3931  */
switch_api_set_locked(lua_State * l)3932 int LuaContext::switch_api_set_locked(lua_State* l) {
3933 
3934   return state_boundary_handle(l, [&] {
3935     Switch& sw = *check_switch(l, 1);
3936     bool locked = LuaTools::opt_boolean(l, 2, true);
3937 
3938     sw.set_locked(locked);
3939 
3940     return 0;
3941   });
3942 }
3943 
3944 /**
3945  * \brief Implementation of switch:is_walkable().
3946  * \param l The Lua context that is calling this function.
3947  * \return Number of values to return to Lua.
3948  */
switch_api_is_walkable(lua_State * l)3949 int LuaContext::switch_api_is_walkable(lua_State* l) {
3950 
3951   return state_boundary_handle(l, [&] {
3952     const Switch& sw = *check_switch(l, 1);
3953 
3954     lua_pushboolean(l, sw.is_walkable());
3955     return 1;
3956   });
3957 }
3958 
3959 /**
3960  * \brief Returns whether a value is a userdata of type stream.
3961  * \param l A Lua context.
3962  * \param index An index in the stack.
3963  * \return \c true if the value at this index is a stream.
3964  */
is_stream(lua_State * l,int index)3965 bool LuaContext::is_stream(lua_State* l, int index) {
3966   return is_userdata(l, index, get_entity_internal_type_name(EntityType::STREAM));
3967 }
3968 
3969 /**
3970  * \brief Checks that the userdata at the specified index of the stack is a
3971  * stream and returns it.
3972  * \param l A Lua context.
3973  * \param index An index in the stack.
3974  * \return The stream.
3975  */
check_stream(lua_State * l,int index)3976 std::shared_ptr<Stream> LuaContext::check_stream(lua_State* l, int index) {
3977   return std::static_pointer_cast<Stream>(check_userdata(
3978       l, index, get_entity_internal_type_name(EntityType::STREAM)
3979   ));
3980 }
3981 
3982 /**
3983  * \brief Pushes a stream userdata onto the stack.
3984  * \param l A Lua context.
3985  * \param stream A stream.
3986  */
push_stream(lua_State * l,Stream & stream)3987 void LuaContext::push_stream(lua_State* l, Stream& stream) {
3988   push_userdata(l, stream);
3989 }
3990 
3991 /**
3992  * \brief Implementation of stream:get_direction().
3993  * \param l The Lua context that is calling this function.
3994  * \return Number of values to return to Lua.
3995  */
stream_api_get_direction(lua_State * l)3996 int LuaContext::stream_api_get_direction(lua_State* l) {
3997 
3998   return state_boundary_handle(l, [&] {
3999     const Stream& stream = *check_stream(l, 1);
4000 
4001     lua_pushinteger(l, stream.get_direction());
4002     return 1;
4003   });
4004 }
4005 
4006 /**
4007  * \brief Implementation of stream:set_direction().
4008  * \param l The Lua context that is calling this function.
4009  * \return Number of values to return to Lua.
4010  */
stream_api_set_direction(lua_State * l)4011 int LuaContext::stream_api_set_direction(lua_State* l) {
4012 
4013   return state_boundary_handle(l, [&] {
4014     Stream& stream = *check_stream(l, 1);
4015     int direction = LuaTools::check_int(l, 2);
4016 
4017     if (direction < 0 || direction >= 8) {
4018       LuaTools::arg_error(l, 2, "Invalid stream direction: must be between 0 and 7");
4019     }
4020 
4021     stream.set_direction(direction);
4022 
4023     return 0;
4024   });
4025 }
4026 
4027 /**
4028  * \brief Implementation of stream:get_speed().
4029  * \param l The Lua context that is calling this function.
4030  * \return Number of values to return to Lua.
4031  */
stream_api_get_speed(lua_State * l)4032 int LuaContext::stream_api_get_speed(lua_State* l) {
4033 
4034   return state_boundary_handle(l, [&] {
4035     const Stream& stream = *check_stream(l, 1);
4036 
4037     lua_pushinteger(l, stream.get_speed());
4038     return 1;
4039   });
4040 }
4041 
4042 /**
4043  * \brief Implementation of stream:set_speed().
4044  * \param l The Lua context that is calling this function.
4045  * \return Number of values to return to Lua.
4046  */
stream_api_set_speed(lua_State * l)4047 int LuaContext::stream_api_set_speed(lua_State* l) {
4048 
4049   return state_boundary_handle(l, [&] {
4050     Stream& stream = *check_stream(l, 1);
4051     int speed = LuaTools::check_int(l, 2);
4052 
4053     stream.set_speed(speed);
4054 
4055     return 0;
4056   });
4057 }
4058 
4059 /**
4060  * \brief Implementation of stream:get_allow_movement().
4061  * \param l The Lua context that is calling this function.
4062  * \return Number of values to return to Lua.
4063  */
stream_api_get_allow_movement(lua_State * l)4064 int LuaContext::stream_api_get_allow_movement(lua_State* l) {
4065 
4066   return state_boundary_handle(l, [&] {
4067     const Stream& stream = *check_stream(l, 1);
4068 
4069     lua_pushboolean(l, stream.get_allow_movement());
4070     return 1;
4071   });
4072 }
4073 
4074 /**
4075  * \brief Implementation of stream:set_allow_movement().
4076  * \param l The Lua context that is calling this function.
4077  * \return Number of values to return to Lua.
4078  */
stream_api_set_allow_movement(lua_State * l)4079 int LuaContext::stream_api_set_allow_movement(lua_State* l) {
4080 
4081   return state_boundary_handle(l, [&] {
4082     Stream& stream = *check_stream(l, 1);
4083     bool allow_movement = LuaTools::opt_boolean(l, 2, true);
4084 
4085     stream.set_allow_movement(allow_movement);
4086 
4087     return 0;
4088   });
4089 }
4090 
4091 /**
4092  * \brief Implementation of stream:get_allow_attack().
4093  * \param l The Lua context that is calling this function.
4094  * \return Number of values to return to Lua.
4095  */
stream_api_get_allow_attack(lua_State * l)4096 int LuaContext::stream_api_get_allow_attack(lua_State* l) {
4097 
4098   return state_boundary_handle(l, [&] {
4099     const Stream& stream = *check_stream(l, 1);
4100 
4101     lua_pushboolean(l, stream.get_allow_attack());
4102     return 1;
4103   });
4104 }
4105 
4106 /**
4107  * \brief Implementation of stream:set_allow_attack().
4108  * \param l The Lua context that is calling this function.
4109  * \return Number of values to return to Lua.
4110  */
stream_api_set_allow_attack(lua_State * l)4111 int LuaContext::stream_api_set_allow_attack(lua_State* l) {
4112 
4113   return state_boundary_handle(l, [&] {
4114     Stream& stream = *check_stream(l, 1);
4115     bool allow_attack = LuaTools::opt_boolean(l, 2, true);
4116 
4117     stream.set_allow_attack(allow_attack);
4118 
4119     return 0;
4120   });
4121 }
4122 
4123 /**
4124  * \brief Implementation of stream:get_allow_item().
4125  * \param l The Lua context that is calling this function.
4126  * \return Number of values to return to Lua.
4127  */
stream_api_get_allow_item(lua_State * l)4128 int LuaContext::stream_api_get_allow_item(lua_State* l) {
4129 
4130   return state_boundary_handle(l, [&] {
4131     const Stream& stream = *check_stream(l, 1);
4132 
4133     lua_pushboolean(l, stream.get_allow_item());
4134     return 1;
4135   });
4136 }
4137 
4138 /**
4139  * \brief Implementation of stream:set_allow_item().
4140  * \param l The Lua context that is calling this function.
4141  * \return Number of values to return to Lua.
4142  */
stream_api_set_allow_item(lua_State * l)4143 int LuaContext::stream_api_set_allow_item(lua_State* l) {
4144 
4145   return state_boundary_handle(l, [&] {
4146     Stream& stream = *check_stream(l, 1);
4147     bool allow_item = LuaTools::opt_boolean(l, 2, true);
4148 
4149     stream.set_allow_item(allow_item);
4150 
4151     return 0;
4152   });
4153 }
4154 
4155 /**
4156  * \brief Returns whether a value is a userdata of type door.
4157  * \param l A Lua context.
4158  * \param index An index in the stack.
4159  * \return \c true if the value at this index is a door.
4160  */
is_door(lua_State * l,int index)4161 bool LuaContext::is_door(lua_State* l, int index) {
4162   return is_userdata(l, index, get_entity_internal_type_name(EntityType::DOOR));
4163 }
4164 
4165 /**
4166  * \brief Checks that the userdata at the specified index of the stack is a
4167  * door and returns it.
4168  * \param l A Lua context.
4169  * \param index An index in the stack.
4170  * \return The door.
4171  */
check_door(lua_State * l,int index)4172 std::shared_ptr<Door> LuaContext::check_door(lua_State* l, int index) {
4173   return std::static_pointer_cast<Door>(check_userdata(
4174       l, index, get_entity_internal_type_name(EntityType::DOOR))
4175   );
4176 }
4177 
4178 /**
4179  * \brief Pushes a door userdata onto the stack.
4180  * \param l A Lua context.
4181  * \param door A door.
4182  */
push_door(lua_State * l,Door & door)4183 void LuaContext::push_door(lua_State* l, Door& door) {
4184   push_userdata(l, door);
4185 }
4186 
4187 /**
4188  * \brief Implementation of door:is_open().
4189  * \param l The Lua context that is calling this function.
4190  * \return Number of values to return to Lua.
4191  */
door_api_is_open(lua_State * l)4192 int LuaContext::door_api_is_open(lua_State* l) {
4193 
4194   return state_boundary_handle(l, [&] {
4195     const Door& door = *check_door(l, 1);
4196 
4197     lua_pushboolean(l, door.is_open());
4198     return 1;
4199   });
4200 }
4201 
4202 /**
4203  * \brief Implementation of door:is_opening().
4204  * \param l The Lua context that is calling this function.
4205  * \return Number of values to return to Lua.
4206  */
door_api_is_opening(lua_State * l)4207 int LuaContext::door_api_is_opening(lua_State* l) {
4208 
4209   return state_boundary_handle(l, [&] {
4210     const Door& door = *check_door(l, 1);
4211 
4212     lua_pushboolean(l, door.is_opening());
4213     return 1;
4214   });
4215 }
4216 
4217 /**
4218  * \brief Implementation of door:is_closed().
4219  * \param l The Lua context that is calling this function.
4220  * \return Number of values to return to Lua.
4221  */
door_api_is_closed(lua_State * l)4222 int LuaContext::door_api_is_closed(lua_State* l) {
4223 
4224   return state_boundary_handle(l, [&] {
4225     const Door& door = *check_door(l, 1);
4226 
4227     lua_pushboolean(l, door.is_closed());
4228     return 1;
4229   });
4230 }
4231 
4232 /**
4233  * \brief Implementation of door:is_closing().
4234  * \param l The Lua context that is calling this function.
4235  * \return Number of values to return to Lua.
4236  */
door_api_is_closing(lua_State * l)4237 int LuaContext::door_api_is_closing(lua_State* l) {
4238 
4239   return state_boundary_handle(l, [&] {
4240     const Door& door = *check_door(l, 1);
4241 
4242     lua_pushboolean(l, door.is_closing());
4243     return 1;
4244   });
4245 }
4246 
4247 /**
4248  * \brief Implementation of door:open().
4249  * \param l The Lua context that is calling this function.
4250  * \return Number of values to return to Lua.
4251  */
door_api_open(lua_State * l)4252 int LuaContext::door_api_open(lua_State* l) {
4253 
4254   return state_boundary_handle(l, [&] {
4255     Door& door = *check_door(l, 1);
4256 
4257     if (!door.is_open() && !door.is_opening()) {
4258       door.open();
4259       Sound::play("door_open");
4260     }
4261 
4262     return 0;
4263   });
4264 }
4265 
4266 /**
4267  * \brief Implementation of door:close().
4268  * \param l The Lua context that is calling this function.
4269  * \return Number of values to return to Lua.
4270  */
door_api_close(lua_State * l)4271 int LuaContext::door_api_close(lua_State* l) {
4272 
4273   return state_boundary_handle(l, [&] {
4274     Door& door = *check_door(l, 1);
4275 
4276     if (!door.is_closed() && !door.is_closing()) {
4277       door.close();
4278       Sound::play("door_closed");
4279     }
4280 
4281     return 0;
4282   });
4283 }
4284 
4285 /**
4286  * \brief Implementation of door:set_open().
4287  * \param l The Lua context that is calling this function.
4288  * \return Number of values to return to Lua.
4289  */
door_api_set_open(lua_State * l)4290 int LuaContext::door_api_set_open(lua_State* l) {
4291 
4292   return state_boundary_handle(l, [&] {
4293     Door& door = *check_door(l, 1);
4294     bool open = LuaTools::opt_boolean(l, 2, true);
4295 
4296     door.set_open(open);
4297 
4298     return 0;
4299   });
4300 }
4301 
4302 /**
4303  * \brief Returns whether a value is a userdata of type stairs.
4304  * \param l A Lua context.
4305  * \param index An index in the stack.
4306  * \return \c true if the value at this index is a stairs entity.
4307  */
is_stairs(lua_State * l,int index)4308 bool LuaContext::is_stairs(lua_State* l, int index) {
4309   return is_userdata(l, index, get_entity_internal_type_name(EntityType::STAIRS));
4310 }
4311 
4312 /**
4313  * \brief Checks that the userdata at the specified index of the stack is a
4314  * stairs entity and returns it.
4315  * \param l A Lua context.
4316  * \param index An index in the stack.
4317  * \return The stairs.
4318  */
check_stairs(lua_State * l,int index)4319 std::shared_ptr<Stairs> LuaContext::check_stairs(lua_State* l, int index) {
4320   return std::static_pointer_cast<Stairs>(check_userdata(
4321       l, index, get_entity_internal_type_name(EntityType::STAIRS))
4322   );
4323 }
4324 
4325 /**
4326  * \brief Pushes a stairs userdata onto the stack.
4327  * \param l A Lua context.
4328  * \param stairs A stairs entity.
4329  */
push_stairs(lua_State * l,Stairs & stairs)4330 void LuaContext::push_stairs(lua_State* l, Stairs& stairs) {
4331   push_userdata(l, stairs);
4332 }
4333 
4334 /**
4335  * \brief Implementation of stairs:get_direction().
4336  * \param l The Lua context that is calling this function.
4337  * \return Number of values to return to Lua.
4338  */
stairs_api_get_direction(lua_State * l)4339 int LuaContext::stairs_api_get_direction(lua_State* l) {
4340 
4341   return state_boundary_handle(l, [&] {
4342     const Stairs& stairs = *check_stairs(l, 1);
4343 
4344     lua_pushinteger(l, stairs.get_direction());
4345     return 1;
4346   });
4347 }
4348 
4349 /**
4350  * \brief Implementation of stairs:is_inner().
4351  * \param l The Lua context that is calling this function.
4352  * \return Number of values to return to Lua.
4353  */
stairs_api_is_inner(lua_State * l)4354 int LuaContext::stairs_api_is_inner(lua_State* l) {
4355 
4356   return state_boundary_handle(l, [&] {
4357     const Stairs& stairs = *check_stairs(l, 1);
4358 
4359     lua_pushboolean(l, stairs.is_inside_floor());
4360     return 1;
4361   });
4362 }
4363 
4364 /**
4365  * \brief Returns whether a value is a userdata of type shop treasure.
4366  * \param l A Lua context.
4367  * \param index An index in the stack.
4368  * \return \c true if the value at this index is a shop treasure.
4369  */
is_shop_treasure(lua_State * l,int index)4370 bool LuaContext::is_shop_treasure(lua_State* l, int index) {
4371   return is_userdata(l, index, get_entity_internal_type_name(EntityType::SHOP_TREASURE));
4372 }
4373 
4374 /**
4375  * \brief Checks that the userdata at the specified index of the stack is a
4376  * shop treasure and returns it.
4377  * \param l A Lua context.
4378  * \param index An index in the stack.
4379  * \return The shop treasure.
4380  */
check_shop_treasure(lua_State * l,int index)4381 std::shared_ptr<ShopTreasure> LuaContext::check_shop_treasure(lua_State* l, int index) {
4382   return std::static_pointer_cast<ShopTreasure>(check_userdata(
4383       l, index, get_entity_internal_type_name(EntityType::SHOP_TREASURE)
4384   ));
4385 }
4386 
4387 /**
4388  * \brief Pushes a shop treasure userdata onto the stack.
4389  * \param l A Lua context.
4390  * \param shop_treasure A shop treasure.
4391  */
push_shop_treasure(lua_State * l,ShopTreasure & shop_treasure)4392 void LuaContext::push_shop_treasure(lua_State* l, ShopTreasure& shop_treasure) {
4393   push_userdata(l, shop_treasure);
4394 }
4395 
4396 /**
4397  * \brief Notifies Lua that the hero interacts with a shop treasure.
4398  *
4399  * Lua then manages the dialogs shown to the player.
4400  *
4401  * \param shop_treasure A shop treasure.
4402  */
notify_shop_treasure_interaction(ShopTreasure & shop_treasure)4403 void LuaContext::notify_shop_treasure_interaction(ShopTreasure& shop_treasure) {
4404 
4405   push_shop_treasure(current_l, shop_treasure);
4406   lua_pushcclosure(current_l, l_shop_treasure_description_dialog_finished, 1);
4407   const ScopedLuaRef& callback_ref = create_ref();
4408 
4409   shop_treasure.get_game().start_dialog(
4410       shop_treasure.get_dialog_id(),
4411       ScopedLuaRef(),
4412       callback_ref
4413   );
4414 }
4415 
4416 /**
4417  * \brief Callback function executed after the description dialog of
4418  * a shop treasure.
4419  * \param l The Lua context that is calling this function.
4420  * \return Number of values to return to Lua.
4421  */
l_shop_treasure_description_dialog_finished(lua_State * l)4422 int LuaContext::l_shop_treasure_description_dialog_finished(lua_State* l) {
4423 
4424   return state_boundary_handle(l, [&] {
4425 
4426     // The description message has just finished.
4427     // The shop treasure is the first upvalue.
4428     ShopTreasure& shop_treasure = *check_shop_treasure(l, lua_upvalueindex(1));
4429     Game& game = shop_treasure.get_game();
4430 
4431     if (shop_treasure.is_being_removed()) {
4432       // The shop treasure was removed during the dialog.
4433       return 0;
4434     }
4435 
4436     lua_pushinteger(l, shop_treasure.get_price());
4437     const ScopedLuaRef& price_ref = LuaTools::create_ref(l);
4438 
4439     push_shop_treasure(l, shop_treasure);
4440     lua_pushcclosure(l, l_shop_treasure_question_dialog_finished, 1);
4441     ScopedLuaRef callback_ref = LuaTools::create_ref(l);
4442 
4443     game.start_dialog("_shop.question", price_ref, callback_ref);
4444 
4445     return 0;
4446   });
4447 }
4448 
4449 /**
4450  * \brief Callback function executed after the question dialog of
4451  * a shop treasure.
4452  * \param l The Lua context that is calling this function.
4453  * \return Number of values to return to Lua.
4454  */
l_shop_treasure_question_dialog_finished(lua_State * l)4455 int LuaContext::l_shop_treasure_question_dialog_finished(lua_State* l) {
4456 
4457   return state_boundary_handle(l, [&] {
4458     LuaContext& lua_context = get();
4459 
4460     // The "do you want to buy?" question has just been displayed.
4461     // The shop treasure is the first upvalue.
4462     ShopTreasure& shop_treasure = *check_shop_treasure(l, lua_upvalueindex(1));
4463 
4464     if (shop_treasure.is_being_removed()) {
4465       // The shop treasure was removed during the dialog.
4466       return 0;
4467     }
4468 
4469     // The first parameter is the answer.
4470     bool wants_to_buy = lua_isboolean(l, 1) && lua_toboolean(l, 1);
4471 
4472     Game& game = shop_treasure.get_game();
4473     if (wants_to_buy) {
4474 
4475       // The player wants to buy the item.
4476       Equipment& equipment = game.get_equipment();
4477       const Treasure& treasure = shop_treasure.get_treasure();
4478       EquipmentItem& item = treasure.get_item();
4479 
4480       if (!treasure.is_obtainable()) {
4481         // This treasure is not allowed.
4482         Sound::play("wrong");
4483       }
4484       else if (equipment.get_money() < shop_treasure.get_price()) {
4485         // Not enough money.
4486         Sound::play("wrong");
4487         game.start_dialog("_shop.not_enough_money", ScopedLuaRef(), ScopedLuaRef());
4488       }
4489       else if (item.has_amount() && item.get_amount() >= item.get_max_amount()) {
4490         // The player already has the maximum amount of this item.
4491         Sound::play("wrong");
4492         game.start_dialog("_shop.amount_full", ScopedLuaRef(), ScopedLuaRef());
4493       }
4494       else {
4495 
4496         bool can_buy = lua_context.shop_treasure_on_buying(shop_treasure);
4497         if (can_buy) {
4498 
4499           // Give the treasure.
4500           equipment.remove_money(shop_treasure.get_price());
4501 
4502           game.get_hero()->start_treasure(treasure, ScopedLuaRef());
4503           if (treasure.is_saved()) {
4504             shop_treasure.remove_from_map();
4505             game.get_savegame().set_boolean(treasure.get_savegame_variable(), true);
4506           }
4507           lua_context.shop_treasure_on_bought(shop_treasure);
4508         }
4509       }
4510     }
4511     return 0;
4512   });
4513 }
4514 
4515 /**
4516  * \brief Returns whether a value is a userdata of type pickable.
4517  * \param l A Lua context.
4518  * \param index An index in the stack.
4519  * \return \c true if the value at this index is a pickable.
4520  */
is_pickable(lua_State * l,int index)4521 bool LuaContext::is_pickable(lua_State* l, int index) {
4522   return is_userdata(l, index, get_entity_internal_type_name(EntityType::PICKABLE));
4523 }
4524 
4525 /**
4526  * \brief Checks that the userdata at the specified index of the stack is an
4527  * pickable and returns it.
4528  * \param l A Lua context.
4529  * \param index An index in the stack.
4530  * \return The pickable.
4531  */
check_pickable(lua_State * l,int index)4532 std::shared_ptr<Pickable> LuaContext::check_pickable(lua_State* l, int index) {
4533   return std::static_pointer_cast<Pickable>(check_userdata(
4534       l, index, get_entity_internal_type_name(EntityType::PICKABLE)
4535   ));
4536 }
4537 
4538 /**
4539  * \brief Pushes an pickable userdata onto the stack.
4540  * \param l A Lua context.
4541  * \param pickable A pickable treasure.
4542  */
push_pickable(lua_State * l,Pickable & pickable)4543 void LuaContext::push_pickable(lua_State* l, Pickable& pickable) {
4544   push_userdata(l, pickable);
4545 }
4546 
4547 /**
4548  * \brief Implementation of pickable:get_followed_entity().
4549  * \param l The Lua context that is calling this function.
4550  * \return Number of values to return to Lua.
4551  */
pickable_api_get_followed_entity(lua_State * l)4552 int LuaContext::pickable_api_get_followed_entity(lua_State* l) {
4553 
4554   return state_boundary_handle(l, [&] {
4555     Pickable& pickable = *check_pickable(l, 1);
4556 
4557     EntityPtr followed_entity = pickable.get_entity_followed();
4558 
4559     if (followed_entity != nullptr) {
4560       push_entity(l, *followed_entity);
4561     }
4562     else {
4563       lua_pushnil(l);
4564     }
4565     return 1;
4566   });
4567 }
4568 
4569 /**
4570  * \brief Implementation of pickable:get_falling_height().
4571  * \param l The Lua context that is calling this function.
4572  * \return Number of values to return to Lua.
4573  */
pickable_api_get_falling_height(lua_State * l)4574 int LuaContext::pickable_api_get_falling_height(lua_State* l) {
4575 
4576   return state_boundary_handle(l, [&] {
4577     const Pickable& pickable = *check_pickable(l, 1);
4578 
4579     lua_pushinteger(l, pickable.get_falling_height());
4580     return 1;
4581   });
4582 }
4583 
4584 /**
4585  * \brief Implementation of pickable:get_treasure().
4586  * \param l The Lua context that is calling this function.
4587  * \return Number of values to return to Lua.
4588  */
pickable_api_get_treasure(lua_State * l)4589 int LuaContext::pickable_api_get_treasure(lua_State* l) {
4590 
4591   return state_boundary_handle(l, [&] {
4592     const Pickable& pickable = *check_pickable(l, 1);
4593     const Treasure& treasure = pickable.get_treasure();
4594 
4595     push_item(l, treasure.get_item());
4596     lua_pushinteger(l, treasure.get_variant());
4597     if (!treasure.is_saved()) {
4598       lua_pushnil(l);
4599     }
4600     else {
4601       push_string(l, treasure.get_savegame_variable());
4602     }
4603     return 3;
4604   });
4605 }
4606 
4607 /**
4608  * \brief Returns whether a value is a userdata of type destructible object.
4609  * \param l A Lua context.
4610  * \param index An index in the stack.
4611  * \return \c true if the value at this index is a destructible object.
4612  */
is_destructible(lua_State * l,int index)4613 bool LuaContext::is_destructible(lua_State* l, int index) {
4614   return is_userdata(l, index, get_entity_internal_type_name(EntityType::DESTRUCTIBLE));
4615 }
4616 
4617 /**
4618  * \brief Checks that the userdata at the specified index of the stack is a
4619  * destructible object and returns it.
4620  * \param l A Lua context.
4621  * \param index An index in the stack.
4622  * \return The destructible object.
4623  */
check_destructible(lua_State * l,int index)4624 std::shared_ptr<Destructible> LuaContext::check_destructible(lua_State* l, int index) {
4625   return std::static_pointer_cast<Destructible>(check_userdata(
4626       l, index, get_entity_internal_type_name(EntityType::DESTRUCTIBLE)
4627   ));
4628 }
4629 
4630 /**
4631  * \brief Pushes a destructible userdata onto the stack.
4632  * \param l A Lua context.
4633  * \param destructible A destructible object.
4634  */
push_destructible(lua_State * l,Destructible & destructible)4635 void LuaContext::push_destructible(lua_State* l, Destructible& destructible) {
4636   push_userdata(l, destructible);
4637 }
4638 
4639 /**
4640  * \brief Implementation of destructible:get_treasure().
4641  * \param l The Lua context that is calling this function.
4642  * \return Number of values to return to Lua.
4643  */
destructible_api_get_treasure(lua_State * l)4644 int LuaContext::destructible_api_get_treasure(lua_State* l) {
4645 
4646   return state_boundary_handle(l, [&] {
4647     const Destructible& destructible = *check_destructible(l, 1);
4648     const Treasure& treasure = destructible.get_treasure();
4649 
4650     if (treasure.get_item_name().empty()) {
4651       // No treasure: return nil.
4652       lua_pushnil(l);
4653       return 1;
4654     }
4655 
4656     push_string(l, treasure.get_item_name());
4657     lua_pushinteger(l, treasure.get_variant());
4658     if (!treasure.is_saved()) {
4659       lua_pushnil(l);
4660     }
4661     else {
4662       push_string(l, treasure.get_savegame_variable());
4663     }
4664     return 3;
4665   });
4666 }
4667 
4668 /**
4669  * \brief Implementation of destructible:set_treasure().
4670  * \param l The Lua context that is calling this function.
4671  * \return Number of values to return to Lua.
4672  */
destructible_api_set_treasure(lua_State * l)4673 int LuaContext::destructible_api_set_treasure(lua_State* l) {
4674 
4675   return state_boundary_handle(l, [&] {
4676     Destructible& destructible = *check_destructible(l, 1);
4677     std::string item_name, savegame_variable;
4678     int variant = 1;
4679 
4680     if (lua_gettop(l) >= 2 && !lua_isnil(l, 2)) {
4681       item_name = LuaTools::check_string(l, 2);
4682     }
4683     if (lua_gettop(l) >= 3 && !lua_isnil(l, 3)) {
4684       variant = LuaTools::check_int(l, 3);
4685     }
4686     if (lua_gettop(l) >= 4 && !lua_isnil(l, 4)) {
4687       savegame_variable = LuaTools::check_string(l, 4);
4688     }
4689 
4690     if (!savegame_variable.empty()
4691         && !LuaTools::is_valid_lua_identifier(savegame_variable)) {
4692       LuaTools::arg_error(l, 4,
4693           std::string("savegame variable identifier expected, got '")
4694       + savegame_variable + "'");
4695     }
4696 
4697     Treasure treasure(destructible.get_game(), item_name, variant, savegame_variable);
4698     destructible.set_treasure(treasure);
4699 
4700     return 0;
4701   });
4702 }
4703 
4704 /**
4705  * \brief Implementation of destructible:get_destruction_sound().
4706  * \param l The Lua context that is calling this function.
4707  * \return Number of values to return to Lua.
4708  */
destructible_api_get_destruction_sound(lua_State * l)4709 int LuaContext::destructible_api_get_destruction_sound(lua_State* l) {
4710 
4711   return state_boundary_handle(l, [&] {
4712     const Destructible& destructible = *check_destructible(l, 1);
4713 
4714     const std::string& destruction_sound_id = destructible.get_destruction_sound();
4715 
4716     if (destruction_sound_id.empty()) {
4717       lua_pushnil(l);
4718     }
4719     else {
4720       push_string(l, destruction_sound_id);
4721     }
4722     return 1;
4723   });
4724 }
4725 
4726 /**
4727  * \brief Implementation of destructible:set_destruction_sound().
4728  * \param l The Lua context that is calling this function.
4729  * \return Number of values to return to Lua.
4730  */
destructible_api_set_destruction_sound(lua_State * l)4731 int LuaContext::destructible_api_set_destruction_sound(lua_State* l) {
4732 
4733   return state_boundary_handle(l, [&] {
4734     Destructible& destructible = *check_destructible(l, 1);
4735     std::string destruction_sound_id;
4736     if (!lua_isnil(l, 2)) {
4737       destruction_sound_id = LuaTools::check_string(l, 2);
4738     }
4739 
4740     destructible.set_destruction_sound(destruction_sound_id);
4741     return 0;
4742   });
4743 }
4744 
4745 /**
4746  * \brief Implementation of destructible:get_can_be_cut().
4747  * \param l The Lua context that is calling this function.
4748  * \return Number of values to return to Lua.
4749  */
destructible_api_get_can_be_cut(lua_State * l)4750 int LuaContext::destructible_api_get_can_be_cut(lua_State* l) {
4751 
4752   return state_boundary_handle(l, [&] {
4753     const Destructible& destructible = *check_destructible(l, 1);
4754 
4755     bool can_be_cut = destructible.get_can_be_cut();
4756 
4757     lua_pushboolean(l, can_be_cut);
4758     return 1;
4759   });
4760 }
4761 
4762 /**
4763  * \brief Implementation of destructible:set_can_be_cut().
4764  * \param l The Lua context that is calling this function.
4765  * \return Number of values to return to Lua.
4766  */
destructible_api_set_can_be_cut(lua_State * l)4767 int LuaContext::destructible_api_set_can_be_cut(lua_State* l) {
4768 
4769   return state_boundary_handle(l, [&] {
4770     Destructible& destructible = *check_destructible(l, 1);
4771     bool can_be_cut = LuaTools::opt_boolean(l, 2, true);
4772 
4773     destructible.set_can_be_cut(can_be_cut);
4774 
4775     return 0;
4776   });
4777 }
4778 
4779 /**
4780  * \brief Implementation of destructible:get_can_explode().
4781  * \param l The Lua context that is calling this function.
4782  * \return Number of values to return to Lua.
4783  */
destructible_api_get_can_explode(lua_State * l)4784 int LuaContext::destructible_api_get_can_explode(lua_State* l) {
4785 
4786   return state_boundary_handle(l, [&] {
4787     const Destructible& destructible = *check_destructible(l, 1);
4788 
4789     bool can_explode = destructible.get_can_explode();
4790 
4791     lua_pushboolean(l, can_explode);
4792     return 1;
4793   });
4794 }
4795 
4796 /**
4797  * \brief Implementation of destructible:set_can_explode().
4798  * \param l The Lua context that is calling this function.
4799  * \return Number of values to return to Lua.
4800  */
destructible_api_set_can_explode(lua_State * l)4801 int LuaContext::destructible_api_set_can_explode(lua_State* l) {
4802 
4803   return state_boundary_handle(l, [&] {
4804     Destructible& destructible = *check_destructible(l, 1);
4805     bool can_explode = LuaTools::opt_boolean(l, 2, true);
4806 
4807     destructible.set_can_explode(can_explode);
4808 
4809     return 0;
4810   });
4811 }
4812 
4813 /**
4814  * \brief Implementation of destructible:get_can_regenerate().
4815  * \param l The Lua context that is calling this function.
4816  * \return Number of values to return to Lua.
4817  */
destructible_api_get_can_regenerate(lua_State * l)4818 int LuaContext::destructible_api_get_can_regenerate(lua_State* l) {
4819 
4820   return state_boundary_handle(l, [&] {
4821     const Destructible& destructible = *check_destructible(l, 1);
4822 
4823     bool can_regenerate = destructible.get_can_regenerate();
4824 
4825     lua_pushboolean(l, can_regenerate);
4826     return 1;
4827   });
4828 }
4829 
4830 /**
4831  * \brief Implementation of destructible:set_can_regenerate().
4832  * \param l The Lua context that is calling this function.
4833  * \return Number of values to return to Lua.
4834  */
destructible_api_set_can_regenerate(lua_State * l)4835 int LuaContext::destructible_api_set_can_regenerate(lua_State* l) {
4836 
4837   return state_boundary_handle(l, [&] {
4838     Destructible& destructible = *check_destructible(l, 1);
4839     bool can_regenerate = LuaTools::opt_boolean(l, 2, true);
4840 
4841     destructible.set_can_regenerate(can_regenerate);
4842 
4843     return 0;
4844   });
4845 }
4846 
4847 /**
4848  * \brief Implementation of destructible:get_damage_on_enemies().
4849  * \param l The Lua context that is calling this function.
4850  * \return Number of values to return to Lua.
4851  */
destructible_api_get_damage_on_enemies(lua_State * l)4852 int LuaContext::destructible_api_get_damage_on_enemies(lua_State* l) {
4853 
4854   return state_boundary_handle(l, [&] {
4855     const Destructible& destructible = *check_destructible(l, 1);
4856 
4857     int damage_on_enemies = destructible.get_damage_on_enemies();
4858 
4859     lua_pushinteger(l, damage_on_enemies);
4860     return 1;
4861   });
4862 }
4863 
4864 /**
4865  * \brief Implementation of destructible:set_damage_on_enemies().
4866  * \param l The Lua context that is calling this function.
4867  * \return Number of values to return to Lua.
4868  */
destructible_api_set_damage_on_enemies(lua_State * l)4869 int LuaContext::destructible_api_set_damage_on_enemies(lua_State* l) {
4870 
4871   return state_boundary_handle(l, [&] {
4872     Destructible& destructible = *check_destructible(l, 1);
4873     int damage_on_enemies = LuaTools::check_int(l, 2);
4874 
4875     destructible.set_damage_on_enemies(damage_on_enemies);
4876 
4877     return 0;
4878   });
4879 }
4880 
4881 /**
4882  * \brief Implementation of destructible:get_modified_ground().
4883  * \param l The Lua context that is calling this function.
4884  * \return Number of values to return to Lua.
4885  */
destructible_api_get_modified_ground(lua_State * l)4886 int LuaContext::destructible_api_get_modified_ground(lua_State* l) {
4887 
4888   return state_boundary_handle(l, [&] {
4889     const Destructible& destructible = *check_destructible(l, 1);
4890 
4891     Ground modified_ground = destructible.get_modified_ground();
4892 
4893     push_string(l, enum_to_name(modified_ground));
4894     return 1;
4895   });
4896 }
4897 
4898 /**
4899  * \brief Returns whether a value is a userdata of type carried object.
4900  * \param l A Lua context.
4901  * \param index An index in the stack.
4902  * \return \c true if the value at this index is a carried object.
4903  */
is_carried_object(lua_State * l,int index)4904 bool LuaContext::is_carried_object(lua_State* l, int index) {
4905   return is_userdata(l, index, get_entity_internal_type_name(EntityType::CARRIED_OBJECT));
4906 }
4907 
4908 /**
4909  * \brief Checks that the userdata at the specified index of the stack is a
4910  * carried object and returns it.
4911  * \param l A Lua context.
4912  * \param index An index in the stack.
4913  * \return The carried object.
4914  */
check_carried_object(lua_State * l,int index)4915 std::shared_ptr<CarriedObject> LuaContext::check_carried_object(lua_State* l, int index) {
4916   return std::static_pointer_cast<CarriedObject>(check_userdata(
4917       l, index, get_entity_internal_type_name(EntityType::CARRIED_OBJECT)
4918   ));
4919 }
4920 
4921 /**
4922  * \brief Pushes a carried object userdata onto the stack.
4923  * \param l A Lua context.
4924  * \param carried_object A carried object.
4925  */
push_carried_object(lua_State * l,CarriedObject & carried_object)4926 void LuaContext::push_carried_object(lua_State* l, CarriedObject& carried_object) {
4927   push_userdata(l, carried_object);
4928 }
4929 
4930 /**
4931  * \brief Implementation of carried_object:get_carrier().
4932  * \param l The Lua context that is calling this function.
4933  * \return Number of values to return to Lua.
4934  */
carried_object_api_get_carrier(lua_State * l)4935 int LuaContext::carried_object_api_get_carrier(lua_State* l) {
4936 
4937   return state_boundary_handle(l, [&] {
4938     const CarriedObject& carried_object = *check_carried_object(l, 1);
4939 
4940     const EntityPtr& carrier = carried_object.get_carrier();
4941     if (carrier == nullptr) {
4942       lua_pushnil(l);
4943     }
4944     else {
4945       push_entity(l, *carrier);
4946     }
4947     return 1;
4948   });
4949 }
4950 
4951 /**
4952  * \brief Implementation of carried_object:get_destruction_sound().
4953  * \param l The Lua context that is calling this function.
4954  * \return Number of values to return to Lua.
4955  */
carried_object_api_get_destruction_sound(lua_State * l)4956 int LuaContext::carried_object_api_get_destruction_sound(lua_State* l) {
4957 
4958   return state_boundary_handle(l, [&] {
4959     const CarriedObject& carried_object = *check_carried_object(l, 1);
4960 
4961     const std::string& destruction_sound_id = carried_object.get_destruction_sound();
4962 
4963     if (destruction_sound_id.empty()) {
4964       lua_pushnil(l);
4965     }
4966     else {
4967       push_string(l, destruction_sound_id);
4968     }
4969     return 1;
4970   });
4971 }
4972 
4973 /**
4974  * \brief Implementation of carried_object:set_destruction_sound().
4975  * \param l The Lua context that is calling this function.
4976  * \return Number of values to return to Lua.
4977  */
carried_object_api_set_destruction_sound(lua_State * l)4978 int LuaContext::carried_object_api_set_destruction_sound(lua_State* l) {
4979 
4980   return state_boundary_handle(l, [&] {
4981     CarriedObject& carried_object = *check_carried_object(l, 1);
4982     std::string destruction_sound_id;
4983     if (!lua_isnil(l, 2)) {
4984       destruction_sound_id = LuaTools::check_string(l, 2);
4985     }
4986 
4987     carried_object.set_destruction_sound(destruction_sound_id);
4988     return 0;
4989   });
4990 }
4991 
4992 /**
4993  * \brief Implementation of carried_object:get_damage_on_enemies().
4994  * \param l The Lua context that is calling this function.
4995  * \return Number of values to return to Lua.
4996  */
carried_object_api_get_damage_on_enemies(lua_State * l)4997 int LuaContext::carried_object_api_get_damage_on_enemies(lua_State* l) {
4998 
4999   return state_boundary_handle(l, [&] {
5000     const CarriedObject& carried_object = *check_carried_object(l, 1);
5001 
5002     int damage_on_enemies = carried_object.get_damage_on_enemies();
5003 
5004     lua_pushinteger(l, damage_on_enemies);
5005     return 1;
5006   });
5007 }
5008 
5009 /**
5010  * \brief Implementation of carried_object:set_damage_on_enemies().
5011  * \param l The Lua context that is calling this function.
5012  * \return Number of values to return to Lua.
5013  */
carried_object_api_set_damage_on_enemies(lua_State * l)5014 int LuaContext::carried_object_api_set_damage_on_enemies(lua_State* l) {
5015 
5016   return state_boundary_handle(l, [&] {
5017     CarriedObject& carried_object = *check_carried_object(l, 1);
5018     int damage_on_enemies = LuaTools::check_int(l, 2);
5019 
5020     carried_object.set_damage_on_enemies(damage_on_enemies);
5021 
5022     return 0;
5023   });
5024 }
5025 
5026 /**
5027  * \brief Returns whether a value is a userdata of type dynamic tile.
5028  * \param l A Lua context.
5029  * \param index An index in the stack.
5030  * \return \c true if the value at this index is a dynamic tile.
5031  */
is_dynamic_tile(lua_State * l,int index)5032 bool LuaContext::is_dynamic_tile(lua_State* l, int index) {
5033   return is_userdata(l, index, get_entity_internal_type_name(EntityType::DYNAMIC_TILE));
5034 }
5035 
5036 /**
5037  * \brief Checks that the userdata at the specified index of the stack is a
5038  * dynamic tile and returns it.
5039  * \param l A Lua context.
5040  * \param index An index in the stack.
5041  * \return The dynamic tile.
5042  */
check_dynamic_tile(lua_State * l,int index)5043 std::shared_ptr<DynamicTile> LuaContext::check_dynamic_tile(lua_State* l, int index) {
5044   return std::static_pointer_cast<DynamicTile>(check_userdata(
5045       l, index, get_entity_internal_type_name(EntityType::DYNAMIC_TILE)
5046   ));
5047 }
5048 
5049 /**
5050  * \brief Pushes a dynamic tile userdata onto the stack.
5051  * \param l A Lua context.
5052  * \param dynamic_tile A dynamic tile.
5053  */
push_dynamic_tile(lua_State * l,DynamicTile & dynamic_tile)5054 void LuaContext::push_dynamic_tile(lua_State* l, DynamicTile& dynamic_tile) {
5055   push_userdata(l, dynamic_tile);
5056 }
5057 
5058 /**
5059  * \brief Implementation of dynamic_tile:get_pattern_id().
5060  * \param l The Lua context that is calling this function.
5061  * \return Number of values to return to Lua.
5062  */
dynamic_tile_api_get_pattern_id(lua_State * l)5063 int LuaContext::dynamic_tile_api_get_pattern_id(lua_State* l) {
5064 
5065   return state_boundary_handle(l, [&] {
5066     const DynamicTile& dynamic_tile = *check_dynamic_tile(l, 1);
5067 
5068     const std::string& pattern_id = dynamic_tile.get_tile_pattern_id();
5069 
5070     push_string(l, pattern_id);
5071     return 1;
5072   });
5073 }
5074 
5075 /**
5076  * \brief Implementation of dynamic_tile:get_modified_ground().
5077  * \param l The Lua context that is calling this function.
5078  * \return Number of values to return to Lua.
5079  */
dynamic_tile_api_get_modified_ground(lua_State * l)5080 int LuaContext::dynamic_tile_api_get_modified_ground(lua_State* l) {
5081 
5082   return state_boundary_handle(l, [&] {
5083     const DynamicTile& dynamic_tile = *check_dynamic_tile(l, 1);
5084 
5085     Ground modified_ground = dynamic_tile.get_modified_ground();
5086 
5087     push_string(l, enum_to_name(modified_ground));
5088     return 1;
5089   });
5090 }
5091 
5092 /**
5093  * \brief Implementation of dynamic_tile:get_tileset().
5094  * \param l The Lua context that is calling this function.
5095  * \return Number of values to return to Lua.
5096  */
dynamic_tile_api_get_tileset(lua_State * l)5097 int LuaContext::dynamic_tile_api_get_tileset(lua_State* l) {
5098 
5099   return state_boundary_handle(l, [&] {
5100     const DynamicTile& dynamic_tile = *check_dynamic_tile(l, 1);
5101 
5102     const Tileset* tileset = dynamic_tile.get_tileset();
5103     if (tileset) {
5104         push_string(l, tileset->get_id());
5105     }
5106     else {
5107         lua_pushnil(l);
5108     }
5109 
5110     return 1;
5111   });
5112 }
5113 
5114 /**
5115  * \brief Implementation of dynamic_tile:set_tileset().
5116  * \param l The Lua context that is calling this function.
5117  * \return Number of values to return to Lua.
5118  */
dynamic_tile_api_set_tileset(lua_State * l)5119 int LuaContext::dynamic_tile_api_set_tileset(lua_State* l) {
5120 
5121   return state_boundary_handle(l, [&] {
5122     DynamicTile& dynamic_tile = *check_dynamic_tile(l, 1);
5123 
5124     if (lua_isstring(l, 2)) {
5125       const std::string& tileset_id = LuaTools::check_string(l, 2);
5126       dynamic_tile.set_tileset(tileset_id);
5127     }
5128     else if (lua_isnil(l, 2)) {
5129       dynamic_tile.set_tileset(nullptr);
5130     }
5131     else {
5132       LuaTools::type_error(l, 2, "string or nil");
5133     }
5134 
5135     return 0;
5136   });
5137 }
5138 
5139 /**
5140  * \brief Returns whether a value is a userdata of type enemy.
5141  * \param l A Lua context.
5142  * \param index An index in the stack.
5143  * \return \c true if the value at this index is an enemy.
5144  */
is_enemy(lua_State * l,int index)5145 bool LuaContext::is_enemy(lua_State* l, int index) {
5146   return is_userdata(l, index, get_entity_internal_type_name(EntityType::ENEMY));
5147 }
5148 
5149 /**
5150  * \brief Checks that the userdata at the specified index of the stack is an
5151  * enemy and returns it.
5152  * \param l A Lua context.
5153  * \param index An index in the stack.
5154  * \return The enemy.
5155  */
check_enemy(lua_State * l,int index)5156 std::shared_ptr<Enemy> LuaContext::check_enemy(lua_State* l, int index) {
5157   return std::static_pointer_cast<Enemy>(check_userdata(
5158       l, index, get_entity_internal_type_name(EntityType::ENEMY)
5159   ));
5160 }
5161 
5162 /**
5163  * \brief Pushes an enemy userdata onto the stack.
5164  * \param l A Lua context.
5165  * \param enemy An enemy.
5166  */
push_enemy(lua_State * l,Enemy & enemy)5167 void LuaContext::push_enemy(lua_State* l, Enemy& enemy) {
5168   push_userdata(l, enemy);
5169 }
5170 
5171 /**
5172  * \brief Implementation of enemy:get_breed().
5173  * \param l The Lua context that is calling this function.
5174  * \return Number of values to return to Lua.
5175  */
enemy_api_get_breed(lua_State * l)5176 int LuaContext::enemy_api_get_breed(lua_State* l) {
5177 
5178   return state_boundary_handle(l, [&] {
5179     const Enemy& enemy = *check_enemy(l, 1);
5180 
5181     push_string(l, enemy.get_breed());
5182     return 1;
5183   });
5184 }
5185 
5186 /**
5187  * \brief Implementation of enemy:get_life().
5188  * \param l The Lua context that is calling this function.
5189  * \return Number of values to return to Lua.
5190  */
enemy_api_get_life(lua_State * l)5191 int LuaContext::enemy_api_get_life(lua_State* l) {
5192 
5193   return state_boundary_handle(l, [&] {
5194     const Enemy& enemy = *check_enemy(l, 1);
5195 
5196     lua_pushinteger(l, enemy.get_life());
5197     return 1;
5198   });
5199 }
5200 
5201 /**
5202  * \brief Implementation of enemy:set_life().
5203  * \param l The Lua context that is calling this function.
5204  * \return Number of values to return to Lua.
5205  */
enemy_api_set_life(lua_State * l)5206 int LuaContext::enemy_api_set_life(lua_State* l) {
5207 
5208   return state_boundary_handle(l, [&] {
5209     Enemy& enemy = *check_enemy(l, 1);
5210     int life = LuaTools::check_int(l, 2);
5211 
5212     enemy.set_life(life);
5213 
5214     return 0;
5215   });
5216 }
5217 
5218 /**
5219  * \brief Implementation of enemy:add_life().
5220  * \param l The Lua context that is calling this function.
5221  * \return Number of values to return to Lua.
5222  */
enemy_api_add_life(lua_State * l)5223 int LuaContext::enemy_api_add_life(lua_State* l) {
5224 
5225   return state_boundary_handle(l, [&] {
5226     Enemy& enemy = *check_enemy(l, 1);
5227     int points = LuaTools::check_int(l, 2);
5228 
5229     enemy.set_life(enemy.get_life() + points);
5230 
5231     return 0;
5232   });
5233 }
5234 
5235 /**
5236  * \brief Implementation of enemy:remove_life().
5237  * \param l The Lua context that is calling this function.
5238  * \return Number of values to return to Lua.
5239  */
enemy_api_remove_life(lua_State * l)5240 int LuaContext::enemy_api_remove_life(lua_State* l) {
5241 
5242   return state_boundary_handle(l, [&] {
5243     Enemy& enemy = *check_enemy(l, 1);
5244     int points = LuaTools::check_int(l, 2);
5245 
5246     enemy.set_life(enemy.get_life() - points);
5247 
5248     return 0;
5249   });
5250 }
5251 
5252 /**
5253  * \brief Implementation of enemy:get_damage().
5254  * \param l The Lua context that is calling this function.
5255  * \return Number of values to return to Lua.
5256  */
enemy_api_get_damage(lua_State * l)5257 int LuaContext::enemy_api_get_damage(lua_State* l) {
5258 
5259   return state_boundary_handle(l, [&] {
5260     const Enemy& enemy = *check_enemy(l, 1);
5261 
5262     lua_pushinteger(l, enemy.get_damage());
5263     return 1;
5264   });
5265 }
5266 
5267 /**
5268  * \brief Implementation of enemy:set_damage().
5269  * \param l The Lua context that is calling this function.
5270  * \return Number of values to return to Lua.
5271  */
enemy_api_set_damage(lua_State * l)5272 int LuaContext::enemy_api_set_damage(lua_State* l) {
5273 
5274   return state_boundary_handle(l, [&] {
5275     Enemy& enemy = *check_enemy(l, 1);
5276     int damage = LuaTools::check_int(l, 2);
5277 
5278     enemy.set_damage(damage);
5279 
5280     return 0;
5281   });
5282 }
5283 
5284 /**
5285  * \brief Implementation of enemy:is_pushed_back_when_hurt().
5286  * \param l The Lua context that is calling this function.
5287  * \return Number of values to return to Lua.
5288  */
enemy_api_is_pushed_back_when_hurt(lua_State * l)5289 int LuaContext::enemy_api_is_pushed_back_when_hurt(lua_State* l) {
5290 
5291   return state_boundary_handle(l, [&] {
5292     const Enemy& enemy = *check_enemy(l, 1);
5293 
5294     lua_pushboolean(l, enemy.get_pushed_back_when_hurt());
5295     return 1;
5296   });
5297 }
5298 
5299 /**
5300  * \brief Implementation of enemy:set_pushed_back_when_hurt().
5301  * \param l The Lua context that is calling this function.
5302  * \return Number of values to return to Lua.
5303  */
enemy_api_set_pushed_back_when_hurt(lua_State * l)5304 int LuaContext::enemy_api_set_pushed_back_when_hurt(lua_State* l) {
5305 
5306   return state_boundary_handle(l, [&] {
5307     Enemy& enemy = *check_enemy(l, 1);
5308     bool push_back = LuaTools::opt_boolean(l, 2, true);
5309 
5310     enemy.set_pushed_back_when_hurt(push_back);
5311 
5312     return 0;
5313   });
5314 }
5315 
5316 /**
5317  * \brief Implementation of enemy:get_push_hero_on_sword().
5318  * \param l The Lua context that is calling this function.
5319  * \return Number of values to return to Lua.
5320  */
enemy_api_get_push_hero_on_sword(lua_State * l)5321 int LuaContext::enemy_api_get_push_hero_on_sword(lua_State* l) {
5322 
5323   return state_boundary_handle(l, [&] {
5324     const Enemy& enemy = *check_enemy(l, 1);
5325 
5326     lua_pushboolean(l, enemy.get_push_hero_on_sword());
5327     return 1;
5328   });
5329 }
5330 
5331 /**
5332  * \brief Implementation of enemy:set_push_hero_on_sword().
5333  * \param l The Lua context that is calling this function.
5334  * \return Number of values to return to Lua.
5335  */
enemy_api_set_push_hero_on_sword(lua_State * l)5336 int LuaContext::enemy_api_set_push_hero_on_sword(lua_State* l) {
5337 
5338   return state_boundary_handle(l, [&] {
5339     Enemy& enemy = *check_enemy(l, 1);
5340     bool push = LuaTools::opt_boolean(l, 2, true);
5341 
5342     enemy.set_push_hero_on_sword(push);
5343 
5344     return 0;
5345   });
5346 }
5347 
5348 /**
5349  * \brief Implementation of enemy:get_can_hurt_hero_running().
5350  * \param l The Lua context that is calling this function.
5351  * \return Number of values to return to Lua.
5352  */
enemy_api_get_can_hurt_hero_running(lua_State * l)5353 int LuaContext::enemy_api_get_can_hurt_hero_running(lua_State* l) {
5354 
5355   return state_boundary_handle(l, [&] {
5356     const Enemy& enemy = *check_enemy(l, 1);
5357 
5358     lua_pushboolean(l, enemy.get_can_hurt_hero_running());
5359     return 1;
5360   });
5361 }
5362 
5363 /**
5364  * \brief Implementation of enemy:set_can_hurt_hero_running().
5365  * \param l The Lua context that is calling this function.
5366  * \return Number of values to return to Lua.
5367  */
enemy_api_set_can_hurt_hero_running(lua_State * l)5368 int LuaContext::enemy_api_set_can_hurt_hero_running(lua_State* l) {
5369 
5370   return state_boundary_handle(l, [&] {
5371     Enemy& enemy = *check_enemy(l, 1);
5372     bool can_hurt_hero_running = LuaTools::opt_boolean(l, 2, true);
5373 
5374     enemy.set_can_hurt_hero_running(can_hurt_hero_running);
5375 
5376     return 0;
5377   });
5378 }
5379 
5380 /**
5381  * \brief Implementation of enemy:get_hurt_style().
5382  * \param l The Lua context that is calling this function.
5383  * \return Number of values to return to Lua.
5384  */
enemy_api_get_hurt_style(lua_State * l)5385 int LuaContext::enemy_api_get_hurt_style(lua_State* l) {
5386 
5387   return state_boundary_handle(l, [&] {
5388     const Enemy& enemy = *check_enemy(l, 1);
5389 
5390     Enemy::HurtStyle hurt_style = enemy.get_hurt_style();
5391 
5392     push_string(l, Enemy::hurt_style_names.find(hurt_style)->second);
5393     return 1;
5394   });
5395 }
5396 
5397 /**
5398  * \brief Implementation of enemy:set_hurt_style().
5399  * \param l The Lua context that is calling this function.
5400  * \return Number of values to return to Lua.
5401  */
enemy_api_set_hurt_style(lua_State * l)5402 int LuaContext::enemy_api_set_hurt_style(lua_State* l) {
5403 
5404   return state_boundary_handle(l, [&] {
5405     Enemy& enemy = *check_enemy(l, 1);
5406     Enemy::HurtStyle hurt_style = LuaTools::check_enum<Enemy::HurtStyle>(
5407         l, 2, Enemy::hurt_style_names);
5408 
5409     enemy.set_hurt_style(hurt_style);
5410 
5411     return 0;
5412   });
5413 }
5414 
5415 /**
5416  * \brief Implementation of enemy:get_dying_sprite_id().
5417  * \param l The Lua context that is calling this function.
5418  * \return Number of values to return to Lua.
5419  */
enemy_api_get_dying_sprite_id(lua_State * l)5420 int LuaContext::enemy_api_get_dying_sprite_id(lua_State* l) {
5421 
5422   return state_boundary_handle(l, [&] {
5423     const Enemy& enemy = *check_enemy(l, 1);
5424 
5425     const std::string& dying_sprite_id = enemy.get_dying_sprite_id();
5426 
5427     if (dying_sprite_id.empty()) {
5428       lua_pushnil(l);
5429     }
5430     else {
5431       push_string(l, dying_sprite_id);
5432     }
5433     return 1;
5434   });
5435 }
5436 
5437 /**
5438  * \brief Implementation of enemy:set_dying_sprite_id().
5439  * \param l The Lua context that is calling this function.
5440  * \return Number of values to return to Lua.
5441  */
enemy_api_set_dying_sprite_id(lua_State * l)5442 int LuaContext::enemy_api_set_dying_sprite_id(lua_State* l) {
5443 
5444   return state_boundary_handle(l, [&] {
5445     Enemy& enemy = *check_enemy(l, 1);
5446     std::string dying_sprite_id;
5447 
5448     if (lua_isstring(l, 2)) {
5449       dying_sprite_id = LuaTools::check_string(l, 2);
5450     }
5451     else if (!lua_isnil(l, 2)) {
5452       LuaTools::type_error(l, 2, "string or nil");
5453     }
5454 
5455     enemy.set_dying_sprite_id(dying_sprite_id);
5456 
5457     return 0;
5458   });
5459 }
5460 
5461 /**
5462  * \brief Implementation of enemy:get_can_attack().
5463  * \param l The Lua context that is calling this function.
5464  * \return Number of values to return to Lua.
5465  */
enemy_api_get_can_attack(lua_State * l)5466 int LuaContext::enemy_api_get_can_attack(lua_State* l) {
5467 
5468   return state_boundary_handle(l, [&] {
5469     const Enemy& enemy = *check_enemy(l, 1);
5470 
5471     lua_pushboolean(l, enemy.get_can_attack());
5472     return 1;
5473   });
5474 }
5475 
5476 /**
5477  * \brief Implementation of enemy:set_can_attack().
5478  * \param l The Lua context that is calling this function.
5479  * \return Number of values to return to Lua.
5480  */
enemy_api_set_can_attack(lua_State * l)5481 int LuaContext::enemy_api_set_can_attack(lua_State* l) {
5482 
5483   return state_boundary_handle(l, [&] {
5484     Enemy& enemy = *check_enemy(l, 1);
5485     bool can_attack = LuaTools::opt_boolean(l, 2, true);
5486 
5487     enemy.set_can_attack(can_attack);
5488 
5489     return 0;
5490   });
5491 }
5492 
5493 /**
5494  * \brief Implementation of enemy:get_minimum_shield_needed().
5495  * \param l The Lua context that is calling this function.
5496  * \return Number of values to return to Lua.
5497  */
enemy_api_get_minimum_shield_needed(lua_State * l)5498 int LuaContext::enemy_api_get_minimum_shield_needed(lua_State* l) {
5499 
5500   return state_boundary_handle(l, [&] {
5501     const Enemy& enemy = *check_enemy(l, 1);
5502 
5503     int shield_level = enemy.get_minimum_shield_needed();
5504 
5505     lua_pushinteger(l, shield_level);
5506     return 1;
5507   });
5508 }
5509 
5510 /**
5511  * \brief Implementation of enemy:set_minimum_shield_needed().
5512  * \param l The Lua context that is calling this function.
5513  * \return Number of values to return to Lua.
5514  */
enemy_api_set_minimum_shield_needed(lua_State * l)5515 int LuaContext::enemy_api_set_minimum_shield_needed(lua_State* l) {
5516 
5517   return state_boundary_handle(l, [&] {
5518     Enemy& enemy = *check_enemy(l, 1);
5519     int shield_level = LuaTools::check_int(l, 2);
5520 
5521     enemy.set_minimum_shield_needed(shield_level);
5522 
5523     return 0;
5524   });
5525 }
5526 
5527 /**
5528  * \brief Implementation of enemy:get_attack_consequence().
5529  * \param l The Lua context that is calling this function.
5530  * \return Number of values to return to Lua.
5531  */
enemy_api_get_attack_consequence(lua_State * l)5532 int LuaContext::enemy_api_get_attack_consequence(lua_State* l) {
5533 
5534   return state_boundary_handle(l, [&] {
5535     const Enemy& enemy = *check_enemy(l, 1);
5536     EnemyAttack attack = LuaTools::check_enum<EnemyAttack>(l, 2, Enemy::attack_names);
5537 
5538     const EnemyReaction::Reaction& reaction = enemy.get_attack_consequence(attack, nullptr);
5539     if (reaction.type == EnemyReaction::ReactionType::HURT) {
5540       // Return the life damage.
5541       lua_pushinteger(l, reaction.life_lost);
5542     } else if (reaction.type == EnemyReaction::ReactionType::LUA_CALLBACK) {
5543       // Return the callback.
5544       reaction.callback.push(l);
5545     } else {
5546       // Return a string.
5547       push_string(l, enum_to_name(reaction.type));
5548     }
5549     return 1;
5550   });
5551 }
5552 
5553 /**
5554  * \brief Implementation of enemy:set_attack_consequence().
5555  * \param l The Lua context that is calling this function.
5556  * \return Number of values to return to Lua.
5557  */
enemy_api_set_attack_consequence(lua_State * l)5558 int LuaContext::enemy_api_set_attack_consequence(lua_State* l) {
5559 
5560   return state_boundary_handle(l, [&] {
5561     Enemy& enemy = *check_enemy(l, 1);
5562     EnemyAttack attack = LuaTools::check_enum<EnemyAttack>(l, 2, Enemy::attack_names);
5563 
5564     if (lua_isnumber(l, 3)) {
5565       int life_points = LuaTools::check_int(l, 3);
5566       if (life_points < 0) {
5567         std::ostringstream oss;
5568         oss << "Invalid life points number for attack consequence: '"
5569             << life_points << "'";
5570         LuaTools::arg_error(l, 3, oss.str());
5571       }
5572       enemy.set_attack_consequence(attack, EnemyReaction::ReactionType::HURT, life_points);
5573     }
5574     else if (lua_isstring(l, 3)) {
5575       EnemyReaction::ReactionType reaction = LuaTools::check_enum<EnemyReaction::ReactionType>(
5576           l, 3);
5577       enemy.set_attack_consequence(attack, reaction);
5578     }
5579     else if (lua_isfunction(l, 3)) {
5580       ScopedLuaRef callback = LuaTools::check_function(l, 3);
5581       enemy.set_attack_consequence(attack, EnemyReaction::ReactionType::LUA_CALLBACK, 0, callback);
5582     }
5583     else {
5584       LuaTools::type_error(l, 3, "number, string or function");
5585     }
5586 
5587     return 0;
5588   });
5589 }
5590 
5591 /**
5592  * \brief Implementation of enemy:get_attack_consequence_sprite().
5593  * \param l The Lua context that is calling this function.
5594  * \return Number of values to return to Lua.
5595  */
enemy_api_get_attack_consequence_sprite(lua_State * l)5596 int LuaContext::enemy_api_get_attack_consequence_sprite(lua_State* l) {
5597 
5598   return state_boundary_handle(l, [&] {
5599     const Enemy& enemy = *check_enemy(l, 1);
5600     Sprite& sprite = *check_sprite(l, 2);
5601     EnemyAttack attack = LuaTools::check_enum<EnemyAttack>(l, 3, Enemy::attack_names);
5602 
5603     const EnemyReaction::Reaction& reaction = enemy.get_attack_consequence(attack, &sprite);
5604     if (reaction.type == EnemyReaction::ReactionType::HURT) {
5605       // Return the life damage.
5606       lua_pushinteger(l, reaction.life_lost);
5607     }
5608     else if (reaction.type == EnemyReaction::ReactionType::LUA_CALLBACK) {
5609       // Return the callback.
5610       reaction.callback.push(l);
5611     }
5612     else {
5613       // Return a string.
5614       push_string(l, enum_to_name(reaction.type));
5615     }
5616     return 1;
5617   });
5618 }
5619 
5620 /**
5621  * \brief Implementation of enemy:set_attack_consequence_sprite().
5622  * \param l The Lua context that is calling this function.
5623  * \return Number of values to return to Lua.
5624  */
enemy_api_set_attack_consequence_sprite(lua_State * l)5625 int LuaContext::enemy_api_set_attack_consequence_sprite(lua_State* l) {
5626 
5627   return state_boundary_handle(l, [&] {
5628     Enemy& enemy = *check_enemy(l, 1);
5629     Sprite& sprite = *check_sprite(l, 2);
5630     EnemyAttack attack = LuaTools::check_enum<EnemyAttack>(l, 3, Enemy::attack_names);
5631 
5632     if (lua_isnumber(l, 4)) {
5633       int life_points = LuaTools::check_int(l, 4);
5634       if (life_points < 0) {
5635         std::ostringstream oss;
5636         oss << "Invalid life points number for attack consequence: '"
5637             << life_points << "'";
5638         LuaTools::arg_error(l, 4, oss.str());
5639       }
5640       enemy.set_attack_consequence_sprite(sprite, attack, EnemyReaction::ReactionType::HURT, life_points);
5641     }
5642     else if (lua_isstring(l, 4)) {
5643       EnemyReaction::ReactionType reaction = LuaTools::check_enum<EnemyReaction::ReactionType>(
5644           l, 4);
5645       enemy.set_attack_consequence_sprite(sprite, attack, reaction);
5646     }
5647     else if (lua_isfunction(l, 4)) {
5648       ScopedLuaRef callback = LuaTools::check_function(l, 4);
5649       enemy.set_attack_consequence_sprite(sprite, attack, EnemyReaction::ReactionType::LUA_CALLBACK, 0, callback);
5650     }
5651     else {
5652       LuaTools::type_error(l, 3, "number, string or function");
5653     }
5654 
5655     return 0;
5656   });
5657 }
5658 
5659 /**
5660  * \brief Implementation of enemy:set_default_attack_consequences().
5661  * \param l The Lua context that is calling this function.
5662  * \return Number of values to return to Lua.
5663  */
enemy_api_set_default_attack_consequences(lua_State * l)5664 int LuaContext::enemy_api_set_default_attack_consequences(lua_State* l) {
5665 
5666   return state_boundary_handle(l, [&] {
5667     Enemy& enemy = *check_enemy(l, 1);
5668 
5669     enemy.set_default_attack_consequences();
5670 
5671     return 0;
5672   });
5673 }
5674 
5675 /**
5676  * \brief Implementation of enemy:set_default_attack_consequences_sprite().
5677  * \param l The Lua context that is calling this function.
5678  * \return Number of values to return to Lua.
5679  */
enemy_api_set_default_attack_consequences_sprite(lua_State * l)5680 int LuaContext::enemy_api_set_default_attack_consequences_sprite(lua_State* l) {
5681 
5682   return state_boundary_handle(l, [&] {
5683     Enemy& enemy = *check_enemy(l, 1);
5684     Sprite& sprite = *check_sprite(l, 2);
5685 
5686     enemy.set_default_attack_consequences_sprite(sprite);
5687 
5688     return 0;
5689   });
5690 }
5691 
5692 /**
5693  * \brief Implementation of enemy:set_invincible().
5694  * \param l The Lua context that is calling this function.
5695  * \return Number of values to return to Lua.
5696  */
enemy_api_set_invincible(lua_State * l)5697 int LuaContext::enemy_api_set_invincible(lua_State* l) {
5698 
5699   return state_boundary_handle(l, [&] {
5700     Enemy& enemy = *check_enemy(l, 1);
5701 
5702     enemy.set_no_attack_consequences();
5703 
5704     return 0;
5705   });
5706 }
5707 
5708 /**
5709  * \brief Implementation of enemy:set_invincible_sprite().
5710  * \param l The Lua context that is calling this function.
5711  * \return Number of values to return to Lua.
5712  */
enemy_api_set_invincible_sprite(lua_State * l)5713 int LuaContext::enemy_api_set_invincible_sprite(lua_State* l) {
5714 
5715   return state_boundary_handle(l, [&] {
5716     Enemy& enemy = *check_enemy(l, 1);
5717     Sprite& sprite = *check_sprite(l, 2);
5718 
5719     enemy.set_no_attack_consequences_sprite(sprite);
5720 
5721     return 0;
5722   });
5723 }
5724 
5725 /**
5726  * \brief Implementation of enemy:get_treasure().
5727  * \param l The Lua context that is calling this function.
5728  * \return Number of values to return to Lua.
5729  */
enemy_api_get_treasure(lua_State * l)5730 int LuaContext::enemy_api_get_treasure(lua_State* l) {
5731 
5732   return state_boundary_handle(l, [&] {
5733     const Enemy& enemy = *check_enemy(l, 1);
5734     const Treasure& treasure = enemy.get_treasure();
5735 
5736     if (treasure.get_item_name().empty()) {
5737       // No treasure: return nil.
5738       lua_pushnil(l);
5739       return 1;
5740     }
5741 
5742     push_string(l, treasure.get_item_name());
5743     lua_pushinteger(l, treasure.get_variant());
5744     if (!treasure.is_saved()) {
5745       lua_pushnil(l);
5746     }
5747     else {
5748       push_string(l, treasure.get_savegame_variable());
5749     }
5750     return 3;
5751   });
5752 }
5753 
5754 
5755 /**
5756  * \brief Implementation of enemy:set_treasure().
5757  * \param l The Lua context that is calling this function.
5758  * \return Number of values to return to Lua.
5759  */
enemy_api_set_treasure(lua_State * l)5760 int LuaContext::enemy_api_set_treasure(lua_State* l) {
5761 
5762   return state_boundary_handle(l, [&] {
5763     Enemy& enemy = *check_enemy(l, 1);
5764     std::string item_name, savegame_variable;
5765     int variant = 1;
5766 
5767     if (lua_gettop(l) >= 2 && !lua_isnil(l, 2)) {
5768       item_name = LuaTools::check_string(l, 2);
5769     }
5770     if (lua_gettop(l) >= 3 && !lua_isnil(l, 3)) {
5771       variant = LuaTools::check_int(l, 3);
5772     }
5773     if (lua_gettop(l) >= 4 && !lua_isnil(l, 4)) {
5774       savegame_variable = LuaTools::check_string(l, 4);
5775     }
5776 
5777     if (!savegame_variable.empty()
5778         && !LuaTools::is_valid_lua_identifier(savegame_variable)) {
5779       LuaTools::arg_error(l, 4,
5780           std::string("savegame variable identifier expected, got '")
5781       + savegame_variable + "'");
5782     }
5783 
5784     Treasure treasure(enemy.get_game(), item_name, variant, savegame_variable);
5785     enemy.set_treasure(treasure);
5786 
5787     return 0;
5788   });
5789 }
5790 
5791 /**
5792  * \brief Implementation of enemy:is_traversable().
5793  * \param l The Lua context that is calling this function.
5794  * \return Number of values to return to Lua.
5795  */
enemy_api_is_traversable(lua_State * l)5796 int LuaContext::enemy_api_is_traversable(lua_State* l) {
5797 
5798   return state_boundary_handle(l, [&] {
5799     const Enemy& enemy = *check_enemy(l, 1);
5800 
5801     lua_pushboolean(l, enemy.is_traversable());
5802     return 1;
5803   });
5804 }
5805 
5806 /**
5807  * \brief Implementation of enemy:set_traversable().
5808  * \param l The Lua context that is calling this function.
5809  * \return Number of values to return to Lua.
5810  */
enemy_api_set_traversable(lua_State * l)5811 int LuaContext::enemy_api_set_traversable(lua_State* l) {
5812 
5813   return state_boundary_handle(l, [&] {
5814     Enemy& enemy = *check_enemy(l, 1);
5815 
5816     bool traversable = LuaTools::opt_boolean(l, 2, true);
5817 
5818     enemy.set_traversable(traversable);
5819 
5820     return 0;
5821   });
5822 }
5823 
5824 /**
5825  * \brief Implementation of enemy:get_attacking_collision_mode().
5826  * \param l The Lua context that is calling this function.
5827  * \return Number of values to return to Lua.
5828  */
enemy_api_get_attacking_collision_mode(lua_State * l)5829 int LuaContext::enemy_api_get_attacking_collision_mode(lua_State* l) {
5830 
5831   return state_boundary_handle(l, [&] {
5832     const Enemy& enemy = *check_enemy(l, 1);
5833 
5834     push_string(l, enum_to_name(enemy.get_attacking_collision_mode()));
5835     return 1;
5836   });
5837 }
5838 
5839 /**
5840  * \brief Implementation of enemy:set_attacking_collision_mode().
5841  * \param l The Lua context that is calling this function.
5842  * \return Number of values to return to Lua.
5843  */
enemy_api_set_attacking_collision_mode(lua_State * l)5844 int LuaContext::enemy_api_set_attacking_collision_mode(lua_State* l) {
5845 
5846   return state_boundary_handle(l, [&] {
5847     Enemy& enemy = *check_enemy(l, 1);
5848     CollisionMode attacking_collision_mode = LuaTools::check_enum<CollisionMode>(l, 2,
5849         EnumInfoTraits<CollisionMode>::names_no_none_no_custom
5850     );
5851     enemy.set_attacking_collision_mode(attacking_collision_mode);
5852 
5853     return 0;
5854   });
5855 }
5856 
5857 /**
5858  * \brief Implementation of enemy:get_obstacle_behavior().
5859  * \param l The Lua context that is calling this function.
5860  * \return Number of values to return to Lua.
5861  */
enemy_api_get_obstacle_behavior(lua_State * l)5862 int LuaContext::enemy_api_get_obstacle_behavior(lua_State* l) {
5863 
5864   return state_boundary_handle(l, [&] {
5865     const Enemy& enemy = *check_enemy(l, 1);
5866 
5867     Enemy::ObstacleBehavior behavior = enemy.get_obstacle_behavior();
5868 
5869     push_string(l, Enemy::obstacle_behavior_names.find(behavior)->second);
5870     return 1;
5871   });
5872 }
5873 
5874 /**
5875  * \brief Implementation of enemy:set_obstacle_behavior().
5876  * \param l The Lua context that is calling this function.
5877  * \return Number of values to return to Lua.
5878  */
enemy_api_set_obstacle_behavior(lua_State * l)5879 int LuaContext::enemy_api_set_obstacle_behavior(lua_State* l) {
5880 
5881   return state_boundary_handle(l, [&] {
5882     Enemy& enemy = *check_enemy(l, 1);
5883     Enemy::ObstacleBehavior behavior = LuaTools::check_enum<Enemy::ObstacleBehavior>(
5884         l, 2, Enemy::obstacle_behavior_names);
5885 
5886     enemy.set_obstacle_behavior(behavior);
5887 
5888     return 0;
5889   });
5890 }
5891 
5892 /**
5893  * \brief Implementation of enemy:restart().
5894  * \param l The Lua context that is calling this function.
5895  * \return Number of values to return to Lua.
5896  */
enemy_api_restart(lua_State * l)5897 int LuaContext::enemy_api_restart(lua_State* l) {
5898 
5899   return state_boundary_handle(l, [&] {
5900     Enemy& enemy = *check_enemy(l, 1);
5901 
5902     enemy.restart();
5903 
5904     return 0;
5905   });
5906 }
5907 
5908 /**
5909  * \brief Implementation of enemy:hurt().
5910  * \param l The Lua context that is calling this function.
5911  * \return Number of values to return to Lua.
5912  */
enemy_api_hurt(lua_State * l)5913 int LuaContext::enemy_api_hurt(lua_State* l) {
5914 
5915   return state_boundary_handle(l, [&] {
5916     Enemy& enemy = *check_enemy(l, 1);
5917     int life_points = LuaTools::check_int(l, 2);
5918 
5919     if (enemy.is_in_normal_state() && !enemy.is_invulnerable()) {
5920       Hero& hero = enemy.get_map().get_entities().get_hero();
5921       enemy.set_attack_consequence(EnemyAttack::SCRIPT, EnemyReaction::ReactionType::HURT, life_points);
5922       enemy.try_hurt(EnemyAttack::SCRIPT, hero, nullptr);
5923     }
5924 
5925     return 0;
5926   });
5927 }
5928 
5929 /**
5930  * \brief Implementation of enemy:is_immobilized().
5931  * \param l The Lua context that is calling this function.
5932  * \return Number of values to return to Lua.
5933  */
enemy_api_is_immobilized(lua_State * l)5934 int LuaContext::enemy_api_is_immobilized(lua_State* l) {
5935 
5936   return state_boundary_handle(l, [&] {
5937     const Enemy& enemy = *check_enemy(l, 1);
5938 
5939     lua_pushboolean(l, enemy.is_immobilized());
5940     return 1;
5941   });
5942 }
5943 
5944 /**
5945  * \brief Implementation of enemy:immobilize().
5946  * \param l The Lua context that is calling this function.
5947  * \return Number of values to return to Lua.
5948  */
enemy_api_immobilize(lua_State * l)5949 int LuaContext::enemy_api_immobilize(lua_State* l) {
5950 
5951   return state_boundary_handle(l, [&] {
5952     Enemy& enemy = *check_enemy(l, 1);
5953 
5954     if (enemy.is_invulnerable()) {
5955       return 0;
5956     }
5957 
5958     if (enemy.is_in_normal_state() || enemy.is_immobilized()) {
5959       Hero& hero = enemy.get_map().get_entities().get_hero();
5960       enemy.set_attack_consequence(EnemyAttack::SCRIPT, EnemyReaction::ReactionType::IMMOBILIZED, 0);
5961       enemy.try_hurt(EnemyAttack::SCRIPT, hero, nullptr);
5962     }
5963 
5964     return 0;
5965   });
5966 }
5967 
5968 /**
5969  * \brief Implementation of enemy:create_enemy().
5970  * \param l The Lua context that is calling this function.
5971  * \return Number of values to return to Lua.
5972  */
enemy_api_create_enemy(lua_State * l)5973 int LuaContext::enemy_api_create_enemy(lua_State* l) {
5974 
5975   return state_boundary_handle(l, [&] {
5976     Enemy& enemy = *check_enemy(l, 1);
5977     LuaTools::check_type(l, 2, LUA_TTABLE);
5978     const std::string& name = LuaTools::opt_string_field(l, 2, "name", "");
5979     int layer = LuaTools::opt_layer_field(l, 2, "layer", enemy.get_map(), enemy.get_layer());
5980     int x = LuaTools::opt_int_field(l, 2, "x", 0);
5981     int y = LuaTools::opt_int_field(l, 2, "y", 0);
5982     int direction = LuaTools::opt_int_field(l, 2, "direction", 3);
5983     const std::string& breed = LuaTools::check_string_field(l, 2, "breed");
5984     const std::string& savegame_variable = LuaTools::opt_string_field(l, 2, "savegame_variable", "");
5985     const std::string& treasure_name = LuaTools::opt_string_field(l, 2, "treasure_name", "");
5986     int treasure_variant = LuaTools::opt_int_field(l, 2, "treasure_variant", 1);
5987     const std::string& treasure_savegame_variable = LuaTools::opt_string_field(l, 2, "treasure_savegame_variable", "");
5988 
5989     if (!savegame_variable.empty()
5990         && !LuaTools::is_valid_lua_identifier(savegame_variable)) {
5991       LuaTools::arg_error(l, 2, std::string(
5992           "Bad field 'savegame_variable' (invalid savegame variable identifier '")
5993       + savegame_variable + "'");
5994     }
5995 
5996     if (!treasure_savegame_variable.empty()
5997         && !LuaTools::is_valid_lua_identifier(treasure_savegame_variable)) {
5998       LuaTools::arg_error(l, 2, std::string(
5999           "Bad field 'treasure_savegame_variable' (invalid savegame variable identifier '")
6000       + treasure_savegame_variable + "'");
6001     }
6002 
6003     // Make x and y relative to the existing enemy.
6004     x += enemy.get_x();
6005     y += enemy.get_y();
6006 
6007     // Create the new enemy.
6008     Map& map = enemy.get_map();
6009 
6010     if (!map.is_loaded()) {
6011       LuaTools::error(l, "Cannot create enemy: this map is not running");
6012     }
6013 
6014     Game& game = map.get_game();
6015     const EntityPtr& entity = Enemy::create(
6016         game,
6017         breed,
6018         savegame_variable,
6019         name,
6020         layer,
6021         { x, y },
6022         direction,
6023         Treasure(game, treasure_name, treasure_variant, treasure_savegame_variable)
6024     );
6025 
6026     if (entity == nullptr) {
6027       // The enemy is saved as already dead.
6028       lua_pushnil(l);
6029       return 1;
6030     }
6031 
6032     map.get_entities().add_entity(entity);
6033 
6034     push_entity(l, *entity);
6035     return 1;
6036   });
6037 }
6038 
6039 /**
6040  * \brief Returns whether a value is a userdata of type custom entity.
6041  * \param l A Lua context.
6042  * \param index An index in the stack.
6043  * \return \c true if the value at this index is a custom entity.
6044  */
is_custom_entity(lua_State * l,int index)6045 bool LuaContext::is_custom_entity(lua_State* l, int index) {
6046   return is_userdata(l, index, get_entity_internal_type_name(EntityType::CUSTOM));
6047 }
6048 
6049 /**
6050  * \brief Checks that the userdata at the specified index of the stack is a
6051  * custom entity and returns it.
6052  * \param l A Lua context.
6053  * \param index An index in the stack.
6054  * \return The custom entity.
6055  */
check_custom_entity(lua_State * l,int index)6056 std::shared_ptr<CustomEntity> LuaContext::check_custom_entity(lua_State* l, int index) {
6057   return std::static_pointer_cast<CustomEntity>(check_userdata(
6058       l, index, get_entity_internal_type_name(EntityType::CUSTOM)
6059   ));
6060 }
6061 
6062 /**
6063  * \brief Pushes a custom entity userdata onto the stack.
6064  * \param l A Lua context.
6065  * \param custom_entity A custom entity.
6066  */
push_custom_entity(lua_State * l,CustomEntity & entity)6067 void LuaContext::push_custom_entity(lua_State* l, CustomEntity& entity) {
6068   push_userdata(l, entity);
6069 }
6070 
6071 /**
6072  * \brief Calls the specified a Lua traversable test function.
6073  * \param traversable_test_ref Lua ref to a traversable test function.
6074  * \param userdata The object that is testing if it can traverse
6075  * or be traversed by another entity.
6076  * \param other_entity The other entity.
6077  * \return \c true if the traversable test function returned \c true.
6078  */
do_traversable_test_function(const ScopedLuaRef & traversable_test_ref,ExportableToLua & userdata,Entity & other_entity)6079 bool LuaContext::do_traversable_test_function(
6080     const ScopedLuaRef& traversable_test_ref,
6081     ExportableToLua& userdata,
6082     Entity& other_entity) {
6083 
6084   Debug::check_assertion(!traversable_test_ref.is_empty(),
6085       "Missing traversable test function ref"
6086   );
6087 
6088   // Call the test function.
6089   push_ref(current_l, traversable_test_ref);
6090   Debug::check_assertion(lua_isfunction(current_l, -1),
6091       "Traversable test is not a function"
6092   );
6093   push_userdata(current_l, userdata);
6094   push_entity(current_l, other_entity);
6095   if (!LuaTools::call_function(current_l, 2, 1, "traversable test function")) {
6096     // Error in the traversable test function.
6097     return false;
6098   }
6099 
6100   // See its result.
6101   bool traversable = lua_toboolean(current_l, -1);
6102   lua_pop(current_l, 1);
6103 
6104   return traversable;
6105 }
6106 
6107 /**
6108  * \brief Calls the specified a Lua collision test function.
6109  * \param collision_test_ref Lua ref to a collision test function.
6110  * \param custom_entity The custom entity that is testing the collision.
6111  * \param other_entity The entity to test a collision with.
6112  * \return \c true if the collision test function returned \c true.
6113  */
do_custom_entity_collision_test_function(const ScopedLuaRef & collision_test_ref,CustomEntity & custom_entity,Entity & other_entity)6114 bool LuaContext::do_custom_entity_collision_test_function(
6115     const ScopedLuaRef& collision_test_ref,
6116     CustomEntity& custom_entity,
6117     Entity& other_entity
6118 ) {
6119   Debug::check_assertion(!collision_test_ref.is_empty(),
6120       "Missing collision test function"
6121   );
6122 
6123   // Call the test function.
6124   push_ref(current_l, collision_test_ref);
6125   Debug::check_assertion(lua_isfunction(current_l, -1),
6126       "Collision test is not a function"
6127   );
6128   push_custom_entity(current_l, custom_entity);
6129   push_entity(current_l, other_entity);
6130   if (!LuaTools::call_function(current_l, 2, 1, "collision test function")) {
6131     // Error in the collision test function.
6132     return false;
6133   }
6134 
6135   // See its result.
6136   bool collision = lua_toboolean(current_l, -1);
6137   lua_pop(current_l, 1);
6138 
6139   return collision;
6140 }
6141 
6142 /**
6143  * \brief Executes a callback after a custom entity detected a collision.
6144  * \param callback_ref Ref of the function to call.
6145  * \param custom_entity A custom entity that detected a collision.
6146  * \param other_entity The entity that was detected.
6147  */
do_custom_entity_collision_callback(const ScopedLuaRef & callback_ref,CustomEntity & custom_entity,Entity & other_entity)6148 void LuaContext::do_custom_entity_collision_callback(
6149     const ScopedLuaRef& callback_ref,
6150     CustomEntity& custom_entity,
6151     Entity& other_entity
6152 ) {
6153   Debug::check_assertion(!callback_ref.is_empty(),
6154       "Missing collision callback");
6155 
6156   push_ref(current_l, callback_ref);
6157   Debug::check_assertion(lua_isfunction(current_l, -1),
6158       "Collision callback is not a function");
6159   push_custom_entity(current_l, custom_entity);
6160   push_entity(current_l, other_entity);
6161   LuaTools::call_function(current_l, 2, 0, "collision callback");
6162 }
6163 
6164 /**
6165  * \brief Executes a callback after a custom entity detected a pixel-precise
6166  * collision.
6167  * \param callback_ref Ref of the function to call.
6168  * \param custom_entity A custom entity that detected a collision.
6169  * \param other_entity The entity that was detected.
6170  * \param custom_entity_sprite Sprite of the custom entity involved in the
6171  * collision.
6172  * \param other_entity_sprite Sprite of the detected entity involved in the
6173  * collision.
6174  */
do_custom_entity_collision_callback(const ScopedLuaRef & callback_ref,CustomEntity & custom_entity,Entity & other_entity,Sprite & custom_entity_sprite,Sprite & other_entity_sprite)6175 void LuaContext::do_custom_entity_collision_callback(
6176     const ScopedLuaRef& callback_ref,
6177     CustomEntity& custom_entity,
6178     Entity& other_entity,
6179     Sprite& custom_entity_sprite,
6180     Sprite& other_entity_sprite) {
6181 
6182   Debug::check_assertion(!callback_ref.is_empty(),
6183       "Missing sprite collision callback"
6184   );
6185 
6186   push_ref(current_l, callback_ref);
6187   Debug::check_assertion(lua_isfunction(current_l, -1),
6188       "Sprite collision callback is not a function");
6189   push_custom_entity(current_l, custom_entity);
6190   push_entity(current_l, other_entity);
6191   push_sprite(current_l, custom_entity_sprite);
6192   push_sprite(current_l, other_entity_sprite);
6193   LuaTools::call_function(current_l, 4, 0, "collision callback");
6194 }
6195 
6196 /**
6197  * \brief Implementation of custom_entity:get_model().
6198  * \param l The Lua context that is calling this function.
6199  * \return Number of values to return to Lua.
6200  */
custom_entity_api_get_model(lua_State * l)6201 int LuaContext::custom_entity_api_get_model(lua_State* l) {
6202 
6203   return state_boundary_handle(l, [&] {
6204     const CustomEntity& entity = *check_custom_entity(l, 1);
6205 
6206     push_string(l, entity.get_model());
6207     return 1;
6208   });
6209 }
6210 
6211 /**
6212  * \brief Implementation of custom_entity:get_direction().
6213  * \param l The Lua context that is calling this function.
6214  * \return Number of values to return to Lua.
6215  */
custom_entity_api_get_direction(lua_State * l)6216 int LuaContext::custom_entity_api_get_direction(lua_State* l) {
6217 
6218   return state_boundary_handle(l, [&] {
6219     const CustomEntity& entity = *check_custom_entity(l, 1);
6220 
6221     lua_pushinteger(l, entity.get_sprites_direction());
6222     return 1;
6223   });
6224 }
6225 
6226 /**
6227  * \brief Implementation of custom_entity:set_direction().
6228  * \param l The Lua context that is calling this function.
6229  * \return Number of values to return to Lua.
6230  */
custom_entity_api_set_direction(lua_State * l)6231 int LuaContext::custom_entity_api_set_direction(lua_State* l) {
6232 
6233   return state_boundary_handle(l, [&] {
6234     CustomEntity& entity = *check_custom_entity(l, 1);
6235     int direction = LuaTools::check_int(l, 2);
6236 
6237     entity.set_sprites_direction(direction);
6238 
6239     return 0;
6240   });
6241 }
6242 
6243 /**
6244  * \brief Implementation of custom_entity:set_traversable_by().
6245  * \param l The Lua context that is calling this function.
6246  * \return Number of values to return to Lua.
6247  */
custom_entity_api_set_traversable_by(lua_State * l)6248 int LuaContext::custom_entity_api_set_traversable_by(lua_State* l) {
6249 
6250   return state_boundary_handle(l, [&] {
6251     CustomEntity& entity = *check_custom_entity(l, 1);
6252 
6253     bool type_specific = false;
6254     EntityType type = EntityType::TILE;
6255     int index = 2;
6256     if (lua_isstring(l, index)) {
6257       ++index;
6258       type_specific = true;
6259       type = LuaTools::check_enum<EntityType>(
6260           l, 2
6261       );
6262     }
6263 
6264     if (lua_isnil(l, index)) {
6265       // Reset the setting.
6266       if (!type_specific) {
6267         entity.reset_traversable_by_entities();
6268       }
6269       else {
6270         entity.reset_traversable_by_entities(type);
6271       }
6272     }
6273     else if (lua_isboolean(l, index)) {
6274       // Boolean value.
6275       bool traversable = lua_toboolean(l, index);
6276       if (!type_specific) {
6277         entity.set_traversable_by_entities(traversable);
6278       }
6279       else {
6280         entity.set_traversable_by_entities(type, traversable);
6281       }
6282     }
6283     else if (lua_isfunction(l, index)) {
6284       // Custom boolean function.
6285 
6286       const ScopedLuaRef& traversable_test_ref = LuaTools::check_function(l, index);
6287       if (!type_specific) {
6288         entity.set_traversable_by_entities(traversable_test_ref);
6289       }
6290       else {
6291         entity.set_traversable_by_entities(type, traversable_test_ref);
6292       }
6293     }
6294     else {
6295       LuaTools::type_error(l, index, "boolean, function or nil");
6296     }
6297 
6298     return 0;
6299   });
6300 }
6301 
6302 /**
6303  * \brief Implementation of custom_entity:set_can_traverse().
6304  * \param l The Lua context that is calling this function.
6305  * \return Number of values to return to Lua.
6306  */
custom_entity_api_set_can_traverse(lua_State * l)6307 int LuaContext::custom_entity_api_set_can_traverse(lua_State* l) {
6308 
6309   return state_boundary_handle(l, [&] {
6310     CustomEntity& entity = *check_custom_entity(l, 1);
6311 
6312     bool type_specific = false;
6313     EntityType type = EntityType::TILE;
6314     int index = 2;
6315     if (lua_isstring(l, index)) {
6316       ++index;
6317       type_specific = true;
6318       type = LuaTools::check_enum<EntityType>(
6319           l, 2
6320       );
6321     }
6322 
6323     if (lua_isnil(l, index)) {
6324       // Reset the setting.
6325       if (!type_specific) {
6326         entity.reset_can_traverse_entities();
6327       }
6328       else {
6329         entity.reset_can_traverse_entities(type);
6330       }
6331     }
6332     else if (lua_isboolean(l, index)) {
6333       // Boolean value.
6334       bool traversable = lua_toboolean(l, index);
6335       if (!type_specific) {
6336         entity.set_can_traverse_entities(traversable);
6337       }
6338       else {
6339         entity.set_can_traverse_entities(type, traversable);
6340       }
6341     }
6342     else if (lua_isfunction(l, index)) {
6343       // Custom boolean function.
6344       const ScopedLuaRef& traversable_test_ref = LuaTools::check_function(l, index);
6345       if (!type_specific) {
6346         entity.set_can_traverse_entities(traversable_test_ref);
6347       }
6348       else {
6349         entity.set_can_traverse_entities(type, traversable_test_ref);
6350       }
6351     }
6352     else {
6353       LuaTools::type_error(l, index, "boolean, function or nil");
6354     }
6355 
6356     return 0;
6357   });
6358 }
6359 
6360 /**
6361  * \brief Implementation of custom_entity:can_traverse_ground().
6362  * \param l The Lua context that is calling this function.
6363  * \return Number of values to return to Lua.
6364  */
custom_entity_api_can_traverse_ground(lua_State * l)6365 int LuaContext::custom_entity_api_can_traverse_ground(lua_State* l) {
6366 
6367   return state_boundary_handle(l, [&] {
6368     const CustomEntity& entity = *check_custom_entity(l, 1);
6369     Ground ground = LuaTools::check_enum<Ground>(l, 2);
6370 
6371     bool traversable = entity.can_traverse_ground(ground);
6372 
6373     lua_pushboolean(l, traversable);
6374     return 1;
6375   });
6376 }
6377 
6378 /**
6379  * \brief Implementation of custom_entity:set_can_traverse_ground().
6380  * \param l The Lua context that is calling this function.
6381  * \return Number of values to return to Lua.
6382  */
custom_entity_api_set_can_traverse_ground(lua_State * l)6383 int LuaContext::custom_entity_api_set_can_traverse_ground(lua_State* l) {
6384 
6385   return state_boundary_handle(l, [&] {
6386     CustomEntity& entity = *check_custom_entity(l, 1);
6387     Ground ground = LuaTools::check_enum<Ground>(l, 2);
6388     if (lua_isnil(l, 3)) {
6389       entity.reset_can_traverse_ground(ground);
6390     }
6391     else {
6392       if (!lua_isboolean(l, 3)) {
6393         LuaTools::type_error(l, 3, "boolean or nil");
6394       }
6395       bool traversable = lua_toboolean(l, 3);
6396 
6397       entity.set_can_traverse_ground(ground, traversable);
6398     }
6399 
6400     return 0;
6401   });
6402 }
6403 
6404 /**
6405  * \brief Implementation of custom_entity:add_collision_test().
6406  * \param l The Lua context that is calling this function.
6407  * \return Number of values to return to Lua.
6408  */
custom_entity_api_add_collision_test(lua_State * l)6409 int LuaContext::custom_entity_api_add_collision_test(lua_State* l) {
6410 
6411   return state_boundary_handle(l, [&] {
6412     CustomEntity& entity = *check_custom_entity(l, 1);
6413 
6414     const ScopedLuaRef& callback_ref = LuaTools::check_function(l, 3);
6415 
6416     if (lua_isstring(l, 2)) {
6417       // Built-in collision test.
6418       CollisionMode collision_mode = LuaTools::check_enum<CollisionMode>(l, 2,
6419           EnumInfoTraits<CollisionMode>::names_no_none_no_custom
6420       );
6421       entity.add_collision_test(collision_mode, callback_ref);
6422     }
6423     else if (lua_isfunction(l, 2)) {
6424       // Custom collision test.
6425       const ScopedLuaRef& collision_test_ref = LuaTools::check_function(l, 2);
6426       entity.add_collision_test(collision_test_ref, callback_ref);
6427     }
6428     else {
6429       LuaTools::type_error(l, 2, "string or function");
6430     }
6431 
6432     return 0;
6433   });
6434 }
6435 
6436 /**
6437  * \brief Implementation of custom_entity:clear_collision_tests().
6438  * \param l The Lua context that is calling this function.
6439  * \return Number of values to return to Lua.
6440  */
custom_entity_api_clear_collision_tests(lua_State * l)6441 int LuaContext::custom_entity_api_clear_collision_tests(lua_State* l) {
6442 
6443   return state_boundary_handle(l, [&] {
6444     CustomEntity& entity = *check_custom_entity(l, 1);
6445 
6446     entity.clear_collision_tests();
6447 
6448     return 0;
6449   });
6450 }
6451 
6452 /**
6453  * \brief Implementation of custom_entity:get_modified_ground().
6454  * \param l The Lua context that is calling this function.
6455  * \return Number of values to return to Lua.
6456  */
custom_entity_api_get_modified_ground(lua_State * l)6457 int LuaContext::custom_entity_api_get_modified_ground(lua_State* l) {
6458 
6459   return state_boundary_handle(l, [&] {
6460     const CustomEntity& entity = *check_custom_entity(l, 1);
6461 
6462     const Ground modified_ground = entity.get_modified_ground();
6463 
6464     if (modified_ground == Ground::EMPTY) {
6465       lua_pushnil(l);
6466     }
6467     else {
6468       push_string(l, enum_to_name(modified_ground));
6469     }
6470     return 1;
6471   });
6472 }
6473 
6474 /**
6475  * \brief Implementation of custom_entity:set_modified_ground().
6476  * \param l The Lua context that is calling this function.
6477  * \return Number of values to return to Lua.
6478  */
custom_entity_api_set_modified_ground(lua_State * l)6479 int LuaContext::custom_entity_api_set_modified_ground(lua_State* l) {
6480 
6481   return state_boundary_handle(l, [&] {
6482     CustomEntity& entity = *check_custom_entity(l, 1);
6483     Ground modified_ground = Ground::EMPTY;
6484 
6485     if (lua_gettop(l) == 1) {
6486       LuaTools::type_error(l, 2, "string or nil");
6487     }
6488     if (!lua_isnil(l, 2)) {
6489       modified_ground = LuaTools::check_enum<Ground>(l, 2);
6490     }
6491 
6492     entity.set_modified_ground(modified_ground);
6493     return 0;
6494   });
6495 }
6496 
6497 /**
6498  * \brief Implementation of custom_entity:get_tiled().
6499  * \param l The Lua context that is calling this function.
6500  * \return Number of values to return to Lua.
6501  */
custom_entity_api_is_tiled(lua_State * l)6502 int LuaContext::custom_entity_api_is_tiled(lua_State* l) {
6503 
6504   return state_boundary_handle(l, [&] {
6505     const CustomEntity& entity = *check_custom_entity(l, 1);
6506 
6507     lua_pushboolean(l, entity.is_tiled());
6508     return 1;
6509   });
6510 }
6511 
6512 /**
6513  * \brief Implementation of custom_entity:set_tiled().
6514  * \param l The Lua context that is calling this function.
6515  * \return Number of values to return to Lua.
6516  */
custom_entity_api_set_tiled(lua_State * l)6517 int LuaContext::custom_entity_api_set_tiled(lua_State* l) {
6518 
6519   return state_boundary_handle(l, [&] {
6520     CustomEntity& entity = *check_custom_entity(l, 1);
6521     bool tiled = LuaTools::opt_boolean(l, 2, true);
6522 
6523     entity.set_tiled(tiled);
6524 
6525     return 0;
6526   });
6527 }
6528 
6529 /**
6530  * \brief Implementation of custom_entity:get_follow_streams().
6531  * \param l The Lua context that is calling this function.
6532  * \return Number of values to return to Lua.
6533  */
custom_entity_api_get_follow_streams(lua_State * l)6534 int LuaContext::custom_entity_api_get_follow_streams(lua_State* l) {
6535 
6536   return state_boundary_handle(l, [&] {
6537     const CustomEntity& entity = *check_custom_entity(l, 1);
6538 
6539     lua_pushboolean(l, entity.get_follow_streams());
6540     return 1;
6541   });
6542 }
6543 
6544 /**
6545  * \brief Implementation of custom_entity:set_follow_streams().
6546  * \param l The Lua context that is calling this function.
6547  * \return Number of values to return to Lua.
6548  */
custom_entity_api_set_follow_streams(lua_State * l)6549 int LuaContext::custom_entity_api_set_follow_streams(lua_State* l) {
6550 
6551   return state_boundary_handle(l, [&] {
6552     CustomEntity& entity = *check_custom_entity(l, 1);
6553     bool follow_streams = LuaTools::opt_boolean(l, 2, true);
6554 
6555     entity.set_follow_streams(follow_streams);
6556 
6557     return 0;
6558   });
6559 }
6560 
6561 /**
6562  * \brief Calls the on_update() method of a Lua map entity.
6563  *
6564  * Does nothing if the method is not defined.
6565  *
6566  * \param entity A map entity.
6567  */
entity_on_update(Entity & entity)6568 void LuaContext::entity_on_update(Entity& entity) {
6569 
6570   // This particular method is tried so often that we want to optimize
6571   // the std::string construction.
6572   static const std::string method_name = "on_update";
6573   if (!userdata_has_field(entity, method_name)) {
6574     return;
6575   }
6576 
6577   push_entity(current_l, entity);
6578   on_update();
6579   lua_pop(current_l, 1);
6580 }
6581 
6582 /**
6583  * \brief Calls the on_suspended() method of a Lua map entity.
6584  *
6585  * Does nothing if the method is not defined.
6586  *
6587  * \param entity A map entity.
6588  * \param suspended \c true if the entity is suspended.
6589  */
entity_on_suspended(Entity & entity,bool suspended)6590 void LuaContext::entity_on_suspended(Entity& entity, bool suspended) {
6591 
6592   if (!userdata_has_field(entity, "on_suspended")) {
6593     return;
6594   }
6595   run_on_main([this, &entity, suspended](lua_State* l){
6596     push_entity(l, entity);
6597     on_suspended(suspended);
6598     lua_pop(l, 1);
6599   });
6600 }
6601 
6602 /**
6603  * \brief Calls the on_created() method of a Lua map entity.
6604  *
6605  * Does nothing if the method is not defined.
6606  *
6607  * \param entity A map entity.
6608  */
entity_on_created(Entity & entity)6609 void LuaContext::entity_on_created(Entity& entity) {
6610 
6611   if (!userdata_has_field(entity, "on_created")) {
6612     return;
6613   }
6614   run_on_main([this, &entity](lua_State* l){
6615     push_entity(l, entity);
6616     on_created();
6617     lua_pop(l, 1);
6618   });
6619 }
6620 
6621 /**
6622  * \brief Calls the on_removed() method of a Lua map entity if it is defined.
6623  *
6624  * Also stops timers associated to the entity.
6625  *
6626  * \param entity A map entity.
6627  */
entity_on_removed(Entity & entity)6628 void LuaContext::entity_on_removed(Entity& entity) {
6629   run_on_main([this, &entity](lua_State* l){
6630     push_entity(l, entity);
6631     if (userdata_has_field(entity, "on_removed")) {
6632       on_removed();
6633     }
6634     remove_timers(-1);  // Stop timers associated to this entity.
6635     lua_pop(l, 1);
6636   });
6637 }
6638 
6639 /**
6640  * \brief Calls the on_enabled() method of a Lua map entity.
6641  *
6642  * Does nothing if the method is not defined.
6643  *
6644  * \param entity A map entity.
6645  */
entity_on_enabled(Entity & entity)6646 void LuaContext::entity_on_enabled(Entity& entity) {
6647 
6648   if (!userdata_has_field(entity, "on_enabled")) {
6649     return;
6650   }
6651   run_on_main([this, &entity](lua_State* l){
6652     push_entity(l, entity);
6653     on_enabled();
6654     lua_pop(l, 1);
6655   });
6656 }
6657 
6658 /**
6659  * \brief Calls the on_disabled() method of a Lua map entity.
6660  *
6661  * Does nothing if the method is not defined.
6662  *
6663  * \param entity A map entity.
6664  */
entity_on_disabled(Entity & entity)6665 void LuaContext::entity_on_disabled(Entity& entity) {
6666 
6667   if (!userdata_has_field(entity, "on_disabled")) {
6668     return;
6669   }
6670   run_on_main([this, &entity](lua_State* l){
6671     push_entity(l, entity);
6672     on_disabled();
6673     lua_pop(l, 1);
6674   });
6675 }
6676 
6677 /**
6678  * \brief Calls the on_pre_draw() method of a Lua map entity.
6679  *
6680  * Does nothing if the method is not defined.
6681  *
6682  * \param entity A map entity.
6683  * \param camera The camera where to draw the entity.
6684  */
entity_on_pre_draw(Entity & entity,Camera & camera)6685 void LuaContext::entity_on_pre_draw(Entity& entity, Camera& camera) {
6686 
6687   if (!userdata_has_field(entity, "on_pre_draw")) {
6688     return;
6689   }
6690   run_on_main([this, &entity, &camera](lua_State* l){
6691     push_entity(l, entity);
6692     on_pre_draw(camera);
6693     lua_pop(l, 1);
6694   });
6695 }
6696 
6697 /**
6698  * \brief Calls the on_post_draw() method of a Lua map entity.
6699  *
6700  * Does nothing if the method is not defined.
6701  *
6702  * \param entity A map entity.
6703  * \param camera The camera where to draw the entity.
6704  */
entity_on_post_draw(Entity & entity,Camera & camera)6705 void LuaContext::entity_on_post_draw(Entity& entity, Camera& camera) {
6706 
6707   if (!userdata_has_field(entity, "on_post_draw")) {
6708     return;
6709   }
6710   run_on_main([this, &entity, &camera](lua_State* l){
6711     push_entity(l, entity);
6712     on_post_draw(camera);
6713     lua_pop(l, 1);
6714   });
6715 }
6716 
6717 /**
6718  * \brief Calls the on_position_changed() method of a Lua map entity.
6719  *
6720  * Does nothing if the method is not defined.
6721  *
6722  * \param entity A map entity.
6723  * \param xy The new coordinates.
6724  * \param layer The new layer.
6725  */
entity_on_position_changed(Entity & entity,const Point & xy,int layer)6726 void LuaContext::entity_on_position_changed(
6727     Entity& entity, const Point& xy, int layer) {
6728 
6729   if (!userdata_has_field(entity, "on_position_changed")) {
6730     return;
6731   }
6732   run_on_main([this, &entity, xy, layer](lua_State* l){
6733     push_entity(l, entity);
6734     on_position_changed(xy, layer);
6735     lua_pop(l, 1);
6736   });
6737 }
6738 
6739 /**
6740  * \brief Calls the on_obstacle_reached() method of a Lua map entity.
6741  *
6742  * Does nothing if the method is not defined.
6743  *
6744  * \param entity A map entity.
6745  * \param movement The movement that reached an obstacle.
6746  */
entity_on_obstacle_reached(Entity & entity,Movement & movement)6747 void LuaContext::entity_on_obstacle_reached(
6748     Entity& entity, Movement& movement) {
6749 
6750   if (!userdata_has_field(entity, "on_obstacle_reached")) {
6751     return;
6752   }
6753   run_on_main([this, &entity, &movement](lua_State* l) {
6754     push_entity(l, entity);
6755     on_obstacle_reached(movement);
6756     lua_pop(l, 1);
6757   });
6758 }
6759 
6760 /**
6761  * \brief Calls the on_movement_started() method of a Lua map entity.
6762  *
6763  * Does nothing if the method is not defined.
6764  *
6765  * \param entity A map entity.
6766  * \param movement The movement that has just started.
6767  */
entity_on_movement_started(Entity & entity,Movement & movement)6768 void LuaContext::entity_on_movement_started(
6769     Entity& entity, Movement& movement) {
6770 
6771   if (!userdata_has_field(entity, "on_movement_started")) {
6772     return;
6773   }
6774 
6775   run_on_main([this, &entity, &movement](lua_State* l) {
6776     push_entity(l, entity);
6777     on_movement_started(movement);
6778     lua_pop(l, 1);
6779   });
6780 }
6781 
6782 /**
6783  * \brief Calls the on_movement_changed() method of a Lua map entity.
6784  *
6785  * Does nothing if the method is not defined.
6786  *
6787  * \param entity A map entity.
6788  * \param movement Its movement.
6789  */
entity_on_movement_changed(Entity & entity,Movement & movement)6790 void LuaContext::entity_on_movement_changed(
6791     Entity& entity, Movement& movement) {
6792 
6793   if (!userdata_has_field(entity, "on_movement_changed")) {
6794     return;
6795   }
6796 
6797   run_on_main([this, &entity, &movement](lua_State* l) {
6798     push_entity(l, entity);
6799     on_movement_changed(movement);
6800     lua_pop(l, 1);
6801   });
6802 }
6803 
6804 /**
6805  * \brief Calls the on_movement_finished() method of a Lua map entity.
6806  *
6807  * Does nothing if the method is not defined.
6808  *
6809  * \param entity A map entity.
6810  */
entity_on_movement_finished(Entity & entity)6811 void LuaContext::entity_on_movement_finished(Entity& entity) {
6812 
6813   if (!userdata_has_field(entity, "on_movement_finished")) {
6814     return;
6815   }
6816 
6817   run_on_main([this, &entity](lua_State* l) {
6818     push_entity(l, entity);
6819     on_movement_finished();
6820     lua_pop(l, 1);
6821   });
6822 }
6823 
6824 /**
6825  * \brief Calls the on_interaction() method of a Lua map entity.
6826  *
6827  * Does nothing if the method is not defined.
6828  *
6829  * \param entity A map entity.
6830  * \return \c true if an interaction occurred.
6831  */
entity_on_interaction(Entity & entity)6832 bool LuaContext::entity_on_interaction(Entity& entity) {
6833 
6834   if (!userdata_has_field(entity, "on_interaction")) {
6835     return false;
6836   }
6837 
6838   //TODO make this on main
6839   check_callback_thread();
6840 
6841   push_entity(current_l, entity);
6842   bool exists = on_interaction();
6843   lua_pop(current_l, 1);
6844 
6845 
6846   return exists;
6847 }
6848 
6849 /**
6850  * \brief Calls the on_interaction_item() method of a Lua map entity.
6851  *
6852  * Does nothing if the method is not defined.
6853  *
6854  * \param entity A map entity.
6855  * \param item_used The equipment item used.
6856  * \return \c true if an interaction occurred.
6857  */
entity_on_interaction_item(Entity & entity,EquipmentItem & item_used)6858 bool LuaContext::entity_on_interaction_item(
6859     Entity& entity, EquipmentItem& item_used) {
6860 
6861   if (!userdata_has_field(entity, "on_interaction_item")) {
6862     return false;
6863   }
6864 
6865    //TODO make this on main
6866   check_callback_thread();
6867 
6868   push_entity(current_l, entity);
6869   bool result = on_interaction_item(item_used);
6870   lua_pop(current_l, 1);
6871   return result;
6872 }
6873 
6874 /**
6875  * \brief Calls the on_state_changing() method of a Lua entity.
6876  *
6877  * Does nothing if the method is not defined.
6878  *
6879  * \param entity A map entity.
6880  * \param state_state Name of the current state.
6881  * \param next_state_name Name of the state about to start.
6882  */
entity_on_state_changing(Entity & entity,const std::string & state_name,const std::string & next_state_name)6883 void LuaContext::entity_on_state_changing(
6884     Entity& entity, const std::string& state_name, const std::string& next_state_name) {
6885 
6886   if (!userdata_has_field(entity, "on_state_changing")) {
6887     return;
6888   }
6889   run_on_main([this, &entity, state_name, next_state_name](lua_State* l){
6890     push_entity(l, entity);
6891     on_state_changing(state_name, next_state_name);
6892     lua_pop(l, 1);
6893   });
6894 }
6895 
6896 /**
6897  * \brief Calls the on_state_changed() method of a Lua entity.
6898  *
6899  * Does nothing if the method is not defined.
6900  *
6901  * \param entity A map entity.
6902  * \param new_state_name A name describing the new state.
6903  */
entity_on_state_changed(Entity & entity,const std::string & new_state_name)6904 void LuaContext::entity_on_state_changed(
6905     Entity& entity, const std::string& new_state_name) {
6906 
6907   if (!userdata_has_field(entity, "on_state_changed")) {
6908     return;
6909   }
6910  run_on_main([this, &entity, new_state_name](lua_State* l){
6911     push_entity(l, entity);
6912     on_state_changed(new_state_name);
6913     lua_pop(l, 1);
6914   });
6915 }
6916 
6917 /**
6918  * \brief Calls the on_lifting() method of a Lua entity.
6919  *
6920  * Does nothing if the method is not defined.
6921  *
6922  * \param entity The entity being lifted.
6923  * \param carrier Entity that is lifting the first one.
6924  * \param carried_object Carried object created to replace
6925  * the entity being lifted.
6926  */
entity_on_lifting(Entity & entity,Entity & carrier,CarriedObject & carried_object)6927 void LuaContext::entity_on_lifting(
6928     Entity& entity,
6929     Entity& carrier,
6930     CarriedObject& carried_object
6931 ) {
6932 
6933   if (!userdata_has_field(entity, "on_lifting")) {
6934     return;
6935   }
6936   run_on_main([this, &entity, &carrier, &carried_object](lua_State* l){
6937     push_entity(l, entity);
6938     on_lifting(carrier, carried_object);
6939     lua_pop(l, 1);
6940   });
6941 }
6942 
6943 /**
6944  * \brief Calls the on_taking_damage() method of a Lua hero.
6945  *
6946  * Does nothing if the method is not defined.
6947  *
6948  * \param hero The hero.
6949  * \param damage The damage to take.
6950  * \return \c true if the event is defined.
6951  */
hero_on_taking_damage(Hero & hero,int damage)6952 bool LuaContext::hero_on_taking_damage(Hero& hero, int damage) {
6953 
6954   if (!userdata_has_field(hero, "on_taking_damage")) {
6955     return false;
6956   }
6957   //TODO make in main
6958   check_callback_thread();
6959 
6960   push_hero(current_l, hero);
6961   bool exists = on_taking_damage(damage);
6962   lua_pop(current_l, 1);
6963   return exists;
6964 }
6965 
6966 /**
6967  * \brief Calls the on_activated() method of a Lua destination.
6968  *
6969  * Does nothing if the method is not defined.
6970  *
6971  * \param destination A destination.
6972  */
destination_on_activated(Destination & destination)6973 void LuaContext::destination_on_activated(Destination& destination) {
6974 
6975   if (!userdata_has_field(destination, "on_activated")) {
6976     return;
6977   }
6978   run_on_main([this, &destination](lua_State* l){
6979     push_entity(l, destination);
6980     on_activated();
6981     lua_pop(l, 1);
6982   });
6983 }
6984 
6985 /**
6986  * \brief Calls the on_activated() method of a Lua teletransporter.
6987  *
6988  * Does nothing if the method is not defined.
6989  *
6990  * \param teletransporter A teletransporter.
6991  */
teletransporter_on_activated(Teletransporter & teletransporter)6992 void LuaContext::teletransporter_on_activated(Teletransporter& teletransporter) {
6993 
6994   if (!userdata_has_field(teletransporter, "on_activated")) {
6995     return;
6996   }
6997   run_on_main([this, &teletransporter](lua_State* l){
6998     push_teletransporter(l, teletransporter);
6999     on_activated();
7000     lua_pop(l, 1);
7001   });
7002 }
7003 
7004 /**
7005  * \brief Calls the on_collision_fire() method of a Lua NPC.
7006  *
7007  * Does nothing if the method is not defined.
7008  *
7009  * \param npc An NPC.
7010  */
npc_on_collision_fire(Npc & npc)7011 void LuaContext::npc_on_collision_fire(Npc& npc) {
7012 
7013   if (!userdata_has_field(npc, "on_collision_fire")) {
7014     return;
7015   }
7016   run_on_main([this, &npc](lua_State* l){
7017     push_npc(l, npc);
7018     on_collision_fire();
7019     lua_pop(l, 1);
7020   });
7021 }
7022 
7023 /**
7024  * \brief Calls the on_lifted() method of a Lua carried object.
7025  *
7026  * Does nothing if the method is not defined.
7027  *
7028  * \param carried_object A carried object.
7029  */
carried_object_on_lifted(CarriedObject & carried_object)7030 void LuaContext::carried_object_on_lifted(CarriedObject& carried_object) {
7031 
7032   if (!userdata_has_field(carried_object, "on_lifted")) {
7033     return;
7034   }
7035   run_on_main([this, &carried_object](lua_State* l){
7036     push_carried_object(l, carried_object);
7037     on_lifted();
7038     lua_pop(l, 1);
7039   });
7040 }
7041 
7042 
7043 /**
7044  * \brief Calls the on_thrown() method of a Lua carried object.
7045  *
7046  * Does nothing if the method is not defined.
7047  *
7048  * \param carried_object A carried object.
7049  */
carried_object_on_thrown(CarriedObject & carried_object)7050 void LuaContext::carried_object_on_thrown(CarriedObject& carried_object) {
7051 
7052   if (!userdata_has_field(carried_object, "on_thrown")) {
7053     return;
7054   }
7055   run_on_main([this, &carried_object](lua_State* l){
7056     push_carried_object(l, carried_object);
7057     on_thrown();
7058     lua_pop(l, 1);
7059   });
7060 }
7061 
7062 
7063 /**
7064  * \brief Calls the on_breaking() method of a Lua carried object.
7065  *
7066  * Does nothing if the method is not defined.
7067  *
7068  * \param carried_object A carried object.
7069  */
carried_object_on_breaking(CarriedObject & carried_object)7070 void LuaContext::carried_object_on_breaking(CarriedObject& carried_object) {
7071 
7072   if (!userdata_has_field(carried_object, "on_breaking")) {
7073     return;
7074   }
7075   run_on_main([this, &carried_object](lua_State* l){
7076     push_carried_object(l, carried_object);
7077     on_breaking();
7078     lua_pop(l, 1);
7079   });
7080 }
7081 
7082 /**
7083  * \brief Calls the on_moving() method of a Lua block.
7084  *
7085  * Does nothing if the method is not defined.
7086  *
7087  * \param block a block.
7088  */
block_on_moving(Block & block)7089 void LuaContext::block_on_moving(Block& block) {
7090 
7091   if (!userdata_has_field(block, "on_moving")) {
7092     return;
7093   }
7094   run_on_main([this, &block](lua_State* l){
7095     push_block(l, block);
7096     on_moving();
7097     lua_pop(l, 1);
7098   });
7099 }
7100 
7101 /**
7102  * \brief Calls the on_moved() method of a Lua block.
7103  *
7104  * Does nothing if the method is not defined.
7105  *
7106  * \param block a block.
7107  */
block_on_moved(Block & block)7108 void LuaContext::block_on_moved(Block& block) {
7109 
7110   if (!userdata_has_field(block, "on_moved")) {
7111     return;
7112   }
7113   run_on_main([this, &block](lua_State* l){
7114     push_block(l, block);
7115     on_moved();
7116     lua_pop(l, 1);
7117   });
7118 }
7119 
7120 /**
7121  * \brief Calls the on_opened() method of a Lua chest.
7122  *
7123  * Does nothing if the method is not defined.
7124  *
7125  * \param chest A chest.
7126  * \param treasure The treasure obtained.
7127  * \return \c true if the on_opened() method is defined.
7128  */
chest_on_opened(Chest & chest,const Treasure & treasure)7129 bool LuaContext::chest_on_opened(Chest& chest, const Treasure& treasure) {
7130 
7131   if (!userdata_has_field(chest, "on_opened")) {
7132     return false;
7133   }
7134 
7135   //TODO make this on main
7136   check_callback_thread();
7137 
7138   push_chest(current_l, chest);
7139   bool exists = on_opened(treasure);
7140   lua_pop(current_l, 1);
7141   return exists;
7142 }
7143 
7144 /**
7145  * \brief Calls the on_activated() method of a Lua switch.
7146  *
7147  * Does nothing if the method is not defined.
7148  *
7149  * \param sw A switch.
7150  */
switch_on_activated(Switch & sw)7151 void LuaContext::switch_on_activated(Switch& sw) {
7152 
7153   if (!userdata_has_field(sw, "on_activated")) {
7154     return;
7155   }
7156 
7157   run_on_main([this, &sw](lua_State* l){
7158     push_switch(l, sw);
7159     on_activated();
7160     lua_pop(l, 1);
7161   });
7162 }
7163 
7164 /**
7165  * \brief Calls the on_inactivated() method of a Lua switch.
7166  *
7167  * Does nothing if the method is not defined.
7168  *
7169  * \param sw A switch.
7170  */
switch_on_inactivated(Switch & sw)7171 void LuaContext::switch_on_inactivated(Switch& sw) {
7172 
7173   if (!userdata_has_field(sw, "on_inactivated")) {
7174     return;
7175   }
7176 
7177   run_on_main([this, &sw](lua_State* l){
7178     push_switch(l, sw);
7179     on_inactivated();
7180     lua_pop(l, 1);
7181   });
7182 }
7183 
7184 /**
7185  * \brief Calls the on_left() method of a Lua switch.
7186  *
7187  * Does nothing if the method is not defined.
7188  *
7189  * \param sw A switch.
7190  */
switch_on_left(Switch & sw)7191 void LuaContext::switch_on_left(Switch& sw) {
7192 
7193   if (!userdata_has_field(sw, "on_left")) {
7194     return;
7195   }
7196 
7197   run_on_main([this, &sw](lua_State* l){
7198     push_switch(l, sw);
7199     on_left();
7200     lua_pop(l, 1);
7201   });
7202 }
7203 
7204 /**
7205  * \brief Calls the on_activated() method of a Lua sensor.
7206  *
7207  * Does nothing if the method is not defined.
7208  *
7209  * \param sensor A sensor.
7210  */
sensor_on_activated(Sensor & sensor)7211 void LuaContext::sensor_on_activated(Sensor& sensor) {
7212 
7213   if (!userdata_has_field(sensor, "on_activated")) {
7214     return;
7215   }
7216 
7217   run_on_main([this, &sensor](lua_State* l){
7218     push_entity(l, sensor);
7219     on_activated();
7220     lua_pop(l, 1);
7221   });
7222 }
7223 
7224 /**
7225  * \brief Calls the on_activated_repeat() method of a Lua sensor.
7226  *
7227  * Does nothing if the method is not defined.
7228  *
7229  * \param sensor A sensor.
7230  */
sensor_on_activated_repeat(Sensor & sensor)7231 void LuaContext::sensor_on_activated_repeat(Sensor& sensor) {
7232 
7233   if (!userdata_has_field(sensor, "on_activated_repeat")) {
7234     return;
7235   }
7236   run_on_main([this, &sensor](lua_State* l){
7237     push_entity(l, sensor);
7238     on_activated_repeat();
7239     lua_pop(l, 1);
7240   });
7241 }
7242 
7243 /**
7244  * \brief Calls the on_left() method of a Lua sensor.
7245  * \param sensor A sensor.
7246  */
sensor_on_left(Sensor & sensor)7247 void LuaContext::sensor_on_left(Sensor& sensor) {
7248 
7249   if (!userdata_has_field(sensor, "on_left")) {
7250     return;
7251   }
7252   run_on_main([this, &sensor](lua_State* l){
7253     push_entity(l, sensor);
7254     on_left();
7255     lua_pop(l, 1);
7256   });
7257 }
7258 
7259 /**
7260  * \brief Calls the on_collision_explosion() method of a Lua sensor.
7261  *
7262  * Does nothing if the method is not defined.
7263  *
7264  * \param sensor A sensor.
7265  */
sensor_on_collision_explosion(Sensor & sensor)7266 void LuaContext::sensor_on_collision_explosion(Sensor& sensor) {
7267 
7268   if (!userdata_has_field(sensor, "on_collision_explosion")) {
7269     return;
7270   }
7271   run_on_main([this, &sensor](lua_State* l){
7272     push_entity(l, sensor);
7273     on_collision_explosion();
7274     lua_pop(l, 1);
7275   });
7276 }
7277 
7278 /**
7279  * \brief Calls the on_activating() method of a Lua separator.
7280  *
7281  * Does nothing if the method is not defined.
7282  *
7283  * \param separator A separator.
7284  * \param direction4 Direction of the traversal.
7285  */
separator_on_activating(Separator & separator,int direction4)7286 void LuaContext::separator_on_activating(Separator& separator, int direction4) {
7287 
7288   if (!userdata_has_field(separator, "on_activating")) {
7289     return;
7290   }
7291   run_on_main([this, &separator, direction4](lua_State* l){
7292     push_entity(l, separator);
7293     on_activating(direction4);
7294     lua_pop(l, 1);
7295   });
7296 }
7297 
7298 /**
7299  * \brief Calls the on_activated() method of a Lua separator.
7300  *
7301  * Does nothing if the method is not defined.
7302  *
7303  * \param separator A separator.
7304  * \param direction4 Direction of the traversal.
7305  */
separator_on_activated(Separator & separator,int direction4)7306 void LuaContext::separator_on_activated(Separator& separator, int direction4) {
7307 
7308   if (!userdata_has_field(separator, "on_activated")) {
7309     return;
7310   }
7311   run_on_main([this, &separator, direction4](lua_State* l){
7312     push_entity(l, separator);
7313     on_activated(direction4);
7314     lua_pop(l, 1);
7315   });
7316 }
7317 
7318 /**
7319  * \brief Calls the on_opened() method of a Lua door.
7320  *
7321  * Does nothing if the method is not defined.
7322  *
7323  * \param door A door.
7324  */
door_on_opened(Door & door)7325 void LuaContext::door_on_opened(Door& door) {
7326 
7327   if (!userdata_has_field(door, "on_opened")) {
7328     return;
7329   }
7330   run_on_main([this, &door](lua_State* l){
7331     push_door(l, door);
7332     on_opened();
7333     lua_pop(l, 1);
7334   });
7335 }
7336 
7337 /**
7338  * \brief Calls the on_closed() method of a Lua door.
7339  *
7340  * Does nothing if the method is not defined.
7341  *
7342  * \param door A door.
7343  */
door_on_closed(Door & door)7344 void LuaContext::door_on_closed(Door& door) {
7345 
7346   if (!userdata_has_field(door, "on_closed")) {
7347     return;
7348   }
7349   run_on_main([this, &door](lua_State* l){
7350     push_door(l, door);
7351     on_closed();
7352     lua_pop(l, 1);
7353   });
7354 }
7355 
7356 /**
7357  * \brief Calls the on_buying() method of a Lua shop treasure.
7358  *
7359  * Does nothing if the method is not defined.
7360  *
7361  * \param shop_treasure A shop treasure.
7362  * \return \c true if the player is allowed to buy the treasure.
7363  */
shop_treasure_on_buying(ShopTreasure & shop_treasure)7364 bool LuaContext::shop_treasure_on_buying(ShopTreasure& shop_treasure) {
7365 
7366   if (!userdata_has_field(shop_treasure, "on_buying")) {
7367     return true;
7368   }
7369 
7370   //TODO make this on main
7371   check_callback_thread();
7372 
7373   push_shop_treasure(current_l, shop_treasure);
7374   bool result = on_buying();
7375   lua_pop(current_l, 1);
7376   return result;
7377 }
7378 
7379 /**
7380  * \brief Calls the on_bought() method of a Lua shop treasure.
7381  *
7382  * Does nothing if the method is not defined.
7383  *
7384  * \param shop_treasure A shop treasure.
7385  */
shop_treasure_on_bought(ShopTreasure & shop_treasure)7386 void LuaContext::shop_treasure_on_bought(ShopTreasure& shop_treasure) {
7387 
7388   if (!userdata_has_field(shop_treasure, "on_bought")) {
7389     return;
7390   }
7391 
7392   run_on_main([this, &shop_treasure](lua_State* l){
7393     push_shop_treasure(l, shop_treasure);
7394     on_bought();
7395     lua_pop(l, 1);
7396   });
7397 }
7398 
7399 /**
7400  * \brief Calls the on_looked() method of a Lua destructible.
7401  *
7402  * Does nothing if the method is not defined.
7403  *
7404  * \param destructible A destructible object.
7405  */
destructible_on_looked(Destructible & destructible)7406 void LuaContext::destructible_on_looked(Destructible& destructible) {
7407 
7408   if (!userdata_has_field(destructible, "on_looked")) {
7409     return;
7410   }
7411   run_on_main([this, &destructible](lua_State* l){
7412     push_destructible(l, destructible);
7413     on_looked();
7414     lua_pop(l, 1);
7415   });
7416 }
7417 
7418 /**
7419  * \brief Calls the on_cut() method of a Lua destructible.
7420  *
7421  * Does nothing if the method is not defined.
7422  *
7423  * \param destructible A destructible object.
7424  */
destructible_on_cut(Destructible & destructible)7425 void LuaContext::destructible_on_cut(Destructible& destructible) {
7426 
7427   if (!userdata_has_field(destructible, "on_cut")) {
7428     return;
7429   }
7430   run_on_main([this, &destructible](lua_State* l){
7431     push_destructible(l, destructible);
7432     on_cut();
7433     lua_pop(l, 1);
7434   });
7435 }
7436 
7437 /**
7438  * \brief Calls the on_exploded() method of a Lua destructible.
7439  *
7440  * Does nothing if the method is not defined.
7441  *
7442  * \param destructible A destructible object.
7443  */
destructible_on_exploded(Destructible & destructible)7444 void LuaContext::destructible_on_exploded(Destructible& destructible) {
7445 
7446   if (!userdata_has_field(destructible, "on_exploded")) {
7447     return;
7448   }
7449   run_on_main([this, &destructible](lua_State* l){
7450     push_destructible(l, destructible);
7451     on_exploded();
7452     lua_pop(l, 1);
7453   });
7454 }
7455 
7456 /**
7457  * \brief Calls the on_regenerating() method of a Lua destructible.
7458  *
7459  * Does nothing if the method is not defined.
7460  *
7461  * \param destructible A destructible object.
7462  */
destructible_on_regenerating(Destructible & destructible)7463 void LuaContext::destructible_on_regenerating(Destructible& destructible) {
7464 
7465   if (!userdata_has_field(destructible, "on_regenerating")) {
7466     return;
7467   }
7468 
7469   run_on_main([this, &destructible](lua_State* l){
7470     push_destructible(l, destructible);
7471     on_regenerating();
7472     lua_pop(l, 1);
7473   });
7474 }
7475 
7476 /**
7477  * \brief Calls the on_restarted() method of a Lua enemy if it is defined.
7478  *
7479  * Also stops timers associated to the entity.
7480  *
7481  * \param enemy An enemy.
7482  */
enemy_on_restarted(Enemy & enemy)7483 void LuaContext::enemy_on_restarted(Enemy& enemy) {
7484   run_on_main([this, &enemy](lua_State* l){
7485     push_enemy(l, enemy);
7486     remove_timers(-1);  // Stop timers associated to this enemy.
7487     if (userdata_has_field(enemy, "on_restarted")) {
7488       on_restarted();
7489     }
7490     lua_pop(l, 1);
7491   });
7492 }
7493 
7494 /**
7495  * \brief Calls the on_collision_enemy() method of a Lua enemy.
7496  *
7497  * Does nothing if the method is not defined.
7498  *
7499  * \param enemy An enemy.
7500  * \param other_enemy Another enemy colliding with the first one.
7501  * \param other_sprite Colliding sprite of the other enemy.
7502  * \param this_sprite Colliding sprite of the first enemy.
7503  */
enemy_on_collision_enemy(Enemy & enemy,Enemy & other_enemy,Sprite & other_sprite,Sprite & this_sprite)7504 void LuaContext::enemy_on_collision_enemy(Enemy& enemy,
7505     Enemy& other_enemy, Sprite& other_sprite, Sprite& this_sprite) {
7506 
7507   if (!userdata_has_field(enemy, "on_collision_enemy")) {
7508     return;
7509   }
7510   run_on_main([&](lua_State* l){
7511     push_enemy(l, enemy);
7512     on_collision_enemy(other_enemy, other_sprite, this_sprite);
7513     lua_pop(l, 1);
7514   });
7515 }
7516 
7517 /**
7518  * \brief Calls the on_custom_attack_received() method of a Lua enemy.
7519  *
7520  * Does nothing if the method is not defined.
7521  *
7522  * \param enemy An enemy.
7523  * \param attack The attack received.
7524  * \param sprite The sprite that receives the attack if any.
7525  */
enemy_on_custom_attack_received(Enemy & enemy,EnemyAttack attack,Sprite * sprite)7526 void LuaContext::enemy_on_custom_attack_received(Enemy& enemy,
7527     EnemyAttack attack, Sprite* sprite) {
7528 
7529   if (!userdata_has_field(enemy, "on_custom_attack_received")) {
7530     return;
7531   }
7532   run_on_main([&, attack, sprite](lua_State* l){
7533     push_enemy(l, enemy);
7534     on_custom_attack_received(attack, sprite);
7535     lua_pop(l, 1);
7536   });
7537 }
7538 
7539 /**
7540  * \brief Calls the on_hurt_by_sword() method of a Lua enemy if it is defined.
7541  * \param enemy An enemy.
7542  * \param hero The hero whose sword is hitting the enemy.
7543  * \param enemy_sprite Sprite of the enemy that gets hits.
7544  * \return \c true if the method is defined.
7545  */
enemy_on_hurt_by_sword(Enemy & enemy,Hero & hero,Sprite & enemy_sprite)7546 bool LuaContext::enemy_on_hurt_by_sword(
7547     Enemy& enemy, Hero& hero, Sprite& enemy_sprite) {
7548 
7549   if (!userdata_has_field(enemy, "on_hurt_by_sword")) {
7550     return false;
7551   }
7552 
7553   //TODO make this on main
7554   check_callback_thread();
7555 
7556   push_enemy(current_l, enemy);
7557   bool exists = on_hurt_by_sword(hero, enemy_sprite);
7558   lua_pop(current_l, 1);
7559   return exists;
7560 }
7561 
7562 /**
7563  * \brief Calls the on_hurt() method of a Lua enemy if it is defined.
7564  *
7565  * Also stops timers associated to the enemy.
7566  *
7567  * \param enemy An enemy.
7568  * \param attack The attack received.
7569  */
enemy_on_hurt(Enemy & enemy,EnemyAttack attack)7570 void LuaContext::enemy_on_hurt(Enemy& enemy, EnemyAttack attack) {
7571 
7572   run_on_main([this, &enemy, attack](lua_State* l){
7573     push_enemy(l, enemy);
7574     remove_timers(-1);  // Stop timers associated to this enemy.
7575     if (userdata_has_field(enemy, "on_hurt")) {
7576       on_hurt(attack);
7577     }
7578     lua_pop(l, 1);
7579   });
7580 }
7581 
7582 /**
7583  * \brief Calls the on_dying() method of a Lua enemy if it is defined.
7584  *
7585  * Also stops timers associated to the enemy.
7586  *
7587  * \param enemy An enemy.
7588  */
enemy_on_dying(Enemy & enemy)7589 void LuaContext::enemy_on_dying(Enemy& enemy) {
7590   run_on_main([this, &enemy](lua_State* l){
7591     push_enemy(l, enemy);
7592     remove_timers(-1);  // Stop timers associated to this enemy.
7593     if (userdata_has_field(enemy, "on_dying")) {
7594       on_dying();
7595     }
7596     lua_pop(l, 1);
7597   });
7598 }
7599 
7600 /**
7601  * \brief Calls the on_dead() method of a Lua enemy.
7602  *
7603  * Does nothing if the method is not defined.
7604  *
7605  * \param enemy An enemy.
7606  */
enemy_on_dead(Enemy & enemy)7607 void LuaContext::enemy_on_dead(Enemy& enemy) {
7608 
7609   if (!userdata_has_field(enemy, "on_dead")) {
7610     return;
7611   }
7612   run_on_main([this, &enemy](lua_State* l){
7613     push_enemy(l, enemy);
7614     on_dead();
7615     lua_pop(l, 1);
7616   });
7617 }
7618 
7619 /**
7620  * \brief Calls the on_immobilized() method of a Lua enemy if it is defined.
7621  *
7622  * Also stops timers associated to the enemy.
7623  *
7624  * \param enemy An enemy.
7625  */
enemy_on_immobilized(Enemy & enemy)7626 void LuaContext::enemy_on_immobilized(Enemy& enemy) {
7627   run_on_main([this, &enemy](lua_State* l){
7628     push_enemy(l, enemy);
7629     remove_timers(-1);  // Stop timers associated to this enemy.
7630     if (userdata_has_field(enemy, "on_immobilized")) {
7631       on_immobilized();
7632     }
7633     lua_pop(l, 1);
7634   });
7635 }
7636 
7637 /**
7638  * \brief Calls the on_attacking_hero() method of a Lua enemy.
7639  *
7640  * Does nothing if the method is not defined.
7641  *
7642  * \param enemy An enemy.
7643  * \param hero The hero attacked.
7644  * \param attacker_sprite Enemy's sprite that caused the collision or nullptr.
7645  * \return \c true if the method is defined.
7646  */
enemy_on_attacking_hero(Enemy & enemy,Hero & hero,Sprite * attacker_sprite)7647 bool LuaContext::enemy_on_attacking_hero(Enemy& enemy, Hero& hero, Sprite* attacker_sprite) {
7648 
7649   if (!userdata_has_field(enemy, "on_attacking_hero")) {
7650     return false;
7651   }
7652 
7653   // TODO make this on main
7654   check_callback_thread();
7655 
7656   push_enemy(current_l, enemy);
7657   bool exists = on_attacking_hero(hero, attacker_sprite);
7658   lua_pop(current_l, 1);
7659   return exists;
7660 }
7661 
7662 /**
7663  * \brief Calls the on_ground_below_changed() method of a Lua custom entity.
7664  *
7665  * Does nothing if the method is not defined.
7666  *
7667  * \param custom_entity A custom entity.
7668  * \param ground_below The new ground below this entity.
7669  */
custom_entity_on_ground_below_changed(CustomEntity & custom_entity,Ground ground_below)7670 void LuaContext::custom_entity_on_ground_below_changed(
7671     CustomEntity& custom_entity, Ground ground_below) {
7672 
7673   if (!userdata_has_field(custom_entity, "on_ground_below_changed")) {
7674     return;
7675   }
7676 
7677   run_on_main([this, &custom_entity, ground_below](lua_State* l) {
7678     push_custom_entity(l, custom_entity);
7679     on_ground_below_changed(ground_below);
7680     lua_pop(l, 1);
7681   });
7682 }
7683 
7684 }
7685 
7686