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/core/AbilityInfo.h"
18 #include "solarus/core/CurrentQuest.h"
19 #include "solarus/core/Debug.h"
20 #include "solarus/core/Equipment.h"
21 #include "solarus/core/EquipmentItem.h"
22 #include "solarus/core/Logger.h"
23 #include "solarus/core/Map.h"
24 #include "solarus/core/QuestFiles.h"
25 #include "solarus/core/QuestProperties.h"
26 #include "solarus/core/Timer.h"
27 #include "solarus/core/Treasure.h"
28 #include "solarus/entities/Block.h"
29 #include "solarus/entities/CarriedObject.h"
30 #include "solarus/entities/Chest.h"
31 #include "solarus/entities/CustomEntity.h"
32 #include "solarus/entities/Destination.h"
33 #include "solarus/entities/Door.h"
34 #include "solarus/entities/Enemy.h"
35 #include "solarus/entities/EnemyAttack.h"
36 #include "solarus/entities/GroundInfo.h"
37 #include "solarus/entities/Npc.h"
38 #include "solarus/entities/Pickable.h"
39 #include "solarus/entities/Sensor.h"
40 #include "solarus/entities/ShopTreasure.h"
41 #include "solarus/entities/Switch.h"
42 #include "solarus/entities/Tileset.h"
43 #include "solarus/lua/ExportableToLuaPtr.h"
44 #include "solarus/lua/LuaContext.h"
45 #include "solarus/lua/LuaTools.h"
46 #include "solarus/core/Arguments.h"
47 #include <sstream>
48
49 namespace Solarus {
50
51 LuaContext* LuaContext::lua_context;
52
53 /**
54 * \brief Creates a Lua context.
55 * \param main_loop The Solarus main loop manager.
56 */
LuaContext(MainLoop & main_loop)57 LuaContext::LuaContext(MainLoop& main_loop):
58 current_l(nullptr),
59 main_loop(main_loop) {
60
61 }
62
63 /**
64 * \brief Destroys this Lua context.
65 */
~LuaContext()66 LuaContext::~LuaContext() {
67
68 this->exit();
69 }
70
71 /**
72 * \brief Returns the LuaContext object that encapsulates a Lua state.
73 * \param l A Lua state.
74 * \return The LuaContext object encapsulating this Lua state.
75 */
get()76 LuaContext& LuaContext::get() {
77 Debug::check_assertion(lua_context,"No lua context available");
78 return *lua_context;
79 }
80
81 /**
82 * \brief Returns the internal Lua state encapsulated by this LuaContext object.
83 * \return The internal Lua state.
84 */
get_internal_state()85 lua_State* LuaContext::get_internal_state() {
86 return current_l;
87 }
88
89 /**
90 * \brief Returns the internal Lua state encapsulated by this LuaContext object.
91 * \return The internal Lua state.
92 */
get_main_state()93 lua_State* LuaContext::get_main_state() {
94 return main_l;
95 }
96
97 /**
98 * \brief Returns the Solarus main loop object.
99 * \return The main loop manager.
100 */
get_main_loop()101 MainLoop& LuaContext::get_main_loop() {
102 return main_loop;
103 }
104
105 /**
106 * \brief Initializes Lua.
107 */
initialize(const Arguments & args)108 void LuaContext::initialize(const Arguments& args) {
109
110 // Create an execution context.
111 main_l = current_l = luaL_newstate();
112 lua_atpanic(current_l, l_panic);
113 luaL_openlibs(current_l);
114
115 print_lua_version();
116
117 // Associate this LuaContext object to the lua_State pointer.
118 lua_context = this;
119
120 // Create a table that will keep track of all userdata.
121 // --
122 lua_newtable(current_l);
123 // all_udata
124 lua_newtable(current_l);
125 // all_udata meta
126 lua_pushstring(current_l, "v");
127 // all_udata meta "v"
128 lua_setfield(current_l, -2, "__mode");
129 // all_udata meta
130 lua_setmetatable(current_l, -2);
131 // all_udata
132 lua_setfield(current_l, LUA_REGISTRYINDEX, "sol.all_userdata");
133 // --
134
135 // Allow userdata to be indexable if they want.
136 lua_newtable(current_l);
137 // udata_tables
138 lua_setfield(current_l, LUA_REGISTRYINDEX, "sol.userdata_tables");
139 // --
140
141 // Create the sol table that will contain the whole Solarus API.
142 lua_newtable(current_l);
143 lua_setglobal(current_l, "sol");
144
145 // Register the C++ functions and types accessible by Lua.
146 register_modules();
147
148 // Make require() able to load Lua files even from the
149 // data.solarus or data.solarus.zip archive.
150 // --
151 lua_getglobal(current_l, "sol");
152 // -- sol
153 lua_pushcfunction(current_l, l_loader);
154 // -- sol loader
155 lua_setfield(current_l, -2, "loader");
156 // -- sol
157 luaL_dostring(current_l, "table.insert(package.loaders, 2, sol.loader)");
158 // -- sol
159 lua_pushnil(current_l);
160 // -- sol nil
161 lua_setfield(current_l, -2, "loader");
162 // -- sol
163 lua_pop(current_l, 1);
164 // --
165
166 // Make sure that stdout gets flushed when Lua scripts output new lines.
167 // This is not always the case by default.
168 luaL_dostring(current_l, "io.stdout:setvbuf(\"line\")");
169
170 // Initially set the language if there is only one declared.
171 const std::map<std::string, std::string>& languages = CurrentQuest::get_resources(ResourceType::LANGUAGE);
172 if (languages.size() == 1) {
173 CurrentQuest::set_language(languages.begin()->first);
174 }
175
176 Debug::check_assertion(lua_gettop(current_l) == 0, "Non-empty Lua stack after initialization");
177
178
179 //Do the script passed as arg
180 std::string arg_script = args.get_argument_value("-s");
181 if(!arg_script.empty()) {
182 Debug::warning("Running script arg \"" + arg_script + "\"");
183 do_string(arg_script,"script argument (-s)");
184 }
185
186 // Execute the main file.
187 do_file_if_exists("main");
188
189 Debug::check_assertion(lua_gettop(current_l) == 0, "Non-empty Lua stack after running main.lua");
190
191 main_on_started();
192 }
193
194 /**
195 * \brief Cleans Lua.
196 */
exit()197 void LuaContext::exit() {
198
199 if (current_l != nullptr) {
200 // Call sol.main.on_finished() if it exists.
201 main_on_finished();
202
203 // Destroy unfinished objects.
204 destroy_menus();
205 destroy_timers();
206 destroy_drawables();
207 userdata_close_lua();
208
209 // Finalize Lua.
210 lua_close(current_l);
211 //lua_contexts.erase(l);
212 lua_context = nullptr;
213 current_l = nullptr;
214 main_l = nullptr;
215 }
216 }
217
218 /**
219 * \brief Updates the Lua world.
220 *
221 * This function is called at each cycle.
222 * sol.main.on_update() is called if it exists.
223 */
update()224 void LuaContext::update() {
225
226 // Make sure the stack does not leak.
227 Debug::check_assertion(lua_gettop(main_l) == 0,
228 "Non-empty stack before LuaContext::update()"
229 );
230
231 Debug::check_assertion(current_l == main_l,
232 "Not on the main lua thread to execute lua update");
233
234 update_drawables();
235
236 Debug::check_assertion(current_l == main_l,
237 "Not on the main lua thread after updating drawable");
238 update_movements();
239
240 Debug::check_assertion(current_l == main_l,
241 "Not on the main lua thread after updating movements");
242
243 update_menus();
244
245 Debug::check_assertion(current_l == main_l,
246 "Not on the main lua thread after updating menus");
247
248 update_timers();
249
250 Debug::check_assertion(current_l == main_l,
251 "Not on the main lua thread after updating timers");
252
253 // Call sol.main.on_update().
254 main_on_update();
255
256 //Call cross state callbacks
257 while(!cross_state_callbacks.empty()) {
258 const auto& f = cross_state_callbacks.front();
259 f(current_l);
260 cross_state_callbacks.pop();
261 }
262
263 current_l = main_l; //Ensure we run again on the main thread
264
265 Debug::check_assertion(lua_gettop(main_l) == 0,
266 "Non-empty stack after LuaContext::update()"
267 );
268 }
269
270 /**
271 * \brief Notifies Lua that an input event has just occurred.
272 *
273 * The appropriate callback in sol.main is notified.
274 *
275 * \param event The input event to handle.
276 * \return \c true if the event was handled and should stop being propagated.
277 */
notify_input(const InputEvent & event)278 bool LuaContext::notify_input(const InputEvent& event) {
279
280 Debug::check_assertion(lua_gettop(current_l) == 0,
281 "Non-empty stack before LuaContext::notify_input()"
282 );
283
284 // Call the appropriate callback in sol.main (if it exists).
285 const bool handled = main_on_input(event);
286
287 Debug::check_assertion(lua_gettop(current_l) == 0,
288 "Non-empty stack after LuaContext::notify_input()"
289 );
290
291 return handled;
292 }
293
294 /**
295 * \brief Notifies Lua that a map has just been started.
296 *
297 * The Lua file of this map is automatically loaded.
298 *
299 * \param map The map started.
300 * \param destination The destination point used if it is a normal one,
301 * nullptr otherwise.
302 */
run_map(Map & map,const std::shared_ptr<Destination> & destination)303 void LuaContext::run_map(Map& map, const std::shared_ptr<Destination>& destination) {
304
305 // Compute the file name, depending on the id of the map.
306 std::string file_name = std::string("maps/") + map.get_id();
307
308 // Load the map's code.
309 if (load_file(file_name)) {
310 // map_fun
311 // Set a special environment to access map entities like global variables.
312 lua_newtable(current_l);
313 // map_fun env
314 lua_newtable(current_l);
315 // map_fun env env_mt
316 push_map(current_l, map);
317 // map_fun env env_mt map
318 // Set our special __index function that gets entities on-demand.
319 lua_pushcclosure(current_l, l_get_map_entity_or_global, 1);
320 // map_fun env env_mt __index
321 lua_setfield(current_l, -2, "__index");
322 // map_fun env env_mt
323 // We are changing the environment, so we need to also define __newindex
324 // with its usual setting (the global table).
325 lua_pushvalue(current_l, LUA_GLOBALSINDEX);
326 // map_fun env env_mt _G
327 lua_setfield(current_l, -2, "__newindex");
328 // map_fun env env_mt
329 lua_setmetatable(current_l, -2);
330 // map_fun env
331 lua_setfenv(current_l, -2);
332 // map_fun
333
334 // Run the map's code with the map userdata as parameter.
335 push_map(current_l, map);
336 call_function(1, 0, file_name.c_str());
337 }
338
339 // Call the map:on_started() callback.
340 map_on_started(map, destination);
341 }
342
343 /**
344 * \brief Notifies Lua that a map has just been suspended or resumed.
345 * \param map A map.
346 * \param suspended \c true if it is suspended, false if it is resumed.
347 */
notify_map_suspended(Map & map,bool suspended)348 void LuaContext::notify_map_suspended(Map& map, bool suspended) {
349
350 notify_timers_map_suspended(suspended); // Notify timers.
351 map_on_suspended(map, suspended); // Call map:on_suspended()
352 }
353
354 /**
355 * \brief Notifies the Lua world that an equipment item has just been created.
356 *
357 * The Lua file of this item is automatically loaded.
358 *
359 * \param item The item.
360 */
run_item(EquipmentItem & item)361 void LuaContext::run_item(EquipmentItem& item) {
362
363 // Compute the file name, depending on the id of the equipment item.
364 std::string file_name = std::string("items/") + item.get_name();
365
366 // Load the item's code.
367 if (load_file(file_name)) {
368
369 // Run it with the item userdata as parameter.
370 push_item(current_l, item);
371 call_function(1, 0, file_name.c_str());
372
373 // Call the item:on_created() callback.
374 item_on_created(item);
375 }
376 }
377
378 /**
379 * \brief Notifies the Lua world that an enemy has just been added to the map.
380 *
381 * The Lua file of this enemy is automatically loaded.
382 *
383 * \param enemy The enemy.
384 */
run_enemy(Enemy & enemy)385 void LuaContext::run_enemy(Enemy& enemy) {
386
387 // Compute the file name, depending on enemy's breed.
388 std::string file_name = std::string("enemies/") + enemy.get_breed();
389
390 // Load the enemy's code.
391 if (load_file(file_name)) {
392
393 // Run it with the enemy userdata as parameter.
394 push_enemy(current_l, enemy);
395 call_function(1, 0, file_name.c_str());
396 }
397
398 // TODO parse Lua only once for each breed.
399 }
400
401 /**
402 * \brief Notifies the Lua world that a custom entity has just been added to
403 * the map.
404 *
405 * The Lua file of this entity if any is automatically loaded.
406 *
407 * \param custom_entity The custom entity.
408 */
run_custom_entity(CustomEntity & custom_entity)409 void LuaContext::run_custom_entity(CustomEntity& custom_entity) {
410
411 const std::string& model = custom_entity.get_model();
412
413 if (model.empty()) {
414 // No Lua model file to run for this entity.
415 return;
416 }
417
418 // Compute the file name depending on the model.
419 std::string file_name = std::string("entities/") + model;
420
421 // Load the entity's code.
422 if (load_file(file_name)) {
423
424 // Run it with the entity userdata as parameter.
425 push_custom_entity(current_l, custom_entity);
426 call_function(1, 0, file_name.c_str());
427 }
428
429 // TODO parse Lua only once for each model.
430 }
431
432 /**
433 * \brief Notifies Lua that a dialog starts.
434 * \param game The game.
435 * \param dialog The dialog that is becoming active.
436 * \param info_ref Lua ref to an optional info parameter to pass to
437 * Lua, or an empty ref.
438 * \return true if Lua handles the dialog, false otherwise.
439 */
notify_dialog_started(Game & game,const Dialog & dialog,const ScopedLuaRef & info_ref)440 bool LuaContext::notify_dialog_started(
441 Game& game,
442 const Dialog& dialog,
443 const ScopedLuaRef& info_ref
444 ) {
445 return game_on_dialog_started(game, dialog, info_ref);
446 }
447
448 /**
449 * \brief Notifies Lua that a dialog is finished.
450 * \param game The game.
451 * \param dialog The dialog that was active.
452 * \param callback_ref Lua ref of the function to call, or an empty ref.
453 * \param status_ref Lua ref to a status value to pass to the callback.
454 * "skipped" means that the dialog was canceled by the user.
455 */
notify_dialog_finished(Game & game,const Dialog & dialog,const ScopedLuaRef & callback_ref,const ScopedLuaRef & status_ref)456 void LuaContext::notify_dialog_finished(
457 Game& game,
458 const Dialog& dialog,
459 const ScopedLuaRef& callback_ref,
460 const ScopedLuaRef& status_ref) {
461
462 game_on_dialog_finished(game, dialog);
463
464 // Execute the callback after game:on_dialog_finished()
465 // because the callback may start another dialog.
466 if (!callback_ref.is_empty()) {
467 push_ref(current_l, callback_ref);
468 if (!status_ref.is_empty()) {
469 push_ref(current_l, status_ref);
470 }
471 else {
472 // No status.
473 lua_pushnil(current_l);
474 }
475 call_function(1, 0, "dialog callback");
476 }
477 }
478
479 /**
480 * \brief Shows a deprecation warning message if the quest format is recent enough.
481 *
482 * Does nothing if the quest format is older than the given version.
483 * Does nothing if the message for this function was already shown once.
484 *
485 * \param version Solarus version (major and minor numbers) where the function
486 * becomes deprecated.
487 * \param function_name A deprecated Lua function.
488 * \param message A warning message explaining how to replace the call.
489 */
warning_deprecated(const std::pair<int,int> & version_deprecating,const std::string & function_name,const std::string & message)490 void LuaContext::warning_deprecated(
491 const std::pair<int, int>& version_deprecating,
492 const std::string& function_name,
493 const std::string& message
494 ) {
495
496 if (warning_deprecated_functions.find(function_name) !=
497 warning_deprecated_functions.end()) {
498 return;
499 }
500
501 if (CurrentQuest::is_format_at_least(version_deprecating)) {
502 std::ostringstream oss;
503 oss << "The function "<< function_name <<
504 " is deprecated since Solarus " <<
505 version_deprecating.first << "." <<
506 version_deprecating.second << ". " <<
507 message;
508 Logger::warning(oss.str());
509 warning_deprecated_functions.insert(function_name);
510 }
511 }
512
513 /**
514 * \brief Creates a reference to the Lua value on top of the stack and pops
515 * this value.
516 * \return The reference created, wrapped in an object that manages its
517 * lifetime.
518 */
create_ref()519 ScopedLuaRef LuaContext::create_ref() {
520
521 return LuaTools::create_ref(current_l);
522 }
523
524 /**
525 * \brief Pushes onto the stack a Lua value from its reference.
526 *
527 * Pushes nil if the reference is empty.
528 *
529 * \param l A Lua state.
530 * \param ref Reference to a Lua value.
531 */
push_ref(lua_State * l,const ScopedLuaRef & ref)532 void LuaContext::push_ref(lua_State* l, const ScopedLuaRef& ref) {
533
534 if (ref.is_empty()) {
535 lua_pushnil(l);
536 return;
537 }
538
539 //This is not needed anymore since several state (threads) can be active
540 //Debug::check_assertion(ref.get_lua_state() == l, "Wrong Lua state");
541 ref.push(l);
542 }
543
544 /**
545 * \brief Returns whether a userdata has an entry with the specified key.
546 *
547 * Userdata can have entries like tables thanks to special __index and
548 * __newindex metamethods.
549 *
550 * Version with const char*, better for performance if you don't have an
551 * std::string representation of the key.
552 *
553 * \param userdata A userdata.
554 * \param key String key to test.
555 * \return \c true if this key exists on the userdata.
556 */
userdata_has_field(const ExportableToLua & userdata,const char * key) const557 bool LuaContext::userdata_has_field(
558 const ExportableToLua& userdata, const char* key) const {
559
560 // TODO since this function now also checks the metatable, check that
561 // doing the work below instead of just returning true is still useful
562 // for performance.
563 // If not, kill this function.
564
565 // First check the metatable of the type.
566 if (userdata_has_metafield(userdata, key)) {
567 return true;
568 }
569
570 // Check the userdata itself then.
571 if (!userdata.is_with_lua_table()) {
572 return false;
573 }
574
575 const auto& it = userdata_fields.find(&userdata);
576 if (it == userdata_fields.end()) {
577 return false;
578 }
579
580 return it->second.find(key) != it->second.end();
581 }
582
583 /**
584 * \brief Returns whether a userdata has an entry with the specified key.
585 *
586 * Userdata can have entries like tables thanks to special __index and
587 * __newindex metamethods.
588 *
589 * Version with std::string, better for performance if you already have an
590 * std::string representation of the key.
591 *
592 * \param userdata A userdata.
593 * \param key String key to test.
594 * \return \c true if this key exists on the userdata.
595 */
userdata_has_field(const ExportableToLua & userdata,const std::string & key) const596 bool LuaContext::userdata_has_field(
597 const ExportableToLua& userdata, const std::string& key) const {
598
599 // First check the metatable of the type.
600 if (userdata_has_metafield(userdata, key.c_str())) {
601 return true;
602 }
603
604 // Check the userdata itself then.
605 if (!userdata.is_with_lua_table()) {
606 return false;
607 }
608
609 const auto& it = userdata_fields.find(&userdata);
610 if (it == userdata_fields.end()) {
611 return false;
612 }
613
614 return it->second.find(key) != it->second.end();
615 }
616
617 /**
618 * \brief Returns whether the metatable of a userdata has the specified field.
619 * \param userdata A userdata.
620 * \param key String key to test.
621 * \return \c true if this key exists on the userdata's metatable.
622 */
userdata_has_metafield(const ExportableToLua & userdata,const char * key) const623 bool LuaContext::userdata_has_metafield(
624 const ExportableToLua& userdata, const char* key) const {
625
626 // We avoid to push the userdata for performance.
627 // Maybe the userdata does not even exist in the Lua side.
628 // ...
629 luaL_getmetatable(current_l, userdata.get_lua_type_name().c_str());
630 // ... meta
631 lua_pushstring(current_l, key);
632 // ... meta key
633 lua_rawget(current_l, -2);
634 // ... meta field/nil
635 const bool found = !lua_isnil(current_l, -1);
636 lua_pop(current_l, 2);
637 // ...
638 return found;
639 }
640
641 /**
642 * \brief Gets a method of the object on top of the stack.
643 *
644 * This is equivalent to find_method(-1, function_name).
645 *
646 * \param function_name Name of the function to find in the object.
647 * This is not an const std::string& but a const char* on purpose to avoid
648 * costly conversions as this function is called very often.
649 * \return true if the function was found.
650 */
find_method(const char * function_name)651 bool LuaContext::find_method(const char* function_name) {
652
653 return find_method(-1, function_name);
654 }
655
656 /**
657 * \brief Gets a method of an object.
658 *
659 * If the method exists, the method and the object are both pushed
660 * so that you can call the method immediately with the object as first parameter.
661 * If the method is not found, the stack is left unchanged.
662 *
663 * \param index Index of the object in the stack.
664 * \param function_name Name of the function to find in the object.
665 * This is not an const std::string& but a const char* on purpose to avoid
666 * costly conversions as this function is called very often.
667 *
668 * \return true if the function was found.
669 */
find_method(int index,const char * function_name)670 bool LuaContext::find_method(int index, const char* function_name) {
671
672 index = LuaTools::get_positive_index(current_l, index);
673 // ... object ...
674 lua_getfield(current_l, index, function_name);
675 // ... object ... method/?
676
677 bool exists = lua_isfunction(current_l, -1);
678 if (exists) {
679 // ... object ... method
680 lua_pushvalue(current_l, index);
681 // ... object ... method object
682 }
683 else {
684 // Restore the stack.
685 lua_pop(current_l, 1);
686 // ... object ...
687 }
688
689 return exists;
690 }
691
692 /**
693 * \brief Calls the Lua function with its arguments on top of the stack.
694 *
695 * This function is like lua_pcall, except that it additionally handles the
696 * error message if an error occurs in the Lua code (the error is printed).
697 * This function leaves the results on the stack if there is no error,
698 * and leaves nothing on the stack in case of error.
699 *
700 * \param nb_arguments number of arguments placed on the Lua stack above the
701 * function to call
702 * \param nb_results number of results expected (you get them on the stack if
703 * there is no error)
704 * \param function_name A name describing the Lua function (only used to print
705 * the error message if any).
706 * This is not a const std::string& but a const char* on purpose to avoid
707 * costly conversions as this function is called very often.
708 * \return true in case of success
709 */
call_function(int nb_arguments,int nb_results,const char * function_name)710 bool LuaContext::call_function(
711 int nb_arguments,
712 int nb_results,
713 const char* function_name
714 ) {
715 return LuaTools::call_function(current_l, nb_arguments, nb_results, function_name);
716 }
717
718 /**
719 * \brief Opens a script if it exists and lets it on top of the stack as a
720 * function.
721 *
722 * If the file does not exist or has a syntax error,
723 * the stack is left intact and false is returned.
724 *
725 * \param script_name File name of the script with or without extension,
726 * relative to the data directory.
727 * \return true if the file exists and was loaded.
728 */
load_file(const std::string & script_name)729 bool LuaContext::load_file(const std::string& script_name) {
730
731 // Determine the file name (possibly adding ".lua").
732 std::string file_name(script_name);
733
734 if (!QuestFiles::data_file_exists(file_name)) {
735 std::ostringstream oss;
736 oss << script_name << ".lua";
737 file_name = oss.str();
738 }
739
740 if (!QuestFiles::data_file_exists(file_name)) {
741 // No error message: this is not an error.
742 return false;
743 }
744
745 // Load the file.
746 // "@" tells Lua that the name is a file name, which is useful for better error messages.
747 const std::string& buffer = QuestFiles::data_file_read(file_name);
748 int result = luaL_loadbuffer(current_l, buffer.data(), buffer.size(), ("@" + file_name).c_str());
749
750 if (result != 0) {
751 Debug::error(std::string("Failed to load script '")
752 + script_name + "': " + lua_tostring(current_l, -1));
753 lua_pop(current_l, 1);
754 return false;
755 }
756 return true;
757 }
758
759 /**
760 * \brief Opens a Lua file and executes it.
761 *
762 * This function just calls load_file() and call_function().
763 * The file must exist.
764 *
765 * \param script_name File name of the script without extension,
766 * relative to the data directory.
767 */
do_file(const std::string & script_name)768 void LuaContext::do_file(const std::string& script_name) {
769
770 if (!load_file(script_name)) {
771 Debug::error("Failed to load script '" + script_name + "'");
772 }
773 else {
774 LuaTools::call_function(current_l, 0, 0, script_name.c_str());
775 }
776 }
777
778 /**
779 * \brief Opens a Lua file if it exists and executes it without arguments.
780 *
781 * This function just calls load_file_if_exists() and call_function().
782 * Nothing is done if the file does not exists.
783 *
784 * \param script_name File name of the script without extension,
785 * relative to the data directory.
786 * \return true if the file exists and was successfully executed.
787 */
do_file_if_exists(const std::string & script_name)788 bool LuaContext::do_file_if_exists(const std::string& script_name) {
789
790 if (load_file(script_name)) {
791 LuaTools::call_function(current_l, 0, 0, script_name.c_str());
792 return true;
793 }
794 return false;
795 }
796
797 /**
798 * \brief Loads and executes some Lua code.
799 * \param code The code to execute.
800 * \param chunk_name A name describing the Lua chunk
801 * (only used to print the error message if any).
802 * \return \c true in case of success.
803 */
do_string(const std::string & code,const std::string & chunk_name)804 bool LuaContext::do_string(const std::string& code, const std::string& chunk_name) {
805 int load_result = luaL_loadstring(current_l, code.c_str());
806
807 if (load_result != 0) {
808 Debug::error(std::string("In ") + chunk_name + ": "
809 + lua_tostring(current_l, -1));
810 lua_pop(current_l, 1);
811 return false;
812 }
813
814 return LuaTools::call_function(current_l, 0, 0, chunk_name.c_str());
815 }
816
817 /**
818 * \brief Executes Lua code in an environment with easy access to game objects.
819 *
820 * The environment provides:
821 * - game,
822 * - map,
823 * - entities from their name,
824 * - tp (teletransportation function).
825 *
826 * \param code The code to execute.
827 * \param chunk_name A name describing the Lua chunk
828 * (only used to print the error message if any).
829 * \return \c true in case of success.
830 */
do_string_with_easy_env(const std::string & code,const std::string & chunk_name)831 bool LuaContext::do_string_with_easy_env(const std::string& code, const std::string& chunk_name) {
832
833 int load_result = luaL_loadstring(current_l, code.c_str());
834
835 if (load_result != 0) {
836 Debug::error(std::string("In ") + chunk_name + ": "
837 + lua_tostring(current_l, -1));
838 lua_pop(current_l, 1);
839 return false;
840 }
841
842 // Set an environment that provides easy access to game objects.
843 // code
844 lua_newtable(current_l);
845 // code env
846 lua_newtable(current_l);
847 // code env env_mt
848 // Set our special __index function.
849 lua_pushcfunction(current_l, l_easy_index);
850 // code env env_mt __index
851 lua_setfield(current_l, -2, "__index");
852 // code env env_mt
853 // We are changing the environment, so we need to also define __newindex
854 // with its usual setting (the global table).
855 lua_pushvalue(current_l, LUA_GLOBALSINDEX);
856 // code env env_mt _G
857 lua_setfield(current_l, -2, "__newindex");
858 // code env env_mt
859 lua_setmetatable(current_l, -2);
860 // code env
861 lua_setfenv(current_l, -2);
862 // code
863
864 return LuaTools::call_function(current_l, 0, 0, chunk_name.c_str());
865 }
866
867 /**
868 * @brief sets the presumed currently running lua state
869 * @param l a lua state
870 */
set_current_state(lua_State * l)871 void LuaContext::set_current_state(lua_State* l) {
872 lua_context->current_l = l;
873 }
874
875 /**
876 * \brief Prints on a line the content of the Lua stack for debugging purposes.
877 * \param l A Lua state.
878 */
print_stack(lua_State * l)879 void LuaContext::print_stack(lua_State* l) {
880
881 int i;
882 int top = lua_gettop(l);
883
884 std::ostringstream oss;
885 for (i = 1; i <= top; i++) {
886
887 int type = lua_type(l, i);
888 switch (type) {
889
890 case LUA_TSTRING:
891 oss << "\"" << lua_tostring(l, i) << "\"";
892 break;
893
894 case LUA_TBOOLEAN:
895 oss << (lua_toboolean(l, i) ? "true" : "false");
896 break;
897
898 case LUA_TNUMBER:
899 oss << lua_tonumber(l, i);
900 break;
901
902 case LUA_TLIGHTUSERDATA:
903 oss << "lightuserdata:" << lua_touserdata(l, i);
904 break;
905
906 case LUA_TUSERDATA:
907 {
908 const ExportableToLuaPtr& userdata = *(static_cast<ExportableToLuaPtr*>(
909 lua_touserdata(l, i)));
910 const std::string& lua_type_name = userdata->get_lua_type_name();
911 oss << lua_type_name.substr(lua_type_name.find_last_of('.') + 1);
912 break;
913 }
914
915 default:
916 oss << lua_typename(l, type);
917 break;
918
919 }
920 oss << " ";
921 }
922 Logger::debug(oss.str());
923 }
924
925 /**
926 * \brief Prints the version of Lua.
927 *
928 * This detects if LuaJIT is being used.
929 */
print_lua_version()930 void LuaContext::print_lua_version() {
931
932 Debug::check_assertion(lua_gettop(current_l) == 0, "Non-empty Lua stack before print_lua_version()");
933
934 // _VERSION is the Lua language version, giving the same
935 // result for vanilla Lua and LuaJIT.
936 // But we want to tell the user if LuaJIT is being used.
937 // To detect this, we can check the presence of the jit table.
938 std::string version;
939 // -
940 lua_getglobal(current_l, "jit");
941 // jit/nil
942 if (lua_isnil(current_l, -1)) {
943 // Vanilla Lua.
944 // nil
945 lua_getglobal(current_l, "_VERSION");
946 // nil version
947 version = LuaTools::check_string(current_l, -1);
948 lua_pop(current_l, 2);
949 // -
950 Logger::info("LuaJIT: no (" + version + ")");
951 }
952 else {
953 // LuaJIT.
954 // jit
955 version = LuaTools::check_string_field(current_l, -1, "version");
956 lua_pop(current_l, 1);
957 // -
958 Logger::info("LuaJIT: yes (" + version + ")");
959 }
960
961 Debug::check_assertion(lua_gettop(current_l) == 0, "Non-empty Lua stack after print_lua_version()");
962 }
963
964 /**
965 * \brief Defines some C++ functions into a Lua table.
966 * \param module_name name of the table that will contain the functions
967 * (e.g. "sol.main").
968 * \param functions List of functions to define in the table.
969 */
register_functions(const std::string & module_name,std::vector<luaL_Reg> functions)970 void LuaContext::register_functions(
971 const std::string& module_name,
972 std::vector<luaL_Reg> functions
973 ) {
974
975 // Create a table and fill it with the functions.
976 functions.push_back({ nullptr, nullptr });
977 luaL_register(current_l, module_name.c_str(), functions.data());
978 lua_pop(current_l, 1);
979 }
980
981 /**
982 * \brief Defines some C++ functions into a new Lua userdata type.
983 * \param module_name name of the table that will contain the functions
984 * (e.g. "sol.game"). It may already exist or not.
985 * This string will also identify the type.
986 * \param functions List of functions to define in the module table.
987 * \param methods List of methods to define in the type.
988 * \param metamethods List of metamethods to define in the metatable of the
989 * type.
990 */
register_type(const std::string & module_name,std::vector<luaL_Reg> functions,std::vector<luaL_Reg> methods,std::vector<luaL_Reg> metamethods)991 void LuaContext::register_type(
992 const std::string& module_name,
993 std::vector<luaL_Reg> functions,
994 std::vector<luaL_Reg> methods,
995 std::vector<luaL_Reg> metamethods
996 ) {
997
998 // Check that this type does not already exist.
999 luaL_getmetatable(current_l, module_name.c_str());
1000 Debug::check_assertion(lua_isnil(current_l, -1),
1001 std::string("Type ") + module_name + " already exists");
1002 lua_pop(current_l, 1);
1003
1004 // Make sure we create the table.
1005 const luaL_Reg empty[] = {
1006 { nullptr, nullptr }
1007 };
1008 luaL_register(current_l, module_name.c_str(), empty);
1009 // module
1010
1011 // Add the functions to the module.
1012 if (!functions.empty()) {
1013 functions.push_back({ nullptr, nullptr});
1014 luaL_register(current_l, nullptr, functions.data());
1015 // module
1016 }
1017 lua_pop(current_l, 1);
1018 // --
1019
1020 // Create the metatable for the type, add it to the Lua registry.
1021 luaL_newmetatable(current_l, module_name.c_str());
1022 // meta
1023
1024 // Store a metafield __solarus_type with the module name.
1025 lua_pushstring(current_l, module_name.c_str());
1026 // meta type_name
1027 lua_setfield(current_l, -2, "__solarus_type");
1028 // meta
1029
1030 // Add the methods to the metatable.
1031 if (!methods.empty()) {
1032 methods.push_back({ nullptr, nullptr });
1033 luaL_register(current_l, nullptr, methods.data());
1034 }
1035 // meta
1036
1037 // Add the metamethods to the metatable.
1038 if (!metamethods.empty()) {
1039 metamethods.push_back({ nullptr, nullptr });
1040 luaL_register(current_l, nullptr, metamethods.data());
1041 // meta
1042 }
1043
1044 // make metatable.__index = metatable,
1045 // unless if __index is already defined
1046 lua_getfield(current_l, -1, "__index");
1047 // meta __index/nil
1048 lua_pushvalue(current_l, -2);
1049 // meta __index/nil meta
1050 if (lua_isnil(current_l, -2)) {
1051 // meta nil meta
1052 lua_setfield(current_l, -3, "__index");
1053 // meta nil
1054 }
1055 lua_settop(current_l, 0);
1056 // --
1057 }
1058
1059 /**
1060 * \brief Tells the Lua context what C++ functions it can call.
1061 */
register_modules()1062 void LuaContext::register_modules() {
1063
1064 Debug::check_assertion(lua_gettop(current_l) == 0,
1065 "Lua stack is not empty before modules initialization");
1066
1067 register_main_module();
1068 register_game_module();
1069 register_map_module();
1070 register_entity_module();
1071 register_audio_module();
1072 register_timer_module();
1073 register_surface_module();
1074 register_text_surface_module();
1075 register_sprite_module();
1076 register_movement_module();
1077 register_item_module();
1078 register_input_module();
1079 register_video_module();
1080 register_shader_module();
1081 register_file_module();
1082 register_menu_module();
1083 register_language_module();
1084 register_state_module();
1085
1086 Debug::check_assertion(lua_gettop(current_l) == 0,
1087 "Lua stack is not empty after modules initialization");
1088 }
1089
1090 /**
1091 * \brief Pushes a string.
1092 * \param l A Lua state.
1093 * \param text A string value.
1094 */
push_string(lua_State * l,const std::string & text)1095 void LuaContext::push_string(lua_State* l, const std::string& text) {
1096 lua_pushlstring(l, text.c_str(), text.size());
1097 }
1098
1099 /**
1100 * \brief Pushes a color onto the stack.
1101 * \param l A Lua context.
1102 * \param color A color.
1103 */
push_color(lua_State * l,const Color & color)1104 void LuaContext::push_color(lua_State* l, const Color& color) {
1105
1106 uint8_t r, g, b, a;
1107 color.get_components(r, g, b, a);
1108 lua_newtable(l);
1109 lua_pushinteger(l, r);
1110 lua_rawseti(l, -2, 1);
1111 lua_pushinteger(l, g);
1112 lua_rawseti(l, -2, 2);
1113 lua_pushinteger(l, b);
1114 lua_rawseti(l, -2, 3);
1115 lua_pushinteger(l, a);
1116 lua_rawseti(l, -2, 4);
1117 }
1118
1119 /**
1120 * \brief Pushes the Lua equivalent of a C++ object onto the stack.
1121 * \param l A Lua context.
1122 * \param userdata A userdata. It must live as a std::shared_ptr somewhere:
1123 * typically, it should have been stored in a std::shared_ptr at creation time.
1124 */
push_userdata(lua_State * l,ExportableToLua & userdata)1125 void LuaContext::push_userdata(lua_State* l, ExportableToLua& userdata) {
1126
1127 // See if this userdata already exists.
1128 //Look in main for the userdata table entry
1129 lua_State* main = lua_context->main_l;
1130 lua_getfield(main, LUA_REGISTRYINDEX, "sol.all_userdata");
1131 // ... all_udata
1132 lua_pushlightuserdata(main, &userdata);
1133 // ... all_udata lightudata
1134 lua_gettable(main, -2);
1135 // ... all_udata udata/nil
1136 if (!lua_isnil(main, -1)) {
1137 // ... all_udata udata
1138 // The userdata already exists in the Lua world.
1139 lua_remove(main, -2);
1140 // ... udata
1141 }
1142 else {
1143 // Create a new userdata.
1144
1145 if (!userdata.is_known_to_lua()) {
1146 // This is the first time we create a Lua userdata for this object.
1147 userdata.set_known_to_lua(true);
1148 userdata.set_lua_context(&get());
1149 }
1150
1151 // ... all_udata nil
1152 lua_pop(main, 1);
1153 // ... all_udata
1154 lua_pushlightuserdata(main, &userdata);
1155 // ... all_udata lightudata
1156
1157 // Find the existing shared_ptr from the raw pointer.
1158 ExportableToLuaPtr shared_userdata;
1159 try {
1160 shared_userdata = userdata.shared_from_this();
1161 }
1162 catch (const std::bad_weak_ptr& ex) {
1163 // No existing shared_ptr. This is probably because you forgot to
1164 // store your object in a shared_ptr at creation time.
1165 Debug::die(
1166 std::string("No living shared_ptr for ") + userdata.get_lua_type_name()
1167 );
1168 }
1169
1170 ExportableToLuaPtr* block_address = static_cast<ExportableToLuaPtr*>(
1171 lua_newuserdata(main, sizeof(ExportableToLuaPtr))
1172 );
1173 // Manually construct a shared_ptr in the block allocated by Lua.
1174 new (block_address) ExportableToLuaPtr(shared_userdata);
1175 // ... all_udata lightudata udata
1176 luaL_getmetatable(main, userdata.get_lua_type_name().c_str());
1177 // ... all_udata lightudata udata mt
1178
1179 Debug::execute_if_debug([&] {
1180 Debug::check_assertion(!lua_isnil(main, -1),
1181 std::string("Userdata of type '" + userdata.get_lua_type_name()
1182 + "' has no metatable, this is a memory leak"));
1183
1184 lua_getfield(main, -1, "__gc");
1185 // ... all_udata lightudata udata mt gc
1186 Debug::check_assertion(lua_isfunction(main, -1),
1187 std::string("Userdata of type '") + userdata.get_lua_type_name()
1188 + "' must have the __gc function LuaContext::userdata_meta_gc");
1189 // ... all_udata lightudata udata mt gc
1190 lua_pop(main, 1);
1191 // ... all_udata lightudata udata mt
1192 });
1193
1194 lua_setmetatable(main, -2);
1195 // ... all_udata lightudata udata
1196 // Keep track of our new userdata.
1197 lua_pushvalue(main, -1);
1198 // ... all_udata lightudata udata udata
1199 lua_insert(main, -4);
1200 // ... udata all_udata lightudata udata
1201 lua_settable(main, -3);
1202 // ... udata all_udata
1203 lua_pop(main, 1);
1204 // ... udata
1205 }
1206
1207 //Check if target stack is different from main...
1208 if(l != main) {
1209 //Move ref to target stack
1210 lua_xmove(main,l,1);
1211 }
1212 }
1213
1214 /**
1215 * \brief Get pointer to userdata if it is of the given type.
1216 *
1217 * This is luaL_testudata from the Lua auxiliary library.
1218 * It should be replaced when Lua 5.3/LuaJIT 2.1 or higher is required.
1219 *
1220 * \param l A Lua context.
1221 * \param index An index in the stack.
1222 * \param module_name Name of a userdata metatable in the registry.
1223 * \return Pointer to userdata if it is a userdata of the given type,
1224 * nullptr otherwise.
1225 */
test_userdata(lua_State * l,int index,const char * module_name)1226 void* LuaContext::test_userdata(
1227 lua_State* l, int index, const char* module_name) {
1228
1229 index = LuaTools::get_positive_index(l, index);
1230
1231 void* udata = lua_touserdata(l, index);
1232 if (udata == nullptr || !lua_getmetatable(l, index)) {
1233 return nullptr;
1234 }
1235 // ... udata ... meta(found)
1236 lua_getfield(l, LUA_REGISTRYINDEX, module_name);
1237 // ... udata ... meta(found) meta(expected)
1238 if (lua_rawequal(l, -1, -2) == 0) {
1239 udata = nullptr;
1240 }
1241 lua_pop(l, 2);
1242 // ... udata ...
1243 return udata;
1244 }
1245
1246 /**
1247 * \brief Returns whether a value is a userdata of a given type.
1248 * \param l a Lua context
1249 * \param index an index in the stack
1250 * \param module_name name of a userdata metatable in the registry
1251 * \return true if the value is a userdata with this metatable
1252 */
is_userdata(lua_State * l,int index,const std::string & module_name)1253 bool LuaContext::is_userdata(lua_State* l, int index,
1254 const std::string& module_name) {
1255
1256 void* udata = test_userdata(l, index, module_name.c_str());
1257 return (udata != nullptr);
1258 }
1259
1260 /**
1261 * \brief Checks that the value at the given index is userdata of the
1262 * specified type and returns it.
1263 * \param l A Lua state.
1264 * \param index An index in the Lua stack.
1265 * \param module_name Name identifying the userdata type.
1266 * \return The userdata at this index.
1267 */
check_userdata(lua_State * l,int index,const std::string & module_name)1268 const ExportableToLuaPtr& LuaContext::check_userdata(
1269 lua_State* l,
1270 int index,
1271 const std::string& module_name
1272 ) {
1273
1274 void* udata = test_userdata(l, index, module_name.c_str());
1275 if (udata == nullptr) {
1276 LuaTools::type_error(l, index, LuaTools::get_type_name(module_name));
1277 }
1278 return *static_cast<ExportableToLuaPtr*>(udata);
1279 }
1280
1281 /**
1282 * \brief Returns whether a value is a userdata from Solarus.
1283 * \param[in] l A Lua context.
1284 * \param[in] index An index in the stack.
1285 * \param[out] module_name Name of the userdata metatable in the registry,
1286 * if found.
1287 * \return \c true if the value is a userdata from Solarus.
1288 */
is_solarus_userdata(lua_State * l,int index,std::string & module_name)1289 bool LuaContext::is_solarus_userdata(
1290 lua_State* l,
1291 int index,
1292 std::string& module_name
1293 ) {
1294 void* udata = lua_touserdata(l, index);
1295 if (udata == nullptr) {
1296 // This is not a userdata.
1297 return false;
1298 }
1299
1300 if (!lua_getmetatable(l, index)) {
1301 // The userdata has no metatable.
1302 return false;
1303 }
1304
1305 // Get the name of the Solarus type from this userdata.
1306 lua_pushstring(l, "__solarus_type");
1307 lua_rawget(l, -2);
1308 if (!lua_isstring(l, -1)) {
1309 // This is probably a userdata from some library other than Solarus.
1310 lua_pop(l, 2);
1311 return false;
1312 }
1313
1314 // Check if the type name is one of the entity type names.
1315 module_name = lua_tostring(l, -1);
1316 if (module_name.substr(0, 4) != "sol.") {
1317 return false;
1318 }
1319
1320 return true;
1321 }
1322
1323 /**
1324 * \brief Finalizer of a userdata type.
1325 * \param l A Lua state.
1326 * \return Number of values to return to Lua.
1327 */
userdata_meta_gc(lua_State * l)1328 int LuaContext::userdata_meta_gc(lua_State* l) {
1329
1330 ExportableToLuaPtr* userdata =
1331 static_cast<ExportableToLuaPtr*>(lua_touserdata(l, 1));
1332
1333 // Note that the full userdata disappears from Lua but it may come back later!
1334 // So we need to keep its table if the refcount is not zero.
1335 // The full userdata is destroyed but the light userdata and its table persist.
1336 // Its table will be destroyed from ~ExportableToLua().
1337
1338 // We don't need to remove the entry from sol.all_userdata
1339 // because it is already done: that table is weak on its values and the
1340 // value was the full userdata.
1341
1342 // Manually destroy the shared_ptr allocated for Lua.
1343 userdata->~shared_ptr<ExportableToLua>();
1344
1345 return 0;
1346 }
1347
1348 /**
1349 * \brief Function called when a userdata is being destroyed from C++.
1350 *
1351 * It means that it is no longer used from Lua either
1352 * (__gc has been called before or is being called).
1353 *
1354 * \param userdata The userdata just destroyed.
1355 */
notify_userdata_destroyed(ExportableToLua & userdata)1356 void LuaContext::notify_userdata_destroyed(ExportableToLua& userdata) {
1357
1358 if (userdata.is_with_lua_table()) {
1359 // Remove the table associated to this userdata.
1360 // Otherwise, if the same pointer gets reallocated, a new userdata will get
1361 // its table from this deleted one!
1362
1363 // ...
1364 lua_getfield(current_l, LUA_REGISTRYINDEX, "sol.userdata_tables");
1365 // ... udata_tables/nil
1366 if (!lua_isnil(current_l, -1)) {
1367 // ... udata_tables
1368 lua_pushlightuserdata(current_l, &userdata);
1369 // ... udata_tables lightudata
1370 lua_pushnil(current_l);
1371 // ... udata_tables lightudata nil
1372 lua_settable(current_l, -3);
1373 // ... udata_tables
1374 }
1375 lua_pop(current_l, 1);
1376 // ...
1377 get().userdata_fields.erase(&userdata);
1378 }
1379 }
1380
1381 /**
1382 * \brief Tells all userdata that Lua is closing.
1383 *
1384 * This must be done when Lua is about to be closed,
1385 * so that they can continue to live normally in C++.
1386 */
userdata_close_lua()1387 void LuaContext::userdata_close_lua() {
1388
1389 // Tell userdata to forget about this Lua state.
1390 lua_getfield(current_l, LUA_REGISTRYINDEX, "sol.all_userdata");
1391 lua_pushnil(current_l);
1392 while (lua_next(current_l, -2) != 0) {
1393 ExportableToLua* userdata = static_cast<ExportableToLua*>(
1394 lua_touserdata(current_l, -2));
1395 userdata->set_lua_context(nullptr);
1396 lua_pop(current_l, 1);
1397 }
1398 lua_pop(current_l, 1);
1399 userdata_fields.clear();
1400
1401 // Clear userdata tables.
1402 lua_pushnil(current_l);
1403 lua_setfield(current_l, LUA_REGISTRYINDEX, "sol.userdata_tables");
1404 }
1405
1406 /**
1407 * \brief Implementation of __newindex that allows userdata to be like tables.
1408 *
1409 * Lua code can make "object[key] = value" if object is a userdata with this
1410 * __newindex metamethod.
1411 *
1412 * This metamethod must be used with its corresponding __index
1413 * metamethod (see userdata_meta_index_as_table).
1414 *
1415 * \param l The Lua context that is calling this function.
1416 * \return Number of values to return to Lua.
1417 */
userdata_meta_newindex_as_table(lua_State * l)1418 int LuaContext::userdata_meta_newindex_as_table(lua_State* l) {
1419
1420 LuaTools::check_type(l, 1, LUA_TUSERDATA);
1421 LuaTools::check_any(l, 2);
1422 LuaTools::check_any(l, 3);
1423
1424 const ExportableToLuaPtr& userdata =
1425 *(static_cast<ExportableToLuaPtr*>(lua_touserdata(l, 1)));
1426
1427 // The user wants to make udata[key] = value but udata is a userdata.
1428 // So what we make instead is udata_tables[udata][key] = value.
1429 // This redirection is totally transparent from the Lua side.
1430
1431 lua_getfield(l, LUA_REGISTRYINDEX, "sol.userdata_tables");
1432 // ... udata_tables
1433
1434 if (!userdata->is_with_lua_table()) {
1435 // Create the userdata table if it does not exist yet.
1436
1437 userdata->set_with_lua_table(true);
1438 // ... udata_tables
1439 lua_newtable(l);
1440 // ... udata_tables udata_table
1441 lua_pushlightuserdata(l, userdata.get());
1442 // ... udata_tables udata_table lightudata
1443 lua_pushvalue(l, -2);
1444 // ... udata_tables udata_table lightudata udata_table
1445 lua_settable(l, -4);
1446 // ... udata_tables udata_table
1447 }
1448 else {
1449 // The userdata table already exists.
1450 lua_pushlightuserdata(l, userdata.get());
1451 // ... udata_tables lightudata
1452 lua_gettable(l, -2);
1453 // ... udata_tables udata_table
1454 }
1455 Debug::check_assertion(!lua_isnil(l, -1), "Missing userdata table");
1456 lua_pushvalue(l, 2);
1457 // ... udata_tables udata_table key
1458 lua_pushvalue(l, 3);
1459 // ... udata_tables udata_table key value
1460 lua_settable(l, -3);
1461 // ... udata_tables udata_table
1462
1463 if (lua_isstring(l, 2)) {
1464 if (!lua_isnil(l, 3)) {
1465 // Add the key to the list of existing strings keys on this userdata.
1466 get().userdata_fields[userdata.get()].insert(lua_tostring(l, 2));
1467 }
1468 else {
1469 // Assigning nil: remove the key from the list.
1470 get().userdata_fields[userdata.get()].erase(lua_tostring(l, 2));
1471 }
1472 }
1473
1474 return 0;
1475 }
1476
1477 /**
1478 * \brief Implementation of __index that allows userdata to be like tables.
1479 *
1480 * Lua code can get "object[key]" for an arbitrary key previously set.
1481 *
1482 * This metamethod must be used with its corresponding __newindex
1483 * metamethod (see userdata_meta_newindex_as_table).
1484 *
1485 * \brief Implementation of __index for the type game.
1486 * \param l The Lua context that is calling this function.
1487 * \return Number of values to return to Lua.
1488 */
userdata_meta_index_as_table(lua_State * l)1489 int LuaContext::userdata_meta_index_as_table(lua_State* l) {
1490
1491 /* The user wants to make udata[key] but udata is a userdata.
1492 * So what we retrieve instead is udata_tables[udata][key].
1493 * This redirection is totally transparent from the Lua side.
1494 * If udata_tables[udata][key] does not exist, we fall back
1495 * to the userdata __index metamethod.
1496 */
1497
1498 LuaTools::check_type(l, 1, LUA_TUSERDATA);
1499 LuaTools::check_any(l, 2);
1500
1501 const ExportableToLuaPtr& userdata =
1502 *(static_cast<ExportableToLuaPtr*>(lua_touserdata(l, 1)));
1503 LuaContext& lua_context = get();
1504
1505 // If the userdata actually has a table, lookup this table, unless we already
1506 // know that we won't find it (because we know all the existing string keys).
1507 if (userdata->is_with_lua_table() &&
1508 (!lua_isstring(l, 2) || lua_context.userdata_has_field(*userdata, lua_tostring(l, 2)))) {
1509
1510 lua_getfield(l, LUA_REGISTRYINDEX, "sol.userdata_tables");
1511 // ... udata_tables
1512 lua_pushlightuserdata(l, userdata.get());
1513 // ... udata_tables lightudata
1514 // Lookup the key in the table, without metamethods.
1515 lua_rawget(l, -2);
1516 // ... udata_tables udata_table/nil
1517 if (!lua_isnil(l, -1)) {
1518 lua_pushvalue(l, 2);
1519 // ... udata_tables udata_table key
1520 lua_gettable(l, -2);
1521 // ... udata_tables udata_table value/nil
1522 if (!lua_isnil(l, -1)) {
1523 // Found it!
1524 return 1;
1525 }
1526 }
1527 }
1528
1529 // Not in the table. See in the metatable
1530 // (just like when metatable.__index = metatable).
1531
1532 lua_pushvalue(l, 1);
1533 // ... udata
1534 lua_getmetatable(l, -1);
1535 // ... udata meta
1536 Debug::check_assertion(!lua_isnil(l, -1), "Missing userdata metatable");
1537 lua_pushvalue(l, 2);
1538 // ... udata meta key
1539 lua_gettable(l, -2);
1540 // ... udata meta key value/nil
1541 return 1;
1542 }
1543
1544 /**
1545 * @brief checks if the LuaContext is in a event-friendly context
1546 */
check_callback_thread() const1547 void LuaContext::check_callback_thread() const {
1548 Debug::check_assertion(current_l == main_l, "Events should be called in the main Lua thread");
1549 }
1550
1551 /**
1552 * \brief Calls the on_started() method of the object on top of the stack.
1553 */
on_started()1554 void LuaContext::on_started() {
1555 check_callback_thread();
1556 if (find_method("on_started")) {
1557 call_function(1, 0, "on_started");
1558 }
1559 }
1560
1561 /**
1562 * \brief Calls the on_started() method of the object on top of the stack.
1563 * \param previous_state_name Name of the previous state.
1564 * \param previous_state The previous state object if it was a custom one.
1565 */
on_started(const std::string & previous_state_name,CustomState * previous_state)1566 void LuaContext::on_started(
1567 const std::string& previous_state_name,
1568 CustomState* previous_state) {
1569 check_callback_thread();
1570 if (find_method("on_started")) {
1571 push_string(current_l, previous_state_name);
1572 if (previous_state == nullptr) {
1573 lua_pushnil(current_l);
1574 }
1575 else {
1576 push_state(current_l, *previous_state);
1577 }
1578 call_function(3, 0, "on_started");
1579 }
1580 }
1581
1582 /**
1583 * \brief Calls the on_finished() method of the object on top of the stack.
1584 */
on_finished()1585 void LuaContext::on_finished() {
1586 check_callback_thread();
1587 if (find_method("on_finished")) {
1588 call_function(1, 0, "on_finished");
1589 }
1590 }
1591
1592 /**
1593 * \brief Calls the on_finished() method of the object on top of the stack.
1594 * \param next_state_name Name of the previous state.
1595 * \param next_state The previous state object if it was a custom one.
1596 */
on_finished(const std::string & next_state_name,CustomState * next_state)1597 void LuaContext::on_finished(
1598 const std::string& next_state_name,
1599 CustomState* next_state) {
1600 check_callback_thread();
1601 if (find_method("on_finished")) {
1602 push_string(current_l, next_state_name);
1603 if (next_state == nullptr) {
1604 lua_pushnil(current_l);
1605 }
1606 else {
1607 push_state(current_l, *next_state);
1608 }
1609 call_function(3, 0, "on_finished");
1610 }
1611 }
1612
1613 /**
1614 * \brief Calls the on_update() method of the object on top of the stack.
1615 */
on_update()1616 void LuaContext::on_update() {
1617 check_callback_thread();
1618 if (find_method("on_update")) {
1619 call_function(1, 0, "on_update");
1620 }
1621 }
1622
1623 /**
1624 * \brief Calls the on_draw() method of the object on top of the stack.
1625 * \param dst_surface The destination surface.
1626 */
on_draw(const SurfacePtr & dst_surface)1627 void LuaContext::on_draw(const SurfacePtr& dst_surface) {
1628 check_callback_thread();
1629 if (find_method("on_draw")) {
1630 push_surface(current_l, *dst_surface);
1631 call_function(2, 0, "on_draw");
1632 }
1633 }
1634
1635 /**
1636 * \brief Calls the on_suspended() method of the object on top of the stack.
1637 * \param suspended true to suspend the object, false to unsuspend it.
1638 */
on_suspended(bool suspended)1639 void LuaContext::on_suspended(bool suspended) {
1640 check_callback_thread();
1641 if (find_method("on_suspended")) {
1642 lua_pushboolean(current_l, suspended);
1643 call_function(2, 0, "on_suspended");
1644 }
1645 }
1646
1647 /**
1648 * \brief Calls the on_paused() method of the object on top of the stack.
1649 */
on_paused()1650 void LuaContext::on_paused() {
1651 check_callback_thread();
1652 if (find_method("on_paused")) {
1653 call_function(1, 0, "on_paused");
1654 }
1655 }
1656
1657 /**
1658 * \brief Calls the on_unpaused() method of the object on top of the stack.
1659 */
on_unpaused()1660 void LuaContext::on_unpaused() {
1661 check_callback_thread();
1662 if (find_method("on_unpaused")) {
1663 call_function(1, 0, "on_unpaused");
1664 }
1665 }
1666
1667 /**
1668 * \brief Calls the on_dialog_started() method of the object on top of the
1669 * stack.
1670 * \param dialog The dialog that just started.
1671 * \param info_ref Lua ref to the info parameter to pass to the method,
1672 * or an empty ref.
1673 * \return true if the on_dialog_started() method is defined.
1674 */
on_dialog_started(const Dialog & dialog,const ScopedLuaRef & info_ref)1675 bool LuaContext::on_dialog_started(
1676 const Dialog& dialog,
1677 const ScopedLuaRef& info_ref
1678 ) {
1679 check_callback_thread();
1680 if (find_method("on_dialog_started")) {
1681 push_dialog(current_l, dialog);
1682 push_ref(current_l, info_ref);
1683 call_function(3, 0, "on_dialog_started");
1684 return true;
1685 }
1686 return false;
1687 }
1688
1689 /**
1690 * \brief Calls the on_dialog_finished() method of the object on top of the stack.
1691 * \param dialog The dialog that has just finished.
1692 */
on_dialog_finished(const Dialog & dialog)1693 void LuaContext::on_dialog_finished(const Dialog& dialog) {
1694 check_callback_thread();
1695 if (find_method("on_dialog_finished")) {
1696 push_dialog(current_l, dialog);
1697 call_function(2, 0, "on_dialog_finished");
1698 }
1699 }
1700
1701 /**
1702 * \brief Calls the on_game_over_started() method of the object on top of the stack.
1703 */
on_game_over_started()1704 bool LuaContext::on_game_over_started() {
1705 check_callback_thread();
1706 if (find_method("on_game_over_started")) {
1707 call_function(1, 0, "on_game_over_started");
1708 return true;
1709 }
1710 return false;
1711 }
1712
1713 /**
1714 * \brief Calls the on_game_over_finished() method of the object on top of the stack.
1715 */
on_game_over_finished()1716 void LuaContext::on_game_over_finished() {
1717 check_callback_thread();
1718 if (find_method("on_game_over_finished")) {
1719 call_function(1, 0, "on_game_over_finished");
1720 }
1721 }
1722
1723 /**
1724 * \brief Calls an input callback method of the object on top of the stack.
1725 * \param event The input event to forward.
1726 * \return \c true if the event was handled and should stop being propagated.
1727 */
on_input(const InputEvent & event)1728 bool LuaContext::on_input(const InputEvent& event) {
1729 check_callback_thread();
1730 // Call the Lua function(s) corresponding to this input event.
1731 bool handled = false;
1732 if (event.is_keyboard_event()) {
1733 // Keyboard.
1734 if (event.is_keyboard_key_pressed()) {
1735 handled = on_key_pressed(event) || handled;
1736 }
1737 else if (event.is_keyboard_key_released()) {
1738 handled = on_key_released(event) || handled;
1739 }
1740 }
1741 else if (event.is_character_pressed()) {
1742 handled = on_character_pressed(event) || handled;
1743 }
1744 else if (event.is_joypad_event()) {
1745 // Joypad.
1746 if (event.is_joypad_button_pressed()) {
1747 handled = on_joypad_button_pressed(event) || handled;
1748 }
1749 else if (event.is_joypad_button_released()) {
1750 handled = on_joypad_button_released(event) || handled;
1751 }
1752 else if (event.is_joypad_axis_moved()) {
1753 handled = on_joypad_axis_moved(event) || handled;
1754 }
1755 else if (event.is_joypad_hat_moved()) {
1756 handled = on_joypad_hat_moved(event) || handled;
1757 }
1758 }
1759 else if (event.is_mouse_event()) {
1760 // Mouse.
1761 if (event.is_mouse_button_pressed()) {
1762 handled = on_mouse_button_pressed(event) || handled;
1763 }
1764 else if (event.is_mouse_button_released()) {
1765 handled = on_mouse_button_released(event) || handled;
1766 }
1767 }
1768 else if (event.is_finger_event() &&
1769 CurrentQuest::is_format_at_least({ 1, 6 })) {
1770 // Touch finger.
1771 if (event.is_finger_pressed()) {
1772 handled = on_finger_pressed(event) || handled;
1773 }
1774 else if (event.is_finger_released()) {
1775 handled = on_finger_released(event) || handled;
1776 }
1777 else if (event.is_finger_moved()) {
1778 handled = on_finger_moved(event) || handled;
1779 }
1780 }
1781
1782 return handled;
1783 }
1784
1785 /**
1786 * \brief Notifies the object on top of the stack
1787 * that a keyboard key was just pressed
1788 * (including if it is a directional key or a character).
1789 * \param event The corresponding input event.
1790 * \return \c true if the event was handled and should stop being propagated.
1791 */
on_key_pressed(const InputEvent & event)1792 bool LuaContext::on_key_pressed(const InputEvent& event) {
1793 check_callback_thread();
1794 bool handled = false;
1795 if (find_method("on_key_pressed")) {
1796
1797 const std::string& key_name = enum_to_name(event.get_keyboard_key());
1798 if (!key_name.empty()) { // This key exists in the Solarus API.
1799
1800 push_string(current_l, key_name);
1801 lua_newtable(current_l);
1802
1803 if (event.is_with_shift()) {
1804 lua_pushboolean(current_l, 1);
1805 lua_setfield(current_l, -2, "shift");
1806 }
1807
1808 if (event.is_with_control()) {
1809 lua_pushboolean(current_l, 1);
1810 lua_setfield(current_l, -2, "control");
1811 }
1812
1813 if (event.is_with_alt()) {
1814 lua_pushboolean(current_l, 1);
1815 lua_setfield(current_l, -2, "alt");
1816 }
1817 bool success = call_function(3, 1, "on_key_pressed");
1818 if (!success) {
1819 // Something was wrong in the script: don't propagate the input to other objects.
1820 handled = true;
1821 }
1822 else {
1823 handled = lua_toboolean(current_l, -1);
1824 lua_pop(current_l, 1);
1825 }
1826 }
1827 else {
1828 // The method exists but the key is unknown.
1829 lua_pop(current_l, 2); // Pop the object and the method.
1830 }
1831 }
1832 return handled;
1833 }
1834
1835 /**
1836 * \brief Notifies the object on top of the stack
1837 * that a character was just pressed with the keyboard.
1838 * \param event The corresponding input event.
1839 * \return \c true if the event was handled and should stop being propagated.
1840 */
on_character_pressed(const InputEvent & event)1841 bool LuaContext::on_character_pressed(const InputEvent& event) {
1842 check_callback_thread();
1843 bool handled = false;
1844 if (find_method("on_character_pressed")) {
1845
1846 const std::string& character = event.get_character();
1847 push_string(current_l, character);
1848 bool success = call_function(2, 1, "on_character_pressed");
1849 if (!success) {
1850 // Something was wrong in the script: don't propagate the input to other objects.
1851 handled = true;
1852 }
1853 else {
1854 handled = lua_toboolean(current_l, -1);
1855 lua_pop(current_l, 1);
1856 }
1857 }
1858 return handled;
1859 }
1860
1861 /**
1862 * \brief Notifies the object on top of the stack
1863 * that a keyboard key was just released
1864 * (including if it is a directional key).
1865 * \param event The corresponding input event.
1866 * \return \c true if the event was handled and should stop being propagated.
1867 */
on_key_released(const InputEvent & event)1868 bool LuaContext::on_key_released(const InputEvent& event) {
1869 check_callback_thread();
1870 bool handled = false;
1871 if (find_method("on_key_released")) {
1872
1873 const std::string& key_name = enum_to_name(event.get_keyboard_key());
1874 if (!key_name.empty()) { // This key exists in the Solarus API.
1875 push_string(current_l, key_name);
1876 bool success = call_function(2, 1, "on_key_released");
1877 if (!success) {
1878 // Something was wrong in the script: don't propagate the input to other objects.
1879 handled = true;
1880 }
1881 else {
1882 handled = lua_toboolean(current_l, -1);
1883 lua_pop(current_l, 1);
1884 }
1885 }
1886 else {
1887 // The method exists but the key is unknown.
1888 lua_pop(current_l, 2); // Pop the object and the method.
1889 }
1890 }
1891 return handled;
1892 }
1893
1894 /**
1895 * \brief Notifies the object on top of the stack
1896 * that a joypad button was just pressed.
1897 * \param event The corresponding input event.
1898 * \return \c true if the event was handled and should stop being propagated.
1899 */
on_joypad_button_pressed(const InputEvent & event)1900 bool LuaContext::on_joypad_button_pressed(const InputEvent& event) {
1901 check_callback_thread();
1902 bool handled = false;
1903 if (find_method("on_joypad_button_pressed")) {
1904 int button = event.get_joypad_button();
1905
1906 lua_pushinteger(current_l, button);
1907 bool success = call_function(2, 1, "on_joypad_button_pressed");
1908 if (!success) {
1909 // Something was wrong in the script: don't propagate the input to other objects.
1910 handled = true;
1911 }
1912 else {
1913 handled = lua_toboolean(current_l, -1);
1914 lua_pop(current_l, 1);
1915 }
1916 }
1917 return handled;
1918 }
1919
1920 /**
1921 * \brief Notifies the object on top of the stack
1922 * that a joypad button was just released.
1923 * \param event The corresponding input event.
1924 * \return \c true if the event was handled and should stop being propagated.
1925 */
on_joypad_button_released(const InputEvent & event)1926 bool LuaContext::on_joypad_button_released(const InputEvent& event) {
1927 check_callback_thread();
1928 bool handled = false;
1929 if (find_method("on_joypad_button_released")) {
1930 int button = event.get_joypad_button();
1931
1932 lua_pushinteger(current_l, button);
1933 bool success = call_function(2, 1, "on_joypad_button_released");
1934 if (!success) {
1935 // Something was wrong in the script: don't propagate the input to other objects.
1936 handled = true;
1937 }
1938 else {
1939 handled = lua_toboolean(current_l, -1);
1940 lua_pop(current_l, 1);
1941 }
1942 }
1943 return handled;
1944 }
1945
1946 /**
1947 * \brief Notifies the object on top of the stack
1948 * that a joypad axis was just moved.
1949 * \param event The corresponding input event.
1950 * \return \c true if the event was handled and should stop being propagated.
1951 */
on_joypad_axis_moved(const InputEvent & event)1952 bool LuaContext::on_joypad_axis_moved(const InputEvent& event) {
1953 check_callback_thread();
1954 bool handled = false;
1955 if (find_method("on_joypad_axis_moved")) {
1956 int axis = event.get_joypad_axis();
1957 int state = event.get_joypad_axis_state();
1958
1959 lua_pushinteger(current_l, axis);
1960 lua_pushinteger(current_l, state);
1961 bool success = call_function(3, 1, "on_joypad_axis_moved");
1962 if (!success) {
1963 // Something was wrong in the script: don't propagate the input to other objects.
1964 handled = true;
1965 }
1966 else {
1967 handled = lua_toboolean(current_l, -1);
1968 lua_pop(current_l, 1);
1969 }
1970 }
1971 return handled;
1972 }
1973
1974 /**
1975 * \brief Notifies the object on top of the stack
1976 * that a joypad hat was just moved.
1977 * \param event The corresponding input event.
1978 * \return \c true if the event was handled and should stop being propagated.
1979 */
on_joypad_hat_moved(const InputEvent & event)1980 bool LuaContext::on_joypad_hat_moved(const InputEvent& event) {
1981 check_callback_thread();
1982 bool handled = false;
1983 if (find_method("on_joypad_hat_moved")) {
1984 int hat = event.get_joypad_hat();
1985 int direction8 = event.get_joypad_hat_direction();
1986
1987 lua_pushinteger(current_l, hat);
1988 lua_pushinteger(current_l, direction8);
1989 bool success = call_function(3, 1, "on_joypad_hat_moved");
1990 if (!success) {
1991 // Something was wrong in the script: don't propagate the input to other objects.
1992 handled = true;
1993 }
1994 else {
1995 handled = lua_toboolean(current_l, -1);
1996 lua_pop(current_l, 1);
1997 }
1998 }
1999 return handled;
2000 }
2001
2002 /**
2003 * \brief Notifies the object on top of the stack
2004 * that a mouse button was just pressed.
2005 * \param event The corresponding input event.
2006 * \return \c true if the event was handled and should stop being propagated.
2007 */
on_mouse_button_pressed(const InputEvent & event)2008 bool LuaContext::on_mouse_button_pressed(const InputEvent& event) {
2009 check_callback_thread();
2010 bool handled = false;
2011 if (find_method("on_mouse_pressed")) {
2012
2013 const std::string& button_name = enum_to_name(event.get_mouse_button());
2014 const Point mouse_xy = event.get_mouse_position();
2015
2016 // Don't call the Lua event if this button doesn't exist in the Solarus API.
2017 if (button_name.empty()) {
2018 lua_pop(current_l, 2); // Pop the object and the method.
2019 return handled;
2020 }
2021
2022 push_string(current_l, button_name);
2023 lua_pushinteger(current_l, mouse_xy.x);
2024 lua_pushinteger(current_l, mouse_xy.y);
2025
2026 bool success = call_function(4, 1, "on_mouse_pressed");
2027 if (!success) {
2028 // Something was wrong in the script: don't propagate the input to other objects.
2029 handled = true;
2030 }
2031 else {
2032 handled = lua_toboolean(current_l, -1);
2033 lua_pop(current_l, 1);
2034 }
2035 }
2036 return handled;
2037 }
2038
2039 /**
2040 * \brief Notifies the object on top of the stack
2041 * that a mouse button was just released.
2042 * \param event The corresponding input event.
2043 * \return \c true if the event was handled and should stop being propagated.
2044 */
on_mouse_button_released(const InputEvent & event)2045 bool LuaContext::on_mouse_button_released(const InputEvent& event) {
2046 check_callback_thread();
2047 bool handled = false;
2048 if (find_method("on_mouse_released")) {
2049
2050 const std::string& button_name = enum_to_name(event.get_mouse_button());
2051 Point mouse_xy = event.get_mouse_position();
2052
2053 // Don't call the Lua event if this button doesn't exist in the Solarus API.
2054 if (button_name.empty()) {
2055 lua_pop(current_l, 2); // Pop the object and the method.
2056 return handled;
2057 }
2058
2059 push_string(current_l, button_name);
2060 lua_pushinteger(current_l, mouse_xy.x);
2061 lua_pushinteger(current_l, mouse_xy.y);
2062
2063 bool success = call_function(4, 1, "on_mouse_released");
2064 if (!success) {
2065 // Something was wrong in the script: don't propagate the input to other objects.
2066 handled = true;
2067 }
2068 else {
2069 handled = lua_toboolean(current_l, -1);
2070 lua_pop(current_l, 1);
2071 }
2072 }
2073 return handled;
2074 }
2075
2076 /**
2077 * \brief Notifies the object on top of the stack
2078 * that a finger was just pressed.
2079 * \param event The corresponding input event.
2080 * \return \c true if the event was handled and should stop being propagated.
2081 */
on_finger_pressed(const InputEvent & event)2082 bool LuaContext::on_finger_pressed(const InputEvent& event) {
2083 check_callback_thread();
2084 bool handled = false;
2085 if (find_method("on_finger_pressed")) {
2086
2087 const int finger_id = event.get_finger();
2088 const Point& finger_xy = event.get_finger_position();
2089 const float finger_pressure = event.get_finger_pressure();
2090
2091 lua_pushinteger(current_l, finger_id);
2092 lua_pushinteger(current_l, finger_xy.x);
2093 lua_pushinteger(current_l, finger_xy.y);
2094 lua_pushnumber(current_l, finger_pressure);
2095
2096 bool success = call_function(5, 1, "on_finger_pressed");
2097 if (!success) {
2098 // Something was wrong in the script: don't propagate the input to other objects.
2099 handled = true;
2100 }
2101 else {
2102 handled = lua_toboolean(current_l, -1);
2103 lua_pop(current_l, 1);
2104 }
2105 }
2106 return handled;
2107 }
2108
2109 /**
2110 * \brief Notifies the object on top of the stack
2111 * that a finger was just released.
2112 * \param event The corresponding input event.
2113 * \return \c true if the event was handled and should stop being propagated.
2114 */
on_finger_released(const InputEvent & event)2115 bool LuaContext::on_finger_released(const InputEvent& event) {
2116 check_callback_thread();
2117 bool handled = false;
2118 if (find_method("on_finger_released")) {
2119
2120 const int finger_id = event.get_finger();
2121 const Point& finger_xy = event.get_finger_position();
2122 const float finger_pressure = event.get_finger_pressure();
2123
2124 lua_pushinteger(current_l, finger_id);
2125 lua_pushinteger(current_l, finger_xy.x);
2126 lua_pushinteger(current_l, finger_xy.y);
2127 lua_pushnumber(current_l, finger_pressure);
2128
2129 bool success = call_function(5, 1, "on_finger_released");
2130 if (!success) {
2131 // Something was wrong in the script: don't propagate the input to other objects.
2132 handled = true;
2133 }
2134 else {
2135 handled = lua_toboolean(current_l, -1);
2136 lua_pop(current_l, 1);
2137 }
2138 }
2139 return handled;
2140 }
2141
2142 /**
2143 * \brief Notifies the object on top of the stack
2144 * that a finger was just moved.
2145 * \param event The corresponding input event.
2146 * \return \c true if the event was handled and should stop being propagated.
2147 */
on_finger_moved(const InputEvent & event)2148 bool LuaContext::on_finger_moved(const InputEvent& event) {
2149 check_callback_thread();
2150 bool handled = false;
2151 if (find_method("on_finger_moved")) {
2152
2153 const int finger_id = event.get_finger();
2154 const Point& finger_xy = event.get_finger_position();
2155 const Point& finger_distance = event.get_finger_distance();
2156 const float finger_pressure = event.get_finger_pressure();
2157
2158 lua_pushinteger(current_l, finger_id);
2159 lua_pushinteger(current_l, finger_xy.x);
2160 lua_pushinteger(current_l, finger_xy.y);
2161 lua_pushinteger(current_l, finger_distance.x);
2162 lua_pushinteger(current_l, finger_distance.y);
2163 lua_pushnumber(current_l, finger_pressure);
2164
2165 bool success = call_function(7, 1, "on_finger_moved");
2166 if (!success) {
2167 // Something was wrong in the script: don't propagate the input to other objects.
2168 handled = true;
2169 }
2170 else {
2171 handled = lua_toboolean(current_l, -1);
2172 lua_pop(current_l, 1);
2173 }
2174 }
2175 return handled;
2176 }
2177
2178 /**
2179 * \brief Calls the on_command_pressed() method of the object on top of the stack.
2180 * \param command The game command just pressed.
2181 */
on_command_pressed(GameCommand command)2182 bool LuaContext::on_command_pressed(GameCommand command) {
2183 check_callback_thread();
2184 bool handled = false;
2185 if (find_method("on_command_pressed")) {
2186 push_string(current_l, GameCommands::get_command_name(command));
2187 bool success = call_function(2, 1, "on_command_pressed");
2188 if (!success) {
2189 // Something was wrong in the script: don't propagate the command to other objects.
2190 handled = true;
2191 }
2192 else {
2193 handled = lua_toboolean(current_l, -1);
2194 lua_pop(current_l, 1);
2195 }
2196 }
2197 return handled;
2198 }
2199
2200 /**
2201 * \brief Calls the on_command_released() method of the object on top of the stack.
2202 * \param command The game command just pressed.
2203 */
on_command_released(GameCommand command)2204 bool LuaContext::on_command_released(GameCommand command) {
2205 check_callback_thread();
2206 bool handled = false;
2207 if (find_method("on_command_released")) {
2208 push_string(current_l, GameCommands::get_command_name(command));
2209 bool success = call_function(2, 1, "on_command_released");
2210 if (!success) {
2211 // Something was wrong in the script: don't propagate the command to other objects.
2212 handled = true;
2213 }
2214 else {
2215 handled = lua_toboolean(current_l, -1);
2216 lua_pop(current_l, 1);
2217 }
2218 }
2219 return handled;
2220 }
2221
2222 /**
2223 * \brief Calls the on_animation_finished() method of the object on top of the stack.
2224 * \param animation Name of the animation finished.
2225 */
on_animation_finished(const std::string & animation)2226 void LuaContext::on_animation_finished(const std::string& animation) {
2227 check_callback_thread();
2228 if (find_method("on_animation_finished")) {
2229 push_string(current_l, animation);
2230 call_function(2, 0, "on_animation_finished");
2231 }
2232 }
2233
2234 /**
2235 * \brief Calls the on_animation_changed() method of the object on top of the stack.
2236 * \param animation Name of the new animation.
2237 */
on_animation_changed(const std::string & animation)2238 void LuaContext::on_animation_changed(const std::string& animation) {
2239 check_callback_thread();
2240 if (find_method("on_animation_changed")) {
2241 push_string(current_l, animation);
2242 call_function(2, 0, "on_animation_changed");
2243 }
2244 }
2245
2246 /**
2247 * \brief Calls the on_direction_changed() method of the object on top of the stack.
2248 * \param animation Name of the sprite animation.
2249 * \param frame The new frame.
2250 */
on_direction_changed(const std::string & animation,int direction)2251 void LuaContext::on_direction_changed(
2252 const std::string& animation, int direction) {
2253 check_callback_thread();
2254 if (find_method("on_direction_changed")) {
2255 push_string(current_l, animation);
2256 lua_pushinteger(current_l, direction);
2257 call_function(3, 0, "on_direction_changed");
2258 }
2259 }
2260
2261 /**
2262 * \brief Calls the on_frame_changed() method of the object on top of the stack.
2263 * \param animation Name of the sprite animation.
2264 * \param frame The new frame.
2265 */
on_frame_changed(const std::string & animation,int frame)2266 void LuaContext::on_frame_changed(const std::string& animation, int frame) {
2267 check_callback_thread();
2268 if (find_method("on_frame_changed")) {
2269 push_string(current_l, animation);
2270 lua_pushinteger(current_l, frame);
2271 call_function(3, 0, "on_frame_changed");
2272 }
2273 }
2274
2275 /**
2276 * \brief Calls the on_position_changed() method of the object on top of the stack.
2277 * \param xy The new coordinates.
2278 */
on_position_changed(const Point & xy)2279 void LuaContext::on_position_changed(const Point& xy) {
2280 check_callback_thread();
2281 if (find_method("on_position_changed")) {
2282 lua_pushinteger(current_l, xy.x);
2283 lua_pushinteger(current_l, xy.y);
2284 call_function(3, 0, "on_position_changed");
2285 }
2286 }
2287
2288 /**
2289 * \brief Calls the on_obstacle_reached() method of the object on top of the stack.
2290 */
on_obstacle_reached()2291 void LuaContext::on_obstacle_reached() {
2292 check_callback_thread();
2293 if (find_method("on_obstacle_reached")) {
2294 call_function(1, 0, "on_obstacle_reached");
2295 }
2296 }
2297
2298 /**
2299 * \brief Calls the on_changed() method of the object on top of the stack.
2300 */
on_changed()2301 void LuaContext::on_changed() {
2302 check_callback_thread();
2303 if (find_method("on_changed")) {
2304 call_function(1, 0, "on_changed");
2305 }
2306 }
2307
2308 /**
2309 * \brief Calls the on_started() method of the object on top of the stack.
2310 * \param destination The destination point used (nullptr if it is a special one).
2311 */
on_started(const std::shared_ptr<Destination> & destination)2312 void LuaContext::on_started(const std::shared_ptr<Destination>& destination) {
2313 check_callback_thread();
2314 if (find_method("on_started")) {
2315 if (destination == nullptr) {
2316 lua_pushnil(current_l);
2317 }
2318 else {
2319 push_entity(current_l, *destination);
2320 }
2321 call_function(2, 0, "on_started");
2322 }
2323 }
2324
2325 /**
2326 * \brief Calls the on_opening_transition_finished() method of the object on top of the stack.
2327 * \param destination The destination point used (nullptr if it is a special one).
2328 */
on_opening_transition_finished(const std::shared_ptr<Destination> & destination)2329 void LuaContext::on_opening_transition_finished(const std::shared_ptr<Destination>& destination) {
2330 check_callback_thread();
2331 if (find_method("on_opening_transition_finished")) {
2332 if (destination == nullptr) {
2333 lua_pushnil(current_l);
2334 }
2335 else {
2336 push_entity(current_l, *destination);
2337 }
2338 call_function(2, 0, "on_opening_transition_finished");
2339 }
2340 }
2341
2342 /**
2343 * \brief Calls the on_obtaining_treasure() method of the object on top of the stack.
2344 * \param treasure The treasure being obtained.
2345 */
on_obtaining_treasure(const Treasure & treasure)2346 void LuaContext::on_obtaining_treasure(const Treasure& treasure) {
2347 check_callback_thread();
2348 if (find_method("on_obtaining_treasure")) {
2349 push_item(current_l, treasure.get_item());
2350 lua_pushinteger(current_l, treasure.get_variant());
2351 if (!treasure.is_saved()) {
2352 lua_pushnil(current_l);
2353 }
2354 else {
2355 lua_pushstring(current_l, treasure.get_savegame_variable().c_str());
2356 }
2357 call_function(4, 0, "on_obtaining_treasure");
2358 }
2359 }
2360
2361 /**
2362 * \brief Calls the on_obtained_treasure() method of the object on top of the stack.
2363 * \param treasure The treasure just obtained.
2364 */
on_obtained_treasure(const Treasure & treasure)2365 void LuaContext::on_obtained_treasure(const Treasure& treasure) {
2366 check_callback_thread();
2367 if (find_method("on_obtained_treasure")) {
2368 push_item(current_l, treasure.get_item());
2369 lua_pushinteger(current_l, treasure.get_variant());
2370 if (!treasure.is_saved()) {
2371 lua_pushnil(current_l);
2372 }
2373 else {
2374 lua_pushstring(current_l, treasure.get_savegame_variable().c_str());
2375 }
2376 call_function(4, 0, "on_obtained_treasure");
2377 }
2378 }
2379
2380 /**
2381 * \brief Calls the on_state_changing() method of the object on top of the stack.
2382 * \param state_name Name of the current state.
2383 * \param next_state_name Name of the state about to start.
2384 */
on_state_changing(const std::string & state_name,const std::string & next_state_name)2385 void LuaContext::on_state_changing(const std::string& state_name, const std::string& next_state_name) {
2386 check_callback_thread();
2387 if (find_method("on_state_changing")) {
2388 push_string(current_l, state_name);
2389 push_string(current_l, next_state_name);
2390 call_function(3, 0, "on_state_changing");
2391 }
2392 }
2393
2394 /**
2395 * \brief Calls the on_state_changed() method of the object on top of the stack.
2396 * \param new_state_name Name of the new state.
2397 */
on_state_changed(const std::string & new_state_name)2398 void LuaContext::on_state_changed(const std::string& new_state_name) {
2399 check_callback_thread();
2400 if (find_method("on_state_changed")) {
2401 push_string(current_l, new_state_name);
2402 call_function(2, 0, "on_state_changed");
2403 }
2404 }
2405
2406 /**
2407 * \brief Calls the on_taking_damage() method of the object on top of the stack.
2408 * \param damage The damage to take.
2409 */
on_taking_damage(int damage)2410 bool LuaContext::on_taking_damage(int damage) {
2411 check_callback_thread();
2412 if (find_method("on_taking_damage")) {
2413 lua_pushinteger(current_l, damage);
2414 call_function(2, 0, "on_taking_damage");
2415 return true;
2416 }
2417 return false;
2418 }
2419
2420 /**
2421 * \brief Calls the on_activating() method of the object on top of the stack.
2422 */
on_activating()2423 void LuaContext::on_activating() {
2424 check_callback_thread();
2425 if (find_method("on_activating")) {
2426 call_function(1, 0, "on_activating");
2427 }
2428 }
2429
2430 /**
2431 * \brief Calls the on_activating() method of the object on top of the stack.
2432 * \param direction Direction to pass as parameter.
2433 */
on_activating(int direction)2434 void LuaContext::on_activating(int direction) {
2435 check_callback_thread();
2436 if (find_method("on_activating")) {
2437 lua_pushinteger(current_l, direction);
2438 call_function(2, 0, "on_activating");
2439 }
2440 }
2441
2442 /**
2443 * \brief Calls the on_activated() method of the object on top of the stack.
2444 */
on_activated()2445 void LuaContext::on_activated() {
2446 check_callback_thread();
2447 if (find_method("on_activated")) {
2448 call_function(1, 0, "on_activated");
2449 }
2450 }
2451
2452 /**
2453 * \brief Calls the on_activated() method of the object on top of the stack.
2454 * \param direction Direction to pass as parameter.
2455 */
on_activated(int direction)2456 void LuaContext::on_activated(int direction) {
2457 check_callback_thread();
2458 if (find_method("on_activated")) {
2459 lua_pushinteger(current_l, direction);
2460 call_function(2, 0, "on_activated");
2461 }
2462 }
2463
2464 /**
2465 * \brief Calls the on_inactivated_repeat() method of the object on top of the stack.
2466 */
on_activated_repeat()2467 void LuaContext::on_activated_repeat() {
2468 check_callback_thread();
2469 if (find_method("on_activated_repeat")) {
2470 call_function(1, 0, "on_activated_repeat");
2471 }
2472 }
2473
2474 /**
2475 * \brief Calls the on_inactivated() method of the object on top of the stack.
2476 */
on_inactivated()2477 void LuaContext::on_inactivated() {
2478 check_callback_thread();
2479 if (find_method("on_inactivated")) {
2480 call_function(1, 0, "on_inactivated");
2481 }
2482 }
2483
2484 /**
2485 * \brief Calls the on_left() method of the object on top of the stack.
2486 */
on_left()2487 void LuaContext::on_left() {
2488 check_callback_thread();
2489 if (find_method("on_left")) {
2490 call_function(1, 0, "on_left");
2491 }
2492 }
2493
2494 /**
2495 * \brief Calls the on_npc_interaction() method of the object on top of the stack.
2496 * \param npc An NPC.
2497 */
on_npc_interaction(Npc & npc)2498 void LuaContext::on_npc_interaction(Npc& npc) {
2499 check_callback_thread();
2500 if (find_method("on_npc_interaction")) {
2501 push_npc(current_l, npc);
2502 call_function(2, 0, "on_npc_interaction");
2503 }
2504 }
2505
2506 /**
2507 * \brief Calls the on_npc_interaction_item() method of the object on top of the stack.
2508 * \param npc An NPC.
2509 * \param item_used The equipment item used.
2510 * \return true if an interaction occurred.
2511 */
on_npc_interaction_item(Npc & npc,EquipmentItem & item_used)2512 bool LuaContext::on_npc_interaction_item(Npc& npc, EquipmentItem& item_used) {
2513 check_callback_thread();
2514 bool interacted = false;
2515 if (find_method("on_npc_interaction_item")) {
2516 push_npc(current_l, npc);
2517 push_item(current_l, item_used);
2518 bool success = call_function(3, 1, "on_npc_interaction_item");
2519 if (!success) {
2520 // Something was wrong in the script: don't propagate the event to other objects.
2521 interacted = true;
2522 }
2523 else {
2524 interacted = lua_toboolean(current_l, -1);
2525 lua_pop(current_l, 1);
2526 }
2527 }
2528 return interacted;
2529 }
2530
2531 /**
2532 * \brief Calls the on_interaction() method of the object on top of the stack.
2533 * \return true if an interaction occurred.
2534 */
on_interaction()2535 bool LuaContext::on_interaction() {
2536 check_callback_thread();
2537 if (find_method("on_interaction")) {
2538 call_function(1, 0, "on_interaction");
2539 return true;
2540 }
2541
2542 return false;
2543 }
2544
2545 /**
2546 * \brief Calls the on_interaction_item() method of the object on top of the stack.
2547 * \param item_used The equipment item used.
2548 * \return true if an interaction occurred.
2549 */
on_interaction_item(EquipmentItem & item)2550 bool LuaContext::on_interaction_item(EquipmentItem& item) {
2551 check_callback_thread();
2552 bool interacted = false;
2553 if (find_method("on_interaction_item")) {
2554 push_item(current_l, item);
2555 bool success = call_function(2, 1, "on_interaction_item");
2556 if (!success) {
2557 // Something was wrong in the script: don't propagate the event to other objects.
2558 interacted = true;
2559 }
2560 else {
2561 interacted = lua_toboolean(current_l, -1);
2562 lua_pop(current_l, 1);
2563 }
2564 }
2565 return interacted;
2566 }
2567
2568 /**
2569 * \brief Calls the on_npc_collision_fire() method of the object on top of the stack.
2570 * \param npc An NPC.
2571 */
on_npc_collision_fire(Npc & npc)2572 void LuaContext::on_npc_collision_fire(Npc& npc) {
2573 check_callback_thread();
2574 if (find_method("on_npc_collision_fire")) {
2575 push_npc(current_l, npc);
2576 call_function(2, 0, "on_npc_collision_fire");
2577 }
2578 }
2579
2580 /**
2581 * \brief Calls the on_collision_fire() method of the object on top of the stack.
2582 */
on_collision_fire()2583 void LuaContext::on_collision_fire() {
2584 check_callback_thread();
2585 if (find_method("on_collision_fire")) {
2586 call_function(1, 0, "on_collision_fire");
2587 }
2588 }
2589
2590 /**
2591 * \brief Calls the on_collision_explosion() method of the object on top of the stack.
2592 */
on_collision_explosion()2593 void LuaContext::on_collision_explosion() {
2594 check_callback_thread();
2595 if (find_method("on_collision_explosion")) {
2596 call_function(1, 0, "on_collision_explosion");
2597 }
2598 }
2599
2600 /**
2601 * \brief Calls the on_buying() method of the object on top of the stack.
2602 * \return true if the player is allowed to buy the item.
2603 */
on_buying()2604 bool LuaContext::on_buying() {
2605 check_callback_thread();
2606 bool can_buy = true;
2607 if (find_method("on_buying")) {
2608 bool success = call_function(1, 1, "on_buying");
2609 if (!success) {
2610 // Something was wrong in the script: don't let the player buy the item.
2611 can_buy = false;
2612 }
2613 else {
2614 can_buy = lua_toboolean(current_l, -1);
2615 lua_pop(current_l, 1);
2616 }
2617 }
2618 return can_buy;
2619 }
2620
2621 /**
2622 * \brief Calls the on_bought() method of the object on top of the stack.
2623 */
on_bought()2624 void LuaContext::on_bought() {
2625 check_callback_thread();
2626 if (find_method("on_bought")) {
2627 call_function(1, 0, "on_bought");
2628 }
2629 }
2630
2631 /**
2632 * \brief Calls the on_opened() method of the object on top of the stack.
2633 */
on_opened()2634 void LuaContext::on_opened() {
2635 check_callback_thread();
2636 if (find_method("on_opened")) {
2637 call_function(1, 0, "on_opened");
2638 }
2639 }
2640
2641 /**
2642 * \brief Calls the on_opened() method of the object on top of the stack.
2643 * \param treasure A treasure being obtained when opening.
2644 * \return \c true if the method is defined.
2645 */
on_opened(const Treasure & treasure)2646 bool LuaContext::on_opened(const Treasure& treasure) {
2647 check_callback_thread();
2648 if (find_method("on_opened")) {
2649
2650 if (treasure.is_empty()) {
2651 lua_pushnil(current_l);
2652 lua_pushnil(current_l);
2653 }
2654 else {
2655 push_item(current_l, treasure.get_item());
2656 lua_pushinteger(current_l, treasure.get_variant());
2657 }
2658
2659 if (!treasure.is_saved()) {
2660 lua_pushnil(current_l);
2661 }
2662 else {
2663 lua_pushstring(current_l, treasure.get_savegame_variable().c_str());
2664 }
2665
2666 call_function(4, 0, "on_opened");
2667 return true;
2668 }
2669
2670 return false;
2671 }
2672
2673 /**
2674 * \brief Calls the on_closed() method of the object on top of the stack.
2675 */
on_closed()2676 void LuaContext::on_closed() {
2677 check_callback_thread();
2678 if (find_method("on_closed")) {
2679 call_function(1, 0, "on_closed");
2680 }
2681 }
2682
2683 /**
2684 * \brief Calls the on_moving() method of the object on top of the stack.
2685 */
on_moving()2686 void LuaContext::on_moving() {
2687 check_callback_thread();
2688 if (find_method("on_moving")) {
2689 call_function(1, 0, "on_moving");
2690 }
2691 }
2692
2693 /**
2694 * \brief Calls the on_moved() method of the object on top of the stack.
2695 */
on_moved()2696 void LuaContext::on_moved() {
2697 check_callback_thread();
2698 if (find_method("on_moved")) {
2699 call_function(1, 0, "on_moved");
2700 }
2701 }
2702
2703 /**
2704 * \brief Calls the on_map_changed() method of the object on top of the stack.
2705 * \param map The new active map.
2706 */
on_map_changed(Map & map)2707 void LuaContext::on_map_changed(Map& map) {
2708 check_callback_thread();
2709 if (find_method("on_map_changed")) {
2710 push_map(current_l, map);
2711 call_function(2, 0, "on_map_changed");
2712 }
2713 }
2714
2715 /**
2716 * \brief Calls the on_game_changed() method of the object on top of the stack.
2717 * \param previous_world The previous world or an empty string.
2718 * \param new_world The new world or an empty string.
2719 */
on_world_changed(const std::string & previous_world,const std::string & new_world)2720 void LuaContext::on_world_changed(const std::string& previous_world, const std::string& new_world) {
2721 check_callback_thread();
2722 if (find_method("on_world_changed")) {
2723 if (previous_world.empty()) {
2724 lua_pushnil(current_l);
2725 }
2726 else {
2727 push_string(current_l, previous_world);
2728 }
2729
2730 if (new_world.empty()) {
2731 lua_pushnil(current_l);
2732 }
2733 else {
2734 push_string(current_l, new_world);
2735 }
2736 call_function(3, 0, "on_world_changed");
2737 }
2738 }
2739
2740 /**
2741 * \brief Calls the on_pickable_created() method of the object on top of the stack.
2742 * \param pickable A pickable treasure.
2743 */
on_pickable_created(Pickable & pickable)2744 void LuaContext::on_pickable_created(Pickable& pickable) {
2745 check_callback_thread();
2746 if (find_method("on_pickable_created")) {
2747 push_entity(current_l, pickable);
2748 call_function(2, 0, "on_pickable_created");
2749 }
2750 }
2751
2752 /**
2753 * \brief Calls the on_variant_changed() method of the object on top of the stack.
2754 * \param variant Variant of an equipment item.
2755 */
on_variant_changed(int variant)2756 void LuaContext::on_variant_changed(int variant) {
2757 check_callback_thread();
2758 if (find_method("on_variant_changed")) {
2759 lua_pushinteger(current_l, variant);
2760 call_function(2, 0, "on_variant_changed");
2761 }
2762 }
2763
2764 /**
2765 * \brief Calls the on_amount_changed() method of the object on top of the stack.
2766 * \param amount Amount of an equipment item.
2767 */
on_amount_changed(int amount)2768 void LuaContext::on_amount_changed(int amount) {
2769 check_callback_thread();
2770 if (find_method("on_amount_changed")) {
2771 lua_pushinteger(current_l, amount);
2772 call_function(2, 0, "on_amount_changed");
2773 }
2774 }
2775
2776 /**
2777 * \brief Calls the on_obtaining() method of the object on top of the stack.
2778 * \param treasure The treasure being obtained.
2779 */
on_obtaining(const Treasure & treasure)2780 void LuaContext::on_obtaining(const Treasure& treasure) {
2781 check_callback_thread();
2782 if (find_method("on_obtaining")) {
2783 lua_pushinteger(current_l, treasure.get_variant());
2784 if (!treasure.is_saved()) {
2785 lua_pushnil(current_l);
2786 }
2787 else {
2788 lua_pushstring(current_l, treasure.get_savegame_variable().c_str());
2789 }
2790 call_function(3, 0, "on_obtaining");
2791 }
2792 }
2793
2794 /**
2795 * \brief Calls the on_obtained() method of the object on top of the stack.
2796 * \param treasure The treasure just obtained.
2797 */
on_obtained(const Treasure & treasure)2798 void LuaContext::on_obtained(const Treasure& treasure) {
2799 check_callback_thread();
2800 if (find_method("on_obtained")) {
2801 lua_pushinteger(current_l, treasure.get_variant());
2802 if (!treasure.is_saved()) {
2803 lua_pushnil(current_l);
2804 }
2805 else {
2806 lua_pushstring(current_l, treasure.get_savegame_variable().c_str());
2807 }
2808 call_function(3, 0, "on_obtained");
2809 }
2810 }
2811
2812 /**
2813 * \brief Calls the on_using() method of the object on top of the stack.
2814 */
on_using()2815 void LuaContext::on_using() {
2816 check_callback_thread();
2817 if (find_method("on_using")) {
2818 call_function(1, 0, "on_using");
2819 }
2820 }
2821
2822 /**
2823 * \brief Calls the on_ability_used() method of the object on top of the stack.
2824 * \param ability A built-in ability.
2825 */
on_ability_used(Ability ability)2826 void LuaContext::on_ability_used(Ability ability) {
2827 check_callback_thread();
2828 if (find_method("on_ability_used")) {
2829 push_string(current_l, enum_to_name(ability));
2830 call_function(2, 0, "on_ability_used");
2831 }
2832 }
2833
2834 /**
2835 * \brief Calls the on_created() method of the object on top of the stack.
2836 */
on_created()2837 void LuaContext::on_created() {
2838 check_callback_thread();
2839 if (find_method("on_created")) {
2840 call_function(1, 0, "on_created");
2841 }
2842 }
2843
2844 /**
2845 * \brief Calls the on_removed() method of the object on top of the stack.
2846 */
on_removed()2847 void LuaContext::on_removed() {
2848 check_callback_thread();
2849 if (find_method("on_removed")) {
2850 call_function(1, 0, "on_removed");
2851 }
2852 }
2853
2854 /**
2855 * \brief Calls the on_enabled() method of the object on top of the stack.
2856 */
on_enabled()2857 void LuaContext::on_enabled() {
2858 check_callback_thread();
2859 if (find_method("on_enabled")) {
2860 call_function(1, 0, "on_enabled");
2861 }
2862 }
2863
2864 /**
2865 * \brief Calls the on_disabled() method of the object on top of the stack.
2866 */
on_disabled()2867 void LuaContext::on_disabled() {
2868 check_callback_thread();
2869 if (find_method("on_disabled")) {
2870 call_function(1, 0, "on_disabled");
2871 }
2872 }
2873
2874 /**
2875 * \brief Calls the on_restarted() method of the object on top of the stack.
2876 */
on_restarted()2877 void LuaContext::on_restarted() {
2878 check_callback_thread();
2879 if (find_method("on_restarted")) {
2880 call_function(1, 0, "on_restarted");
2881 }
2882 }
2883
2884 /**
2885 * \brief Calls the on_pre_draw() method of the object on top of the stack.
2886 * \param camera The camera where to draw.
2887 */
on_pre_draw(Camera & camera)2888 void LuaContext::on_pre_draw(Camera& camera) {
2889 check_callback_thread();
2890 if (find_method("on_pre_draw")) {
2891 push_camera(current_l, camera);
2892 call_function(2, 0, "on_pre_draw");
2893 }
2894 }
2895
2896 /**
2897 * \brief Calls the on_post_draw() method of the object on top of the stack.
2898 * \param camera The camera where to draw.
2899 */
on_post_draw(Camera & camera)2900 void LuaContext::on_post_draw(Camera& camera) {
2901 check_callback_thread();
2902 if (find_method("on_post_draw")) {
2903 push_camera(current_l, camera);
2904 call_function(2, 0, "on_post_draw");
2905 }
2906 }
2907
2908 /**
2909 * \brief Calls the on_position_changed() method of the object on top of the stack.
2910 * \param xy The new position.
2911 * \param layer The new layer.
2912 */
on_position_changed(const Point & xy,int layer)2913 void LuaContext::on_position_changed(const Point& xy, int layer) {
2914 check_callback_thread();
2915 if (find_method("on_position_changed")) {
2916 lua_pushinteger(current_l, xy.x);
2917 lua_pushinteger(current_l, xy.y);
2918 lua_pushinteger(current_l, layer);
2919 call_function(4, 0, "on_position_changed");
2920 }
2921 }
2922
2923 /**
2924 * \brief Calls the on_obstacle_reached() method of the object on top of the stack.
2925 * \param movement The movement that reached an obstacle.
2926 */
on_obstacle_reached(Movement & movement)2927 void LuaContext::on_obstacle_reached(Movement& movement) {
2928 check_callback_thread();
2929 if (find_method("on_obstacle_reached")) {
2930 push_movement(current_l, movement);
2931 call_function(2, 0, "on_obstacle_reached");
2932 }
2933 }
2934
2935 /**
2936 * \brief Calls the on_movement_started() method of the object on top of the stack.
2937 * \param movement A movement.
2938 */
on_movement_started(Movement & movement)2939 void LuaContext::on_movement_started(Movement& movement) {
2940 check_callback_thread();
2941 if (find_method("on_movement_started")) {
2942 push_movement(current_l, movement);
2943 call_function(2, 0, "on_movement_started");
2944 }
2945 }
2946
2947 /**
2948 * \brief Calls the on_movement_changed() method of the object on top of the stack.
2949 * \param movement A movement.
2950 */
on_movement_changed(Movement & movement)2951 void LuaContext::on_movement_changed(Movement& movement) {
2952 check_callback_thread();
2953 if (find_method("on_movement_changed")) {
2954 push_movement(current_l, movement);
2955 call_function(2, 0, "on_movement_changed");
2956 }
2957 }
2958
2959 /**
2960 * \brief Calls the on_movement_finished() method of the object on top of the stack.
2961 */
on_movement_finished()2962 void LuaContext::on_movement_finished() {
2963 check_callback_thread();
2964 if (find_method("on_movement_finished")) {
2965 call_function(1, 0, "on_movement_finished");
2966 }
2967 }
2968
2969 /**
2970 * \brief Calls the on_collision_enemy() method of the object on top of the stack.
2971 * \param other_enemy Another enemy colliding with the object on top of the stack.
2972 * \param other_sprite Colliding sprite of the other enemy.
2973 * \param this_sprite Colliding sprite of the first enemy.
2974 */
on_collision_enemy(Enemy & other_enemy,Sprite & other_sprite,Sprite & this_sprite)2975 void LuaContext::on_collision_enemy(Enemy& other_enemy, Sprite& other_sprite, Sprite& this_sprite) {
2976 check_callback_thread();
2977 if (find_method("on_collision_enemy")) {
2978 push_enemy(current_l, other_enemy);
2979 push_sprite(current_l, other_sprite);
2980 push_sprite(current_l, this_sprite);
2981 call_function(4, 0, "on_collision_enemy");
2982 }
2983 }
2984
2985 /**
2986 * \brief Calls the on_lifted() method of the object on top of the stack.
2987 */
on_lifted()2988 void LuaContext::on_lifted() {
2989 check_callback_thread();
2990 if (find_method("on_lifted")) {
2991 call_function(1, 0, "on_lifted");
2992 }
2993 }
2994
2995 /**
2996 * \brief Calls the on_thrown() method of the object on top of the stack.
2997 */
on_thrown()2998 void LuaContext::on_thrown() {
2999 check_callback_thread();
3000 if (find_method("on_thrown")) {
3001 call_function(1, 0, "on_thrown");
3002 }
3003 }
3004
3005 /**
3006 * \brief Calls the on_breaking() method of the object on top of the stack.
3007 */
on_breaking()3008 void LuaContext::on_breaking() {
3009 check_callback_thread();
3010 if (find_method("on_breaking")) {
3011 call_function(1, 0, "on_breaking");
3012 }
3013 }
3014
3015 /**
3016 * \brief Calls the on_looked() method of the object on top of the stack.
3017 */
on_looked()3018 void LuaContext::on_looked() {
3019 check_callback_thread();
3020 if (find_method("on_looked")) {
3021 call_function(1, 0, "on_looked");
3022 }
3023 }
3024
3025 /**
3026 * \brief Calls the on_cut() method of the object on top of the stack.
3027 */
on_cut()3028 void LuaContext::on_cut() {
3029 check_callback_thread();
3030 if (find_method("on_cut")) {
3031 call_function(1, 0, "on_cut");
3032 }
3033 }
3034
3035 /**
3036 * \brief Calls the on_lifting() method of the object on top of the stack.
3037 * \param carrier Entity that is lifting another one.
3038 * \param carried_object Carried object created to replace
3039 * the entity being lifted.
3040 */
on_lifting(Entity & carrier,CarriedObject & carried_object)3041 void LuaContext::on_lifting(
3042 Entity& carrier,
3043 CarriedObject& carried_object
3044 ) {
3045 check_callback_thread();
3046 if (find_method("on_lifting")) {
3047 push_entity(current_l, carrier);
3048 push_carried_object(current_l, carried_object);
3049 call_function(3, 0, "on_lifting");
3050 }
3051 }
3052
3053 /**
3054 * \brief Calls the on_exploded() method of the object on top of the stack.
3055 */
on_exploded()3056 void LuaContext::on_exploded() {
3057 check_callback_thread();
3058 if (find_method("on_exploded")) {
3059 call_function(1, 0, "on_exploded");
3060 }
3061 }
3062
3063 /**
3064 * \brief Calls the on_regenerating() method of the object on top of the stack.
3065 */
on_regenerating()3066 void LuaContext::on_regenerating() {
3067 check_callback_thread();
3068 if (find_method("on_regenerating")) {
3069 call_function(1, 0, "on_regenerating");
3070 }
3071 }
3072
3073 /**
3074 * \brief Calls the on_custom_attack_received() method of the object on top of the stack.
3075 * \param attack The attack received.
3076 * \param sprite The sprite that receives the attack if any.
3077 */
on_custom_attack_received(EnemyAttack attack,Sprite * sprite)3078 void LuaContext::on_custom_attack_received(EnemyAttack attack, Sprite* sprite) {
3079 check_callback_thread();
3080 if (find_method("on_custom_attack_received")) {
3081 push_string(current_l, Enemy::attack_names.find(attack)->second);
3082 if (sprite != nullptr) {
3083 // Pixel-precise collision.
3084 push_sprite(current_l, *sprite);
3085 call_function(3, 0, "on_custom_attack_received");
3086 }
3087 else {
3088 call_function(2, 0, "on_custom_attack_received");
3089 }
3090 }
3091 }
3092
3093 /**
3094 * \brief Calls the on_hurt_by_sword() method of the object on top of the stack.
3095 * \param hero The hero whose sword is hitting the enemy.
3096 * \param enemy_sprite Sprite of the enemy that gets hits.
3097 * \return \c true if the method is defined.
3098 */
on_hurt_by_sword(Hero & hero,Sprite & enemy_sprite)3099 bool LuaContext::on_hurt_by_sword(Hero& hero, Sprite& enemy_sprite) {
3100 check_callback_thread();
3101 if (find_method("on_hurt_by_sword")) {
3102 push_hero(current_l, hero);
3103 push_sprite(current_l, enemy_sprite);
3104 call_function(3, 0, "on_hurt_by_sword");
3105 return true;
3106 }
3107 return false;
3108 }
3109
3110 /**
3111 * \brief Calls the on_hurt() method of the object on top of the stack.
3112 * \param attack The attack received.
3113 */
on_hurt(EnemyAttack attack)3114 void LuaContext::on_hurt(EnemyAttack attack) {
3115 check_callback_thread();
3116 if (find_method("on_hurt")) {
3117 push_string(current_l, Enemy::attack_names.find(attack)->second);
3118 call_function(2, 0, "on_hurt");
3119 }
3120 }
3121
3122 /**
3123 * \brief Calls the on_dying() method of the object on top of the stack.
3124 */
on_dying()3125 void LuaContext::on_dying() {
3126 check_callback_thread();
3127 if (find_method("on_dying")) {
3128 call_function(1, 0, "on_dying");
3129 }
3130 }
3131
3132 /**
3133 * \brief Calls the on_dead() method of the object on top of the stack.
3134 */
on_dead()3135 void LuaContext::on_dead() {
3136 check_callback_thread();
3137 if (find_method("on_dead")) {
3138 call_function(1, 0, "on_dead");
3139 }
3140 }
3141
3142 /**
3143 * \brief Calls the on_immobilized() method of the object on top of the stack.
3144 */
on_immobilized()3145 void LuaContext::on_immobilized() {
3146 check_callback_thread();
3147 if (find_method("on_immobilized")) {
3148 call_function(1, 0, "on_immobilized");
3149 }
3150 }
3151
3152 /**
3153 * \brief Calls the on_attacking_hero() method of the object on top of the stack.
3154 * \param hero The hero attacked.
3155 * \param attacker_sprite Sprite that caused the collision or nullptr.
3156 * \return \c true if the method is defined.
3157 */
on_attacking_hero(Hero & hero,Sprite * attacker_sprite)3158 bool LuaContext::on_attacking_hero(Hero& hero, Sprite* attacker_sprite) {
3159 check_callback_thread();
3160 if (find_method("on_attacking_hero")) {
3161 push_hero(current_l, hero);
3162 if (attacker_sprite == nullptr) {
3163 lua_pushnil(current_l);
3164 }
3165 else {
3166 push_sprite(current_l, *attacker_sprite);
3167 }
3168 call_function(3, 0, "on_attacking_hero");
3169 return true;
3170 }
3171 return false;
3172 }
3173
3174 /**
3175 * \brief Calls the on_attacked_enemy() method of the object on top of the stack.
3176 * \param The enemy that was attacked.
3177 * \param enemy_sprite Sprite that was attacked if any.
3178 * \param attack How the enemy was attacked.
3179 * \param reaction How the enemy reacted to the attack.
3180 */
on_attacked_enemy(Enemy & enemy,Sprite * enemy_sprite,EnemyAttack attack,const EnemyReaction::Reaction & reaction)3181 void LuaContext::on_attacked_enemy(
3182 Enemy& enemy,
3183 Sprite* enemy_sprite,
3184 EnemyAttack attack,
3185 const EnemyReaction::Reaction& reaction
3186 ) {
3187 check_callback_thread();
3188 if (find_method("on_attacked_enemy")) {
3189 push_enemy(current_l, enemy);
3190 if (enemy_sprite == nullptr) {
3191 lua_pushnil(current_l);
3192 } else {
3193 push_sprite(current_l, *enemy_sprite);
3194 }
3195 push_string(current_l, Enemy::attack_names.find(attack)->second);
3196
3197 if (reaction.type == EnemyReaction::ReactionType::HURT) {
3198 lua_pushinteger(current_l, reaction.life_lost);
3199 } else if (reaction.type == EnemyReaction::ReactionType::LUA_CALLBACK) {
3200 reaction.callback.push(current_l);
3201 } else {
3202 push_string(current_l, enum_to_name(reaction.type));
3203 }
3204
3205 call_function(5, 0, "on_attacked_enemy");
3206 }
3207 }
3208
3209 /**
3210 * \brief Calls the on_ground_below_changed() method of the object on top of the stack.
3211 * \param ground_below The new ground below the object.
3212 */
on_ground_below_changed(Ground ground_below)3213 void LuaContext::on_ground_below_changed(Ground ground_below) {
3214 check_callback_thread();
3215 if (find_method("on_ground_below_changed")) {
3216 if (ground_below == Ground::EMPTY) {
3217 lua_pushnil(current_l);
3218 }
3219 else {
3220 push_string(current_l, enum_to_name(ground_below));
3221 }
3222 call_function(2, 0, "on_ground_below_changed");
3223 }
3224 }
3225
3226 /**
3227 * \brief Calls the on_map_started() method of the object on top of the stack.
3228 * \param map The map.
3229 * \param destination Destination entity where the hero is placed or nullptr.
3230 */
on_map_started(Map & map,const std::shared_ptr<Destination> & destination)3231 void LuaContext::on_map_started(
3232 Map& map, const std::shared_ptr<Destination>& destination) {
3233
3234 check_callback_thread();
3235 if (find_method("on_map_started")) {
3236 push_map(current_l, map);
3237 if (destination == nullptr) {
3238 lua_pushnil(current_l);
3239 }
3240 else {
3241 push_entity(current_l, *destination);
3242 }
3243 call_function(3, 0, "on_map_started");
3244 }
3245 }
3246
3247 /**
3248 * \brief Calls the on_map_opening_transition_finished() method of the object on top of the stack.
3249 * \param map The map.
3250 * \param destination Destination entity where the hero is placed or nullptr.
3251 */
on_map_opening_transition_finished(Map & map,const std::shared_ptr<Destination> & destination)3252 void LuaContext::on_map_opening_transition_finished(
3253 Map& map, const std::shared_ptr<Destination>& destination) {
3254
3255 check_callback_thread();
3256 if (find_method("on_map_opening_transition_finished")) {
3257 push_map(current_l, map);
3258 if (destination == nullptr) {
3259 lua_pushnil(current_l);
3260 }
3261 else {
3262 push_entity(current_l, *destination);
3263 }
3264 call_function(3, 0, "on_map_opening_transition_finished");
3265 }
3266 }
3267
3268 /**
3269 * \brief Calls the on_map_finished() method of the object on top of the stack.
3270 */
on_map_finished()3271 void LuaContext::on_map_finished() {
3272
3273 check_callback_thread();
3274 if (find_method("on_map_finished")) {
3275 call_function(1, 0, "on_map_finished");
3276 }
3277 }
3278
3279 /**
3280 * \brief Function called when an unprotected Lua error occurs.
3281 * \param l The Lua context.
3282 * \return Number of values to return to Lua.
3283 */
l_panic(lua_State * l)3284 int LuaContext::l_panic(lua_State* l) {
3285
3286 const std::string& error = luaL_checkstring(l, 1);
3287
3288 Debug::die(error);
3289 }
3290
3291 /**
3292 * \brief A loader that makes require() able to load Lua files
3293 * from the quest data directory or archive.
3294 * \param l The Lua context.
3295 * \return Number of values to return to Lua.
3296 */
l_loader(lua_State * l)3297 int LuaContext::l_loader(lua_State* l) {
3298
3299 return state_boundary_handle(l, [&] {
3300 const std::string& script_name = luaL_checkstring(l, 1);
3301 bool load_success = get().load_file(script_name);
3302
3303 if (!load_success) {
3304 std::ostringstream oss;
3305 oss << std::endl << "\tno quest file '" << script_name
3306 << ".lua' in 'data/', 'data.solarus' or 'data.solarus.zip'";
3307 push_string(l, oss.str());
3308 }
3309 return 1;
3310 });
3311 }
3312
3313 /**
3314 * \brief A function that prints the stack trace of an error raised in Lua.
3315 * \param l The Lua context.
3316 * \return Number of values to return to Lua.
3317 */
l_backtrace(lua_State * l)3318 int LuaContext::l_backtrace(lua_State* l) {
3319
3320 if (!lua_isstring(l, 1)) {
3321 push_string(l, "Unknown error");
3322 return 1;
3323 }
3324 lua_getglobal(l, "debug");
3325 if (!lua_istable(l, -1)) {
3326 lua_pushvalue(l, 1); // Return the original error message.
3327 return 1;
3328 }
3329 lua_getfield(l, -1, "traceback");
3330 if (!lua_isfunction(l, -1)) {
3331 lua_pushvalue(l, 1); // Return the original error message.
3332 return 1;
3333 }
3334 lua_pushvalue(l, 1); // pass error message
3335 lua_call(l, 1, 1); // call debug.traceback
3336 return 1;
3337 }
3338
3339 }
3340
3341