From: Matthias Braun Date: Mon, 10 Apr 2006 22:08:23 +0000 (+0000) Subject: Major rewrite of scripting support: X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=f3e5e57c9996168a4889ae8e195be25f8b7e629b;p=supertux.git Major rewrite of scripting support: - Add squirrel support to console - Reused ScriptManager from windstille (with some modifications now) - Added some new scripting commands (display, load_worldmap, load_level, wait_for_screenswitch, maybe others which I forgot) - Improved miniswig generated wrapper functions to check arguments passed and to catch exceptions and transform them into squirrel exceptions - All scripts are run as cooperative threads now - Sectors have a custom squirrel table now that contains all their objects and which has the (real) roottable set as parent. Sectorscripts use this sectortable as roottable. SVN-Revision: 3287 --- diff --git a/data/levels/test/default.nut b/data/levels/test/default.nut index d569d68f0..34e17f7c3 100644 --- a/data/levels/test/default.nut +++ b/data/levels/test/default.nut @@ -1,4 +1,5 @@ /* Default functions for the whole levelset */ +print("default.nut loaded\n"); function intro() { @@ -7,13 +8,13 @@ function intro() RADIO.set_action("quiet"); PENNY.set_action("stand-left"); NOLOK.set_visible(false); - local logo = FloatingImage("images/objects/logo/logo.sprite"); + logo <- FloatingImage("images/objects/logo/logo.sprite"); Tux.deactivate(); Tux.set_visible(false); - DisplayEffect.sixteen_to_nine(0); + Effect.sixteen_to_nine(0); //begin scrolling sequence - DisplayEffect.fade_in(2); + Effect.fade_in(2); Camera.scroll_to(0, 945, 15); Sound.play("music/intro.ogg"); wait(3); @@ -53,7 +54,7 @@ function intro() //enter Nolok NOLOK.set_velocity(-220, 600); NOLOK.set_visible(true); - DisplayEffect.fade_out(1.3); + Effect.fade_out(1.3); wait(3); //darkness @@ -63,7 +64,7 @@ function intro() SUPERTUX.set_pos(3550, SUPERTUX.get_pos_y()); //wake up, Tux... - DisplayEffect.fade_in(4); + Effect.fade_in(4); wait(4); Sound.play("speech/tux_upset.ogg"); wait(3); @@ -76,7 +77,7 @@ function intro() wait(2); //end intro sequence - DisplayEffect.fade_out(2); + Effect.fade_out(2); wait(3); Level.finish(true); } @@ -113,9 +114,9 @@ function intro_scene2() NOLOK.set_visible(false); Tux.deactivate(); Tux.set_visible(false); - DisplayEffect.sixteen_to_nine(0); + Effect.sixteen_to_nine(0); Sound.play("music/nolok.ogg"); - DisplayEffect.fade_in(5); + Effect.fade_in(5); wait(5); Camera.scroll_to(3100, 945, 8); NOLOK.set_visible(true); diff --git a/data/levels/test/intro.stl b/data/levels/test/intro.stl index b93450e88..7d8dc55a3 100644 --- a/data/levels/test/intro.stl +++ b/data/levels/test/intro.stl @@ -108,7 +108,10 @@ (y 510) (sprite "images/creatures/dummyguy/dummyguy.sprite") ) - (init-script "intro();") + (init-script " + import(\"levels/test/default.nut\"); + intro(); + ") ) ) diff --git a/data/levels/test/intro2.stl b/data/levels/test/intro2.stl index 89666651c..bcfa1006e 100644 --- a/data/levels/test/intro2.stl +++ b/data/levels/test/intro2.stl @@ -5,7 +5,10 @@ (author "SuperTux Team") (sector (name "main") - (init-script "intro()") + (init-script " + import(\"levels/test/default.nut\"); + intro(); + ") (gravity 10.000000) (tilemap (layer "background") diff --git a/data/levels/world1/world.nut b/data/levels/world1/world.nut new file mode 100644 index 000000000..94aac6617 --- /dev/null +++ b/data/levels/world1/world.nut @@ -0,0 +1,6 @@ +print("Hello World\n"); +display_text_file("levels/world1/intro.txt"); +wait_for_screenswitch(); +wait_for_screenswitch(); +load_worldmap("levels/world1/worldmap.stwm"); + diff --git a/data/levels/world2/default.nut b/data/levels/world2/default.nut index ca65fc778..0713e291c 100644 --- a/data/levels/world2/default.nut +++ b/data/levels/world2/default.nut @@ -10,13 +10,13 @@ function level2_init() add_key(KEY_BRASS); add_key(KEY_IRON); Tux.deactivate(); - DisplayEffect.sixteen_to_nine(2); + Effect.sixteen_to_nine(2); Text.set_text(translate("---Insert Cutscene Here---")); Tux.walk(100); Text.fade_in(2); wait(4); Text.fade_out(1); wait(1); - DisplayEffect.four_to_three(); + Effect.four_to_three(); Tux.activate(); } diff --git a/data/levels/world2/level2.stl b/data/levels/world2/level2.stl index 757146bce..6901b9a98 100644 --- a/data/levels/world2/level2.stl +++ b/data/levels/world2/level2.stl @@ -189,7 +189,11 @@ (image "images/background/forest1.jpg") (speed 0.7) ) - (init-script "level2_init();") + (init-script " + import(\"levels/world2/default.nut\"); + import(\"script/default.nut\"); + level2_init(); + ") (secretarea (x 673.0) (y 1090.0) (width 24.0) diff --git a/data/script/default.nut b/data/script/default.nut index 95b4f1340..6629aaef3 100644 --- a/data/script/default.nut +++ b/data/script/default.nut @@ -4,15 +4,15 @@ function end_level() Sound.play_music("music/leveldone.ogg"); Tux.deactivate(); wait(6); - DisplayEffect.fade_out(2); + Effect.fade_out(2); wait(2); Level.finish(); } function levelflip() { - DisplayEffect.fade_out(1); + Effect.fade_out(1); wait(1); Level.flip_vertically(); - DisplayEffect.fade_in(1); + Effect.fade_in(1); } diff --git a/src/badguy/yeti.cpp b/src/badguy/yeti.cpp index f11a6e241..f34a550fe 100644 --- a/src/badguy/yeti.cpp +++ b/src/badguy/yeti.cpp @@ -27,7 +27,6 @@ #include "yeti_stalactite.hpp" #include "bouncing_snowball.hpp" #include "game_session.hpp" -#include "scripting/script_interpreter.hpp" static const float JUMP_VEL1 = 250; static const float JUMP_VEL2 = 700; @@ -155,8 +154,8 @@ Yeti::collision_squished(Player& player) // start script if(dead_script != "") { - ScriptInterpreter::add_script_object(Sector::current(), - "Yeti - dead-script", dead_script); + std::istringstream stream(dead_script); + Sector::current()->run_script(stream, "Yeti - dead-script"); } } else { safe_timer.start(SAFE_TIME); diff --git a/src/console.cpp b/src/console.cpp index 69f854753..da30b2225 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -16,13 +16,16 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - #include + #include #include "console.hpp" #include "video/drawing_context.hpp" #include "video/surface.hpp" +#include "scripting/squirrel_error.hpp" +#include "scripting/wrapper_util.hpp" #include "player_status.hpp" +#include "script_manager.hpp" #include "main.hpp" #include "resources.hpp" @@ -65,6 +68,39 @@ Console::flush(ConsoleStreamBuffer* buffer) } void +Console::execute_script(const std::string& command) +{ + using namespace Scripting; + + HSQUIRRELVM vm = script_manager->get_global_vm(); + + if(command == "") + return; + + int oldtop = sq_gettop(vm); + try { + if(SQ_FAILED(sq_compilebuffer(vm, command.c_str(), command.length(), + "", SQTrue))) + throw SquirrelError(vm, "Couldn't compile command"); + + sq_pushroottable(vm); + if(SQ_FAILED(sq_call(vm, 1, SQTrue))) + throw SquirrelError(vm, "Problem while executing command"); + + if(sq_gettype(vm, -1) != OT_NULL) + addLine(squirrel2string(vm, -1)); + } catch(std::exception& e) { + addLine(e.what()); + } + int newtop = sq_gettop(vm); + if(newtop < oldtop) { + msg_fatal << "Script destroyed squirrel stack..." << std::endl; + } else { + sq_settop(vm, oldtop); + } +} + +void Console::backspace() { std::string s = inputBuffer.str(); @@ -150,7 +186,11 @@ Console::parse(std::string s) // look up registered ccr std::map >::iterator i = commands.find(command); if ((i == commands.end()) || (i->second.size() == 0)) { - addLine("unknown command: \"" + command + "\""); + try { + execute_script(s); + } catch(std::exception& e) { + addLine(e.what()); + } return; } diff --git a/src/console.hpp b/src/console.hpp index 7834d76f6..1863309f8 100644 --- a/src/console.hpp +++ b/src/console.hpp @@ -91,6 +91,10 @@ class Console static void addLine(std::string s); /**< display a line in the console */ static void parse(std::string s); /**< react to a given command */ + + /** execute squirrel script and output result */ + static void execute_script(const std::string& s); + static bool consoleCommand(std::string command, std::vector arguments); /**< process internal command; return false if command was unknown, true otherwise */ friend class ConsoleStreamBuffer; @@ -102,20 +106,25 @@ class ConsoleStreamBuffer : public std::stringbuf public: int sync() { + int result = std::stringbuf::sync(); Console::flush(this); - return std::stringbuf::sync(); + return result; } }; class ConsoleCommandReceiver { - public: - ConsoleCommandReceiver() {} - virtual bool consoleCommand(std::string command, std::vector arguments) = 0; /**< callback from Console; return false if command was unknown, true otherwise */ - virtual ~ConsoleCommandReceiver() - { - Console::unregisterCommands(this); - } +public: + virtual ~ConsoleCommandReceiver() + { + Console::unregisterCommands(this); + } + + /** + * callback from Console; return false if command was unknown, + * true otherwise + */ + virtual bool consoleCommand(std::string command, std::vector arguments) = 0; }; #endif diff --git a/src/control/controller.hpp b/src/control/controller.hpp index 3e37cf728..026ec2af1 100644 --- a/src/control/controller.hpp +++ b/src/control/controller.hpp @@ -47,7 +47,7 @@ public: bool hold(Control control); /** returns true if the control has just been pressed down this frame */ bool pressed(Control control); - /** returns true if the control has just been released down this frame */ + /** returns true if the control has just been released this frame */ bool released(Control control); virtual void reset(); diff --git a/src/exceptions.hpp b/src/exceptions.hpp deleted file mode 100644 index 5fa82a5fd..000000000 --- a/src/exceptions.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2005 Matthias Braun -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -// 02111-1307, USA. -#ifndef __EXCEPTIONS_H__ -#define __EXCEPTIONS_H__ - -#include - -/** Throw this exception to gracefully shut SuperTux down. - */ -class graceful_shutdown : public std::exception -{ -public: - explicit graceful_shutdown() {}; -}; - -#endif diff --git a/src/game_session.cpp b/src/game_session.cpp index bad7bfd63..f0da60304 100644 --- a/src/game_session.cpp +++ b/src/game_session.cpp @@ -67,7 +67,7 @@ #include "file_system.hpp" #include "gameconfig.hpp" #include "gettext.hpp" -#include "exceptions.hpp" +#include "console.hpp" #include "flip_level_transformer.hpp" // the engine will be run with a logical framerate of 64fps. @@ -696,12 +696,13 @@ GameSession::display_info_box(const std::string& text) while(running) { + // TODO make a screen out of this, another mainloop is ugly main_controller->update(); SDL_Event event; while (SDL_PollEvent(&event)) { main_controller->process_event(event); if(event.type == SDL_QUIT) - throw graceful_shutdown(); + main_loop->quit(); } if(main_controller->pressed(Controller::JUMP) diff --git a/src/gui/menu.cpp b/src/gui/menu.cpp index 052a54d13..4e28ff27e 100644 --- a/src/gui/menu.cpp +++ b/src/gui/menu.cpp @@ -30,6 +30,7 @@ #include #include "menu.hpp" +#include "mainloop.hpp" #include "video/screen.hpp" #include "video/drawing_context.hpp" #include "gettext.hpp" @@ -37,7 +38,6 @@ #include "main.hpp" #include "resources.hpp" #include "control/joystickkeyboardcontroller.hpp" -#include "exceptions.hpp" static const int MENU_REPEAT_INITIAL = 400; static const int MENU_REPEAT_RATE = 200; @@ -68,12 +68,13 @@ bool confirm_dialog(Surface *background, std::string text) DrawingContext context; + // TODO make this a screen and not another mainloop... while(true) { SDL_Event event; while (SDL_PollEvent(&event)) { if(event.type == SDL_QUIT) - throw graceful_shutdown(); + main_loop->quit(); main_controller->process_event(event); dialog->event(event); } diff --git a/src/main.cpp b/src/main.cpp index 2bfbed289..8874b003e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,9 +48,12 @@ #include "mainloop.hpp" #include "title.hpp" #include "game_session.hpp" +#include "script_manager.hpp" +#include "scripting/sound.hpp" +#include "scripting/level.hpp" +#include "scripting/wrapper_util.hpp" #include "file_system.hpp" #include "physfs/physfs_sdl.hpp" -#include "exceptions.hpp" SDL_Surface* screen = 0; JoystickKeyboardController* main_controller = 0; @@ -193,7 +196,7 @@ static void print_usage(const char* argv0) "\n")); } -static void parse_commandline(int argc, char** argv) +static bool parse_commandline(int argc, char** argv) { for(int i = 1; i < argc; ++i) { std::string arg = argv[i]; @@ -232,10 +235,10 @@ static void parse_commandline(int argc, char** argv) config->record_demo = argv[++i]; } else if(arg == "--help") { print_usage(argv[0]); - throw graceful_shutdown(); + return true; } else if(arg == "--version") { msg_info << PACKAGE_NAME << " " << PACKAGE_VERSION << std::endl; - throw graceful_shutdown(); + return true; } else if(arg[0] != '-') { config->start_level = arg; } else { @@ -243,7 +246,7 @@ static void parse_commandline(int argc, char** argv) } } - // TODO joystick switchyes... + return false; } static void init_sdl() @@ -374,11 +377,22 @@ static void init_audio() sound_manager->enable_music(config->music_enabled); } +static void init_scripting() +{ + script_manager = new ScriptManager(); + + HSQUIRRELVM vm = script_manager->get_global_vm(); + sq_pushroottable(vm); + expose_object(vm, -1, new Scripting::Sound(), "Sound", true); + expose_object(vm, -1, new Scripting::Level(), "Level", true); + sq_pop(vm, 1); +} + static void quit_audio() { - if(sound_manager) { + if(sound_manager != NULL) { delete sound_manager; - sound_manager = 0; + sound_manager = NULL; } } @@ -395,7 +409,7 @@ void wait_for_event(float min_delay, float max_delay) sound_manager->update(); } - // clear even queue + // clear event queue SDL_Event event; while (SDL_PollEvent(&event)) {} @@ -407,7 +421,8 @@ void wait_for_event(float min_delay, float max_delay) while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: - throw graceful_shutdown(); + main_loop->quit(); + break; case SDL_KEYDOWN: case SDL_JOYBUTTONDOWN: case SDL_MOUSEBUTTONDOWN: @@ -455,11 +470,14 @@ int main(int argc, char** argv) timelog("tinygettext"); init_tinygettext(); timelog("commandline"); - parse_commandline(argc, argv); + if(parse_commandline(argc, argv)) + return 0; timelog("audio"); init_audio(); timelog("video"); init_video(); + timelog("scripting"); + init_scripting(); timelog("menu"); setup_menu(); @@ -489,7 +507,6 @@ int main(int argc, char** argv) delete main_loop; main_loop = NULL; - } catch(graceful_shutdown& e) { } catch(std::exception& e) { msg_fatal << "Unexpected exception: " << e.what() << std::endl; return 1; @@ -499,14 +516,20 @@ int main(int argc, char** argv) } free_menu(); + delete script_manager; + script_manager = NULL; + printf("crashunloadshared?\n"); unload_shared(); quit_audio(); if(config) config->save(); delete config; + config = NULL; delete main_controller; + main_controller = NULL; delete texture_manager; + texture_manager = NULL; SDL_Quit(); PHYSFS_deinit(); diff --git a/src/mainloop.cpp b/src/mainloop.cpp index 1c98cd499..afd60ae08 100644 --- a/src/mainloop.cpp +++ b/src/mainloop.cpp @@ -26,9 +26,11 @@ #include "control/joystickkeyboardcontroller.hpp" #include "gui/menu.hpp" #include "audio/sound_manager.hpp" +#include "script_manager.hpp" #include "gameconfig.hpp" #include "main.hpp" #include "resources.hpp" +#include "script_manager.hpp" #include "screen.hpp" #include "timer.hpp" @@ -97,10 +99,13 @@ MainLoop::run() running = true; while(running) { if(next_screen.get() != NULL) { - if(nextpush) + if(nextpush && current_screen.get() != NULL) { + current_screen->leave(); screen_stack.push_back(current_screen.release()); + } next_screen->setup(); + script_manager->fire_wakeup_event(ScriptManager::SCREEN_SWITCHED); current_screen.reset(next_screen.release()); next_screen.reset(NULL); nextpush = false; @@ -159,8 +164,9 @@ MainLoop::run() elapsed_time *= speed; game_time += elapsed_time; + script_manager->update(); current_screen->update(elapsed_time); - + main_controller->update(); SDL_Event event; while(SDL_PollEvent(&event)) { diff --git a/src/object/camera.cpp b/src/object/camera.cpp index c1077cc43..61d404a18 100644 --- a/src/object/camera.cpp +++ b/src/object/camera.cpp @@ -25,6 +25,8 @@ #include "lisp/lisp.hpp" #include "lisp/writer.hpp" #include "lisp/list_iterator.hpp" +#include "scripting/camera.hpp" +#include "scripting/wrapper_util.hpp" #include "camera.hpp" #include "player.hpp" #include "tilemap.hpp" @@ -46,6 +48,19 @@ Camera::~Camera() { } +void +Camera::expose(HSQUIRRELVM vm, int table_idx) +{ + Scripting::Camera* interface = new Scripting::Camera(this); + expose_object(vm, table_idx, interface, "Camera", true); +} + +void +Camera::unexpose(HSQUIRRELVM vm, int table_idx) +{ + Scripting::unexpose_object(vm, table_idx, "Camera"); +} + const Vector& Camera::get_translation() const { diff --git a/src/object/camera.hpp b/src/object/camera.hpp index 0be750e92..ed7b5a7e2 100644 --- a/src/object/camera.hpp +++ b/src/object/camera.hpp @@ -28,6 +28,7 @@ #include "video/drawing_context.hpp" #include "serializable.hpp" #include "timer.hpp" +#include "script_interface.hpp" namespace lisp { class Lisp; @@ -37,7 +38,7 @@ class Sector; class Path; class PathWalker; -class Camera : public GameObject, public Serializable +class Camera : public GameObject, public Serializable, public ScriptInterface { public: Camera(Sector* sector); @@ -60,6 +61,9 @@ public: { } + virtual void expose(HSQUIRRELVM vm, int table_idx); + virtual void unexpose(HSQUIRRELVM vm, int table_idx); + // shake camera in a direction 1 time void shake(float speed, float x, float y); diff --git a/src/object/display_effect.cpp b/src/object/display_effect.cpp index ffa154dc9..c2b1538d6 100644 --- a/src/object/display_effect.cpp +++ b/src/object/display_effect.cpp @@ -3,6 +3,7 @@ #include #include "video/drawing_context.hpp" +#include "scripting/wrapper_util.hpp" #include "main.hpp" static const float BORDER_SIZE = 75; @@ -19,6 +20,23 @@ DisplayEffect::~DisplayEffect() } void +DisplayEffect::expose(HSQUIRRELVM vm, int table_idx) +{ + Scripting::DisplayEffect* interface = static_cast (this); + expose_object(vm, table_idx, interface, "Effect", false); +} + +void +DisplayEffect::unexpose(HSQUIRRELVM vm, int table_idx) +{ + try { + Scripting::unexpose_object(vm, table_idx, "Effect"); + } catch(...) { + // for now... + } +} + +void DisplayEffect::update(float elapsed_time) { switch(screen_fade) { diff --git a/src/object/display_effect.hpp b/src/object/display_effect.hpp index 033d8adae..972b5dcbc 100644 --- a/src/object/display_effect.hpp +++ b/src/object/display_effect.hpp @@ -3,13 +3,18 @@ #include "scripting/display_effect.hpp" #include "game_object.hpp" +#include "script_interface.hpp" -class DisplayEffect : public GameObject, public Scripting::DisplayEffect +class DisplayEffect : public GameObject, public Scripting::DisplayEffect, + public ScriptInterface { public: DisplayEffect(); virtual ~DisplayEffect(); + void expose(HSQUIRRELVM vm, int table_idx); + void unexpose(HSQUIRRELVM vm, int table_idx); + void update(float elapsed_time); void draw(DrawingContext& context); diff --git a/src/object/player.cpp b/src/object/player.cpp index 96e10b31f..659328d0f 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -41,6 +41,7 @@ #include "object/bullet.hpp" #include "trigger/trigger_base.hpp" #include "control/joystickkeyboardcontroller.hpp" +#include "scripting/wrapper_util.hpp" #include "main.hpp" #include "platform.hpp" #include "badguy/badguy.hpp" @@ -107,8 +108,6 @@ Player::Player(PlayerStatus* _player_status) smalltux_star = sprite_manager->create("images/creatures/tux_small/smalltux-star.sprite"); bigtux_star = sprite_manager->create("images/creatures/tux_big/bigtux-star.sprite"); - Console::registerCommand("set_bonus", this); - init(); } @@ -153,6 +152,19 @@ Player::init() } void +Player::expose(HSQUIRRELVM vm, int table_idx) +{ + Scripting::Player* interface = static_cast (this); + expose_object(vm, table_idx, interface, "Tux", false); +} + +void +Player::unexpose(HSQUIRRELVM vm, int table_idx) +{ + Scripting::unexpose_object(vm, table_idx, "Tux"); +} + +void Player::set_controller(Controller* controller) { this->controller = controller; @@ -953,27 +965,3 @@ void Player::walk(float speed) physic.set_velocity_x(speed); } -bool -Player::consoleCommand(std::string command, std::vector arguments) -{ - if (command == "set_bonus") { - if (arguments.size() == 1) { - if (arguments[0] == "egg") { - set_bonus(GROWUP_BONUS, false); - return true; - } - if (arguments[0] == "fire") { - set_bonus(FIRE_BONUS, false); - return true; - } - if (arguments[0] == "ice") { - set_bonus(ICE_BONUS, false); - return true; - } - } - msg_info << "Usage: give {\"egg\" | \"fire\" | \"ice\"}" << std::endl; - return true; - } - return false; -} - diff --git a/src/object/player.hpp b/src/object/player.hpp index 43cddf999..eb5ab8acc 100644 --- a/src/object/player.hpp +++ b/src/object/player.hpp @@ -32,6 +32,7 @@ #include "scripting/player.hpp" #include "player_status.hpp" #include "display_effect.hpp" +#include "script_interface.hpp" #include "console.hpp" class BadGuy; @@ -78,7 +79,7 @@ extern TuxBodyParts* big_tux; extern TuxBodyParts* fire_tux; extern TuxBodyParts* ice_tux; -class Player : public MovingObject, public Scripting::Player, public ConsoleCommandReceiver +class Player : public MovingObject, public Scripting::Player, public ScriptInterface { public: enum HurtMode { KILL, SHRINK }; @@ -121,6 +122,9 @@ public: Player(PlayerStatus* player_status); virtual ~Player(); + virtual void expose(HSQUIRRELVM vm, int table_idx); + virtual void unexpose(HSQUIRRELVM vm, int table_idx); + void set_controller(Controller* controller); virtual void update(float elapsed_time); @@ -165,8 +169,6 @@ public: bool on_ground(); - bool consoleCommand(std::string command, std::vector arguments); /**< callback from Console; return false if command was unknown, true otherwise */ - private: void handle_input(); bool deactivated; diff --git a/src/object/powerup.cpp b/src/object/powerup.cpp index 5f28bd7ea..f73182231 100644 --- a/src/object/powerup.cpp +++ b/src/object/powerup.cpp @@ -27,7 +27,6 @@ #include "audio/sound_manager.hpp" #include "object_factory.hpp" #include "sector.hpp" -#include "scripting/script_interpreter.hpp" #include "msg.hpp" PowerUp::PowerUp(const lisp::Lisp& lisp) @@ -70,8 +69,8 @@ PowerUp::collision(GameObject& other, const CollisionHit& hit) remove_me(); if (script != "") { - ScriptInterpreter::add_script_object(Sector::current(), "powerup-script", - script); + std::istringstream stream(script); + Sector::current()->run_script(stream, "powerup-script"); return ABORT_MOVE; } diff --git a/src/object/scripted_object.cpp b/src/object/scripted_object.cpp index 53ef31715..928b3504d 100644 --- a/src/object/scripted_object.cpp +++ b/src/object/scripted_object.cpp @@ -6,6 +6,7 @@ #include "scripted_object.hpp" #include "video/drawing_context.hpp" #include "sprite/sprite_manager.hpp" +#include "scripting/wrapper_util.hpp" #include "resources.hpp" #include "object_factory.hpp" #include "math/vector.hpp" @@ -46,6 +47,19 @@ ScriptedObject::~ScriptedObject() } void +ScriptedObject::expose(HSQUIRRELVM vm, int table_idx) +{ + Scripting::ScriptedObject* interface = static_cast (this); + expose_object(vm, table_idx, interface, name, false); +} + +void +ScriptedObject::unexpose(HSQUIRRELVM vm, int table_idx) +{ + Scripting::unexpose_object(vm, table_idx, name); +} + +void ScriptedObject::move(float x, float y) { bbox.move(Vector(x, y)); diff --git a/src/object/scripted_object.hpp b/src/object/scripted_object.hpp index 699a0540b..ac810b2fd 100644 --- a/src/object/scripted_object.hpp +++ b/src/object/scripted_object.hpp @@ -6,14 +6,19 @@ #include "sprite/sprite.hpp" #include "lisp/lisp.hpp" #include "moving_object.hpp" +#include "script_interface.hpp" #include "scripting/scripted_object.hpp" -class ScriptedObject : public MovingObject, public Scripting::ScriptedObject +class ScriptedObject : public MovingObject, public Scripting::ScriptedObject, + public ScriptInterface { public: ScriptedObject(const lisp::Lisp& lisp); virtual ~ScriptedObject(); + virtual void expose(HSQUIRRELVM vm, int table_idx); + virtual void unexpose(HSQUIRRELVM vm, int table_idx); + void update(float elapsed_time); void draw(DrawingContext& context); HitResponse collision(GameObject& other, const CollisionHit& hit); diff --git a/src/object/text_object.cpp b/src/object/text_object.cpp index 8b992cd0c..8608b9f05 100644 --- a/src/object/text_object.cpp +++ b/src/object/text_object.cpp @@ -5,6 +5,7 @@ #include #include "resources.hpp" #include "video/drawing_context.hpp" +#include "scripting/wrapper_util.hpp" #include "msg.hpp" TextObject::TextObject() @@ -19,6 +20,19 @@ TextObject::~TextObject() } void +TextObject::expose(HSQUIRRELVM vm, int table_idx) +{ + Scripting::Text* interface = static_cast (this); + Scripting::expose_object(vm, table_idx, interface, "Text", false); +} + +void +TextObject::unexpose(HSQUIRRELVM vm, int table_idx) +{ + Scripting::unexpose_object(vm, table_idx, "Text"); +} + +void TextObject::set_font(const std::string& name) { if(name == "gold") { diff --git a/src/object/text_object.hpp b/src/object/text_object.hpp index 194dc94ba..2f39b1d5e 100644 --- a/src/object/text_object.hpp +++ b/src/object/text_object.hpp @@ -3,16 +3,21 @@ #include "game_object.hpp" #include "scripting/text.hpp" +#include "script_interface.hpp" class Font; /** A text object intended for scripts that want to tell a story */ -class TextObject : public GameObject, public Scripting::Text +class TextObject : public GameObject, public Scripting::Text, + public ScriptInterface { public: TextObject(); virtual ~TextObject(); + void expose(HSQUIRRELVM vm, int table_idx); + void unexpose(HSQUIRRELVM vm, int table_idx); + void set_text(const std::string& text); void set_font(const std::string& name); void fade_in(float fadetime); diff --git a/src/resources.cpp b/src/resources.cpp index 3570e002e..b5615782f 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -112,29 +112,41 @@ void load_shared() /* Free shared data: */ void unload_shared() { + printf("0\n"); + /* Free global images: */ delete gold_text; + printf("first\n"); delete white_text; delete blue_text; delete gray_text; delete white_small_text; + printf("last\n"); delete white_big_text; + + printf("1\n"); delete small_tux; delete big_tux; delete fire_tux; delete ice_tux; + printf("2\n"); + for (int i = 0; i < GROWING_FRAMES; i++) { delete growingtux_left[i]; delete growingtux_right[i]; } + printf("3\n"); + delete sprite_manager; sprite_manager = 0; delete tile_manager; tile_manager = 0; + printf("4\n"); + /* Free mouse-cursor */ delete mouse_cursor; } diff --git a/src/screen.hpp b/src/screen.hpp index fd3b8908f..6c6ea0219 100644 --- a/src/screen.hpp +++ b/src/screen.hpp @@ -27,11 +27,26 @@ public: virtual ~Screen() {} + /** + * gets called before this screen gets activated (which is at least once + * before the first draw or update call + */ virtual void setup() {} + /** gets called when the current screen is temporarily suspended */ + virtual void leave() + {} + /** + * gets called once per frame. The screen should draw itself in this function. + * State changes should not be done in this function, but rather in update + */ virtual void draw(DrawingContext& context) = 0; + /** + * gets called for once (per logical) frame. Screens should do their state + * updates and logic here + */ virtual void update(float elapsed_time) = 0; }; diff --git a/src/script_interface.hpp b/src/script_interface.hpp new file mode 100644 index 000000000..bc21c38e3 --- /dev/null +++ b/src/script_interface.hpp @@ -0,0 +1,40 @@ +// $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $ +// +// SuperTux +// Copyright (C) 2005 Matthias Braun +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +#ifndef __SCRIPT_INTERFACE_HPP__ +#define __SCRIPT_INTERFACE_HPP__ + +#include + +/** + * Objects that want to expose themself to the scripting environment + * should implement this interface + */ +class ScriptInterface +{ +public: + virtual ~ScriptInterface() + {} + + virtual void expose(HSQUIRRELVM vm, int table_idx) = 0; + virtual void unexpose(HSQUIRRELVM vm, int table_idx) = 0; +}; + +#endif + diff --git a/src/script_manager.cpp b/src/script_manager.cpp new file mode 100644 index 000000000..d0656a57d --- /dev/null +++ b/src/script_manager.cpp @@ -0,0 +1,197 @@ +// $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $ +// +// SuperTux +// Copyright (C) 2005 Matthias Braun +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +#include + +#include "script_manager.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "timer.hpp" +#include "console.hpp" +#include "scripting/wrapper.hpp" +#include "scripting/wrapper_util.hpp" +#include "scripting/squirrel_error.hpp" +#include "physfs/physfs_stream.hpp" + +using namespace Scripting; + +ScriptManager* script_manager = 0; + +static void printfunc(HSQUIRRELVM, const char* str, ...) +{ + char buf[4096]; + va_list arglist; + va_start(arglist, str); + vsprintf(buf, str, arglist); + Console::output << (const char*) buf << std::flush; + va_end(arglist); +} + +ScriptManager::ScriptManager() +{ + v = sq_open(1024); + if(v == 0) + throw std::runtime_error("Couldn't initialize squirrel vm"); + + // register default error handlers + sqstd_seterrorhandlers(v); + // register squirrel libs + sq_pushroottable(v); + if(sqstd_register_bloblib(v) < 0) + throw SquirrelError(v, "Couldn't register blob lib"); + if(sqstd_register_iolib(v) < 0) + throw SquirrelError(v, "Couldn't register io lib"); + if(sqstd_register_systemlib(v) < 0) + throw SquirrelError(v, "Couldn't register system lib"); + if(sqstd_register_mathlib(v) < 0) + throw SquirrelError(v, "Couldn't register math lib"); + if(sqstd_register_stringlib(v) < 0) + throw SquirrelError(v, "Couldn't register string lib"); + + // register print function + sq_setprintfunc(v, printfunc); + + // register supertux API + register_supertux_wrapper(v); +} + +ScriptManager::~ScriptManager() +{ + for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i) + sq_release(v, &(i->vm_obj)); + + sq_close(v); +} + +HSQUIRRELVM +ScriptManager::create_thread() +{ + HSQUIRRELVM vm = sq_newthread(v, 1024); + if(vm == NULL) + throw SquirrelError(v, "Couldn't create new VM"); + + // retrieve reference to thread from stack and increase refcounter + HSQOBJECT vm_obj; + sq_resetobject(&vm_obj); + if(SQ_FAILED(sq_getstackobj(v, -1, &vm_obj))) { + throw SquirrelError(v, "Couldn't get coroutine vm from stack"); + } + sq_addref(v, &vm_obj); + sq_pop(v, 1); + + squirrel_vms.push_back(SquirrelVM(vm, vm_obj)); + + return vm; +} + +void +ScriptManager::update() +{ + for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ) { + SquirrelVM& squirrel_vm = *i; + int vm_state = sq_getvmstate(squirrel_vm.vm); + + if(vm_state == SQ_VMSTATE_SUSPENDED && squirrel_vm.wakeup_time > 0 && game_time >= squirrel_vm.wakeup_time) { + squirrel_vm.waiting_for_events = WakeupData(NO_EVENT); + try { + if(SQ_FAILED(sq_wakeupvm(squirrel_vm.vm, false, false))) { + throw SquirrelError(squirrel_vm.vm, "Couldn't resume script"); + } + } catch(std::exception& e) { + std::cerr << "Problem executing script: " << e.what() << "\n"; + sq_release(v, &squirrel_vm.vm_obj); + i = squirrel_vms.erase(i); + continue; + } + } + + if (vm_state != SQ_VMSTATE_SUSPENDED) { + sq_release(v, &(squirrel_vm.vm_obj)); + i = squirrel_vms.erase(i); + } else { + ++i; + } + } +} + +void +ScriptManager::set_wakeup_event(HSQUIRRELVM vm, WakeupData event, float timeout) +{ + assert(event.type >= 0 && event.type < WAKEUP_EVENT_COUNT); + // find the VM in the list and update it + for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i) { + SquirrelVM& squirrel_vm = *i; + if(squirrel_vm.vm == vm) + { + squirrel_vm.waiting_for_events = event; + + if(timeout < 0) { + squirrel_vm.wakeup_time = -1; + } else { + squirrel_vm.wakeup_time = game_time + timeout; + } + return; + } + } +} + +void +ScriptManager::fire_wakeup_event(WakeupData event) +{ + assert(event.type >= 0 && event.type < WAKEUP_EVENT_COUNT); + for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i) + { + SquirrelVM& vm = *i; + if(vm.waiting_for_events.type == event.type && vm.waiting_for_events.type != NO_EVENT) + { + vm.wakeup_time = game_time; + break; + } + } +} + +void +ScriptManager::set_wakeup_event(HSQUIRRELVM vm, WakeupEvent event, float timeout) +{ + set_wakeup_event(vm, WakeupData(event), timeout); +} + +void +ScriptManager::fire_wakeup_event(WakeupEvent event) +{ + fire_wakeup_event(WakeupData(event)); +} + +ScriptManager::SquirrelVM::SquirrelVM(HSQUIRRELVM arg_vm, HSQOBJECT arg_obj) + : vm(arg_vm), vm_obj(arg_obj) +{ + waiting_for_events = WakeupData(NO_EVENT); + wakeup_time = 0; +} + diff --git a/src/script_manager.hpp b/src/script_manager.hpp new file mode 100644 index 000000000..bbcbbf1b7 --- /dev/null +++ b/src/script_manager.hpp @@ -0,0 +1,100 @@ +// $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $ +// +// SuperTux +// Copyright (C) 2005 Matthias Braun +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +#ifndef __SCRIPT_MANAGER_H__ +#define __SCRIPT_MANAGER_H__ + +#include +#include +#include +#include +#include "timer.hpp" + +class GameObject; + +/** + * This class is responsible for managing all running squirrel threads + * (they are cooperative threads or coroutines) + * It keeps a list of suspended scripts and receives wakeup events for them + */ +class ScriptManager +{ +public: + ScriptManager(); + ~ScriptManager(); + + void update(); + + /** + * Creates a new thread and registers it with the script manager + * (so it can suspend and register for wakeup events) + */ + HSQUIRRELVM create_thread(); + + HSQUIRRELVM get_global_vm() const + { + return v; + } + + enum WakeupEvent { + NO_EVENT, + TIME, + SCREEN_SWITCHED, + WAKEUP_EVENT_COUNT + }; + + struct WakeupData { + explicit WakeupData() : type(NO_EVENT) {} + explicit WakeupData(WakeupEvent type_) : type(type_) {} + + WakeupEvent type; + + union { + // GAMEOBJECT_DONE + GameObject* game_object; + }; + }; + + void set_wakeup_event(HSQUIRRELVM vm, WakeupEvent event, float timeout = -1); + void set_wakeup_event(HSQUIRRELVM vm, WakeupData event, float timeout = -1); + void fire_wakeup_event(WakeupEvent event); + void fire_wakeup_event(WakeupData event); + +private: + class SquirrelVM + { + public: + SquirrelVM(HSQUIRRELVM arg_vm, HSQOBJECT arg_obj); + + HSQUIRRELVM vm; + HSQOBJECT vm_obj; + float wakeup_time; + WakeupData waiting_for_events; + }; + + typedef std::list SquirrelVMs; + SquirrelVMs squirrel_vms; + + HSQUIRRELVM v; +}; + +extern ScriptManager* script_manager; + +#endif + diff --git a/src/scripting/camera.cpp b/src/scripting/camera.cpp index d96b5a468..93b910437 100644 --- a/src/scripting/camera.cpp +++ b/src/scripting/camera.cpp @@ -6,7 +6,7 @@ #include "scripting/camera.hpp" #include "math/vector.hpp" -#define NOIMPL printf("%s not implemented.\n", __PRETTY_FUNCTION__); +#define NOIMPL msg_fatal << __PRETTY_FUNCTION__ << " not implemented." namespace Scripting { @@ -30,9 +30,15 @@ namespace Scripting } void - Camera::set_mode(const std::string& ) + Camera::set_mode(const std::string& mode) { - NOIMPL; + if(mode == "normal") { + camera->mode = ::Camera::NORMAL; + } else if(mode == "manual") { + camera->mode = ::Camera::MANUAL; + } else { + msg_fatal << "Camera mode '" << mode << "' unknown."; + } } void diff --git a/src/scripting/functions.cpp b/src/scripting/functions.cpp index 5c1d6ff12..21712a647 100644 --- a/src/scripting/functions.cpp +++ b/src/scripting/functions.cpp @@ -1,22 +1,61 @@ +// $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $ +// +// SuperTux +// Copyright (C) 2005 Matthias Braun +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +#include + +#include #include #include #include #include #include "textscroller.hpp" #include "functions.hpp" -#include "script_interpreter.hpp" +#include "game_session.hpp" #include "tinygettext/tinygettext.hpp" +#include "physfs/physfs_stream.hpp" +#include "script_manager.hpp" #include "resources.hpp" #include "gettext.hpp" #include "msg.hpp" #include "mainloop.hpp" +#include "worldmap.hpp" + +#include "squirrel_error.hpp" +#include "wrapper_util.hpp" namespace Scripting { -void wait(float seconds) +int display(HSQUIRRELVM vm) +{ + Console::output << squirrel2string(vm, -1) << std::endl; + return 0; +} + +void wait(HSQUIRRELVM vm, float seconds) +{ + script_manager->set_wakeup_event(vm, ScriptManager::TIME, seconds); +} + +void wait_for_screenswitch(HSQUIRRELVM vm) { - ScriptInterpreter::current()->set_wakeup_time(seconds); + script_manager->set_wakeup_event(vm, ScriptManager::SCREEN_SWITCHED); } std::string translate(const std::string& text) @@ -26,25 +65,48 @@ std::string translate(const std::string& text) void display_text_file(const std::string& filename) { - std::string file - = ScriptInterpreter::current()->get_working_directory() + filename; - main_loop->push_screen(new TextScroller(file)); + main_loop->push_screen(new TextScroller(filename)); } -void import(HSQUIRRELVM v, const std::string& filename) +void load_worldmap(const std::string& filename) { - std::string file - = ScriptInterpreter::current()->get_working_directory() + filename; - if(sqstd_loadfile(v, file.c_str(), true) < 0) { - msg_warning << "couldn't load script '" << filename << "' (" << file << ")" << std::endl; - return; - } + using namespace WorldMapNS; + + std::auto_ptr worldmap(new WorldMap()); + worldmap->loadmap(filename); + main_loop->push_screen(worldmap.release()); +} + +void load_level(const std::string& filename) +{ + main_loop->push_screen(new GameSession(filename, ST_GL_PLAY)); +} + +static SQInteger squirrel_read_char(SQUserPointer file) +{ + std::istream* in = reinterpret_cast (file); + char c = in->get(); + if(in->eof()) + return 0; + + return c; +} - sq_push(v, -2); - if(sq_call(v, 1, false) < 0) { - msg_warning << "Couldn't execute script '" << filename << "' (" << file << ")" << std::endl; - return; + +void import(HSQUIRRELVM vm, const std::string& filename) +{ + IFileStream in(filename); + + if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, + filename.c_str(), SQTrue))) + throw SquirrelError(vm, "Couldn't parse script"); + + sq_pushroottable(vm); + if(SQ_FAILED(sq_call(vm, 1, SQFalse))) { + sq_pop(vm, 1); + throw SquirrelError(vm, "Couldn't execute script"); } + sq_pop(vm, 1); } void add_key(int new_key) diff --git a/src/scripting/functions.hpp b/src/scripting/functions.hpp index 7321c79d5..ccf0e62cd 100644 --- a/src/scripting/functions.hpp +++ b/src/scripting/functions.hpp @@ -1,8 +1,29 @@ +// $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $ +// +// SuperTux +// Copyright (C) 2005 Matthias Braun +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. #ifndef __FUNCTIONS_H__ #define __FUNCTIONS_H__ #ifndef SCRIPTING_API #define __suspend +#define __custom +#include #include "player_status.hpp" #endif @@ -16,25 +37,50 @@ static const int KEY_BRONZE = 0x004; static const int KEY_SILVER = 0x008; static const int KEY_GOLD = 0x010; -/** displays a text file and scrolls it over the screen */ +/** + * Display the value of the argument. This is usefull for inspecting tables. + */ +int display(HSQUIRRELVM vm) __custom; + +/** + * Display a text file and scrolls it over the screen (on next screenswitch) + */ void display_text_file(const std::string& filename); /** - * Suspends the script execution for the specified number of seconds + * Load and display a worldmap (on next screenswitch) */ -void wait(float seconds) __suspend; +void load_worldmap(const std::string& filename); -/** translates a give text into the users language (by looking it up in the .po +/** + * Load and display a level (on next screenswitch) + */ +void load_level(const std::string& filename); + +/** + * Suspend the script execution for the specified number of seconds + */ +void wait(HSQUIRRELVM vm, float seconds) __suspend; + +/** + * Suspend the script execution until the current screen has been changed + */ +void wait_for_screenswitch(HSQUIRRELVM vm) __suspend; + +/** + * Translate a text into the users language (by looking it up in the .po * files) */ std::string translate(const std::string& text); -/** load a script file and executes it - * This is typically used to import functions from external files. +/** + * Load a script file and executes it. This is typically used to import + * functions from external files. */ void import(HSQUIRRELVM v, const std::string& filename); -/** add a key to the inventory +/** + * Add a key to the inventory */ void add_key(int new_key); diff --git a/src/scripting/script_interpreter.cpp b/src/scripting/script_interpreter.cpp deleted file mode 100644 index 32265596d..000000000 --- a/src/scripting/script_interpreter.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include - -#include "script_interpreter.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "msg.hpp" -#include "wrapper.hpp" -#include "wrapper_util.hpp" -#include "sector.hpp" -#include "file_system.hpp" -#include "game_session.hpp" -#include "resources.hpp" -#include "physfs/physfs_stream.hpp" -#include "object/text_object.hpp" -#include "object/scripted_object.hpp" -#include "object/display_effect.hpp" -#include "object/player.hpp" -#include "scripting/sound.hpp" -#include "scripting/scripted_object.hpp" -#include "scripting/display_effect.hpp" -#include "scripting/squirrel_error.hpp" - -static void printfunc(HSQUIRRELVM, const char* str, ...) -{ - va_list arglist; - va_start(arglist, str); - vprintf(str, arglist); - va_end(arglist); -} - -ScriptInterpreter* ScriptInterpreter::_current = 0; - -ScriptInterpreter::ScriptInterpreter(const std::string& new_working_directory) - : working_directory(new_working_directory), sound(0), level(0), camera(0) -{ - v = sq_open(1024); - if(v == 0) - throw std::runtime_error("Couldn't initialize squirrel vm"); - - // register default error handlers - sqstd_seterrorhandlers(v); - // register squirrel libs - sq_pushroottable(v); - if(sqstd_register_bloblib(v) < 0) - throw Scripting::SquirrelError(v, "Couldn't register blob lib"); - if(sqstd_register_iolib(v) < 0) - throw Scripting::SquirrelError(v, "Couldn't register io lib"); - if(sqstd_register_systemlib(v) < 0) - throw Scripting::SquirrelError(v, "Couldn't register system lib"); - if(sqstd_register_mathlib(v) < 0) - throw Scripting::SquirrelError(v, "Couldn't register math lib"); - if(sqstd_register_stringlib(v) < 0) - throw Scripting::SquirrelError(v, "Couldn't register string lib"); - - // register print function - sq_setprintfunc(v, printfunc); - - // register supertux API - Scripting::register_supertux_wrapper(v); - - // expose some "global" objects - sound = new Scripting::Sound(); - expose_object(sound, "Sound"); - - level = new Scripting::Level(); - expose_object(level, "Level"); -} - -void -ScriptInterpreter::register_sector(Sector* sector) -{ - // expose ScriptedObjects to the script - for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); - i != sector->gameobjects.end(); ++i) { - GameObject* object = *i; - Scripting::ScriptedObject* scripted_object - = dynamic_cast (object); - if(!scripted_object) - continue; - - expose_object(scripted_object, scripted_object->get_name()); - } - - expose_object(static_cast (sector->player), "Tux"); - TextObject* text_object = new TextObject(); - sector->add_object(text_object); - Scripting::Text* text = static_cast (text_object); - expose_object(text, "Text"); - - DisplayEffect* display_effect = new DisplayEffect(); - sector->add_object(display_effect); - Scripting::DisplayEffect* display_effect_api - = static_cast (display_effect); - expose_object(display_effect_api, "DisplayEffect"); - - Scripting::Camera* camera = new Scripting::Camera(sector->camera); - expose_object(camera, "Camera"); -} - -ScriptInterpreter::~ScriptInterpreter() -{ - sq_close(v); - delete sound; - delete level; - delete camera; -} - -static SQInteger squirrel_read_char(SQUserPointer file) -{ - std::istream* in = reinterpret_cast (file); - char c = in->get(); - if(in->eof()) - return 0; - return c; -} - -void -ScriptInterpreter::run_script(std::istream& in, const std::string& sourcename, - bool remove_when_terminated) -{ - if(sq_compile(v, squirrel_read_char, &in, sourcename.c_str(), true) < 0) - throw Scripting::SquirrelError(v, "Couldn't parse script"); - - _current = this; - sq_push(v, -2); - if(sq_call(v, 1, false) < 0) - throw Scripting::SquirrelError(v, "Couldn't start script"); - _current = 0; - if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) { - if(remove_when_terminated) { - remove_me(); - } - // remove closure from stack - sq_pop(v, 1); - } -} - -void -ScriptInterpreter::set_wakeup_time(float seconds) -{ - wakeup_timer.start(seconds); -} - -void -ScriptInterpreter::update(float ) -{ - if(!wakeup_timer.check()) - return; - - _current = this; - if(sq_wakeupvm(v, false, false) < 0) - throw Scripting::SquirrelError(v, "Couldn't resume script"); - _current = 0; - if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) { - printf("script ended...\n"); - remove_me(); - } -} - -void -ScriptInterpreter::draw(DrawingContext& ) -{ -} - -void -ScriptInterpreter::add_script_object(Sector* sector, const std::string& name, - const std::string& script) -{ - try { - std::string workdir = GameSession::current()->get_working_directory(); - std::auto_ptr interpreter( - new ScriptInterpreter(workdir)); - interpreter->register_sector(sector); - - // load global default.nut file if it exists - //TODO: Load all .nut files from that directory - try { - std::string filename = "script/default.nut"; - IFileStream in(filename); - interpreter->run_script(in, filename, false); - } catch(std::exception& e) { - // nothing - } - - // load world-specific default.nut file if it exists - try { - std::string filename = workdir + "/default.nut"; - IFileStream in(filename); - interpreter->run_script(in, filename, false); - } catch(std::exception& e) { - // nothing - } - - std::istringstream in(script); - interpreter->run_script(in, name); - sector->add_object(interpreter.release()); - } catch(std::exception& e) { - msg_warning << "Couldn't start '" << name << "' script: " << e.what() << std::endl; - } -} - diff --git a/src/scripting/script_interpreter.hpp b/src/scripting/script_interpreter.hpp deleted file mode 100644 index de86f876d..000000000 --- a/src/scripting/script_interpreter.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef __SCRIPT_INTERPRETER_H__ -#define __SCRIPT_INTERPRETER_H__ - -#include -#include -#include -#include -#include "timer.hpp" -#include "game_object.hpp" -#include "scripting/wrapper.hpp" -#include "scripting/wrapper_util.hpp" -#include "scripting/sound.hpp" -#include "scripting/level.hpp" -#include "scripting/squirrel_error.hpp" -#include "scripting/camera.hpp" - -class Sector; - -class ScriptInterpreter : public GameObject -{ -public: - ScriptInterpreter(const std::string& working_dir); - ~ScriptInterpreter(); - - void register_sector(Sector* sector); - - void draw(DrawingContext& ); - void update(float ); - - void run_script(std::istream& in, const std::string& sourcename = "", - bool remove_when_terminated = true); - - template - void expose_object(T* object, const std::string& name, bool free = false) - { - sq_pushroottable(v); - sq_pushstring(v, name.c_str(), -1); - - sq_pushroottable(v); - Scripting::create_squirrel_instance(v, object, free); - sq_remove(v, -2); - - // register instance in root table - if(sq_createslot(v, -3) < 0) { - std::ostringstream msg; - msg << "Couldn't register object '" << name << "' in squirrel root table"; - throw Scripting::SquirrelError(v, msg.str()); - } - - sq_pop(v, 1); - } - - void set_wakeup_time(float seconds); - - /** helper function that parses a script, starts it and adds it to the sector - * specified - */ - static void add_script_object(Sector* sector, const std::string& scriptname, - const std::string& script); - - static ScriptInterpreter* current() - { - return _current; - } - - const std::string& get_working_directory() const - { - return working_directory; - } - -private: - HSQUIRRELVM v; - static ScriptInterpreter* _current; - Timer wakeup_timer; - - /// this directory is used as base for all filenames used in scripts - std::string working_directory; - Scripting::Sound* sound; - Scripting::Level* level; - Scripting::Camera* camera; -}; - -#endif - diff --git a/src/scripting/sound.hpp b/src/scripting/sound.hpp index 51aa7b951..ac97f2557 100644 --- a/src/scripting/sound.hpp +++ b/src/scripting/sound.hpp @@ -16,9 +16,10 @@ public: */ void play(const std::string& soundfile); + ~Sound(); + #ifndef SCRIPTING_API Sound(); - ~Sound(); #endif }; diff --git a/src/scripting/wrapper.cpp b/src/scripting/wrapper.cpp index 944c7b617..b31ccceff 100644 --- a/src/scripting/wrapper.cpp +++ b/src/scripting/wrapper.cpp @@ -25,75 +25,168 @@ static int DisplayEffect_release_hook(SQUserPointer ptr, int ) return 0; } -static int DisplayEffect_fade_out_wrapper(HSQUIRRELVM v) +static int DisplayEffect_fade_out_wrapper(HSQUIRRELVM vm) { Scripting::DisplayEffect* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'fade_out' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } - _this->fade_out(arg0); + try { + _this->fade_out(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'fade_out'")); + return SQ_ERROR; + } - return 0; } -static int DisplayEffect_fade_in_wrapper(HSQUIRRELVM v) +static int DisplayEffect_fade_in_wrapper(HSQUIRRELVM vm) { Scripting::DisplayEffect* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'fade_in' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } - _this->fade_in(arg0); + try { + _this->fade_in(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'fade_in'")); + return SQ_ERROR; + } - return 0; } -static int DisplayEffect_set_black_wrapper(HSQUIRRELVM v) +static int DisplayEffect_set_black_wrapper(HSQUIRRELVM vm) { Scripting::DisplayEffect* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_black' called without instance")); + return SQ_ERROR; + } SQBool arg0; - sq_getbool(v, 2, &arg0); + if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a bool")); + return SQ_ERROR; + } - _this->set_black(arg0); + try { + _this->set_black(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_black'")); + return SQ_ERROR; + } - return 0; } -static int DisplayEffect_is_black_wrapper(HSQUIRRELVM v) +static int DisplayEffect_is_black_wrapper(HSQUIRRELVM vm) { Scripting::DisplayEffect* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'is_black' called without instance")); + return SQ_ERROR; + } + + try { + bool return_value = _this->is_black(); - bool return_value = _this->is_black(); + sq_pushbool(vm, return_value); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'is_black'")); + return SQ_ERROR; + } - sq_pushbool(v, return_value); - return 1; } -static int DisplayEffect_sixteen_to_nine_wrapper(HSQUIRRELVM v) +static int DisplayEffect_sixteen_to_nine_wrapper(HSQUIRRELVM vm) { Scripting::DisplayEffect* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'sixteen_to_nine' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } - _this->sixteen_to_nine(arg0); + try { + _this->sixteen_to_nine(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'sixteen_to_nine'")); + return SQ_ERROR; + } - return 0; } -static int DisplayEffect_four_to_three_wrapper(HSQUIRRELVM v) +static int DisplayEffect_four_to_three_wrapper(HSQUIRRELVM vm) { Scripting::DisplayEffect* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'four_to_three' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } - _this->four_to_three(arg0); + try { + _this->four_to_three(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'four_to_three'")); + return SQ_ERROR; + } - return 0; } static int Camera_release_hook(SQUserPointer ptr, int ) @@ -103,62 +196,141 @@ static int Camera_release_hook(SQUserPointer ptr, int ) return 0; } -static int Camera_shake_wrapper(HSQUIRRELVM v) +static int Camera_shake_wrapper(HSQUIRRELVM vm) { Scripting::Camera* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'shake' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } float arg1; - sq_getfloat(v, 3, &arg1); + if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) { + sq_throwerror(vm, _SC("Argument 2 not a float")); + return SQ_ERROR; + } float arg2; - sq_getfloat(v, 4, &arg2); + if(SQ_FAILED(sq_getfloat(vm, 4, &arg2))) { + sq_throwerror(vm, _SC("Argument 3 not a float")); + return SQ_ERROR; + } - _this->shake(arg0, arg1, arg2); + try { + _this->shake(arg0, arg1, arg2); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'shake'")); + return SQ_ERROR; + } - return 0; } -static int Camera_set_pos_wrapper(HSQUIRRELVM v) +static int Camera_set_pos_wrapper(HSQUIRRELVM vm) { Scripting::Camera* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_pos' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } float arg1; - sq_getfloat(v, 3, &arg1); + if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) { + sq_throwerror(vm, _SC("Argument 2 not a float")); + return SQ_ERROR; + } - _this->set_pos(arg0, arg1); + try { + _this->set_pos(arg0, arg1); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_pos'")); + return SQ_ERROR; + } - return 0; } -static int Camera_set_mode_wrapper(HSQUIRRELVM v) +static int Camera_set_mode_wrapper(HSQUIRRELVM vm) { Scripting::Camera* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_mode' called without instance")); + return SQ_ERROR; + } const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } - _this->set_mode(arg0); + try { + _this->set_mode(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_mode'")); + return SQ_ERROR; + } - return 0; } -static int Camera_scroll_to_wrapper(HSQUIRRELVM v) +static int Camera_scroll_to_wrapper(HSQUIRRELVM vm) { Scripting::Camera* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'scroll_to' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } float arg1; - sq_getfloat(v, 3, &arg1); + if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) { + sq_throwerror(vm, _SC("Argument 2 not a float")); + return SQ_ERROR; + } float arg2; - sq_getfloat(v, 4, &arg2); + if(SQ_FAILED(sq_getfloat(vm, 4, &arg2))) { + sq_throwerror(vm, _SC("Argument 3 not a float")); + return SQ_ERROR; + } - _this->scroll_to(arg0, arg1, arg2); + try { + _this->scroll_to(arg0, arg1, arg2); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'scroll_to'")); + return SQ_ERROR; + } - return 0; } static int Level_release_hook(SQUserPointer ptr, int ) @@ -168,40 +340,88 @@ static int Level_release_hook(SQUserPointer ptr, int ) return 0; } -static int Level_finish_wrapper(HSQUIRRELVM v) +static int Level_finish_wrapper(HSQUIRRELVM vm) { Scripting::Level* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'finish' called without instance")); + return SQ_ERROR; + } SQBool arg0; - sq_getbool(v, 2, &arg0); + if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a bool")); + return SQ_ERROR; + } - _this->finish(arg0); + try { + _this->finish(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'finish'")); + return SQ_ERROR; + } - return 0; } -static int Level_spawn_wrapper(HSQUIRRELVM v) +static int Level_spawn_wrapper(HSQUIRRELVM vm) { Scripting::Level* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'spawn' called without instance")); + return SQ_ERROR; + } const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } const char* arg1; - sq_getstring(v, 3, &arg1); + if(SQ_FAILED(sq_getstring(vm, 3, &arg1))) { + sq_throwerror(vm, _SC("Argument 2 not a string")); + return SQ_ERROR; + } - _this->spawn(arg0, arg1); + try { + _this->spawn(arg0, arg1); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'spawn'")); + return SQ_ERROR; + } - return 0; } -static int Level_flip_vertically_wrapper(HSQUIRRELVM v) +static int Level_flip_vertically_wrapper(HSQUIRRELVM vm) { Scripting::Level* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'flip_vertically' called without instance")); + return SQ_ERROR; + } - _this->flip_vertically(); + try { + _this->flip_vertically(); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'flip_vertically'")); + return SQ_ERROR; + } - return 0; } static int ScriptedObject_release_hook(SQUserPointer ptr, int ) @@ -211,147 +431,327 @@ static int ScriptedObject_release_hook(SQUserPointer ptr, int ) return 0; } -static int ScriptedObject_set_action_wrapper(HSQUIRRELVM v) +static int ScriptedObject_set_action_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_action' called without instance")); + return SQ_ERROR; + } const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } - _this->set_action(arg0); + try { + _this->set_action(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_action'")); + return SQ_ERROR; + } - return 0; } -static int ScriptedObject_get_action_wrapper(HSQUIRRELVM v) +static int ScriptedObject_get_action_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_action' called without instance")); + return SQ_ERROR; + } - std::string return_value = _this->get_action(); + try { + std::string return_value = _this->get_action(); + + sq_pushstring(vm, return_value.c_str(), return_value.size()); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_action'")); + return SQ_ERROR; + } - sq_pushstring(v, return_value.c_str(), return_value.size()); - return 1; } -static int ScriptedObject_move_wrapper(HSQUIRRELVM v) +static int ScriptedObject_move_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'move' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } float arg1; - sq_getfloat(v, 3, &arg1); + if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) { + sq_throwerror(vm, _SC("Argument 2 not a float")); + return SQ_ERROR; + } - _this->move(arg0, arg1); + try { + _this->move(arg0, arg1); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'move'")); + return SQ_ERROR; + } - return 0; } -static int ScriptedObject_set_pos_wrapper(HSQUIRRELVM v) +static int ScriptedObject_set_pos_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_pos' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } float arg1; - sq_getfloat(v, 3, &arg1); + if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) { + sq_throwerror(vm, _SC("Argument 2 not a float")); + return SQ_ERROR; + } - _this->set_pos(arg0, arg1); + try { + _this->set_pos(arg0, arg1); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_pos'")); + return SQ_ERROR; + } - return 0; } -static int ScriptedObject_get_pos_x_wrapper(HSQUIRRELVM v) +static int ScriptedObject_get_pos_x_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_pos_x' called without instance")); + return SQ_ERROR; + } + + try { + float return_value = _this->get_pos_x(); + + sq_pushfloat(vm, return_value); + return 1; - float return_value = _this->get_pos_x(); + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_pos_x'")); + return SQ_ERROR; + } - sq_pushfloat(v, return_value); - return 1; } -static int ScriptedObject_get_pos_y_wrapper(HSQUIRRELVM v) +static int ScriptedObject_get_pos_y_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_pos_y' called without instance")); + return SQ_ERROR; + } + + try { + float return_value = _this->get_pos_y(); + + sq_pushfloat(vm, return_value); + return 1; - float return_value = _this->get_pos_y(); + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_pos_y'")); + return SQ_ERROR; + } - sq_pushfloat(v, return_value); - return 1; } -static int ScriptedObject_set_velocity_wrapper(HSQUIRRELVM v) +static int ScriptedObject_set_velocity_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_velocity' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } float arg1; - sq_getfloat(v, 3, &arg1); + if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) { + sq_throwerror(vm, _SC("Argument 2 not a float")); + return SQ_ERROR; + } - _this->set_velocity(arg0, arg1); + try { + _this->set_velocity(arg0, arg1); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_velocity'")); + return SQ_ERROR; + } - return 0; } -static int ScriptedObject_get_velocity_x_wrapper(HSQUIRRELVM v) +static int ScriptedObject_get_velocity_x_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_velocity_x' called without instance")); + return SQ_ERROR; + } + + try { + float return_value = _this->get_velocity_x(); + + sq_pushfloat(vm, return_value); + return 1; - float return_value = _this->get_velocity_x(); + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_velocity_x'")); + return SQ_ERROR; + } - sq_pushfloat(v, return_value); - return 1; } -static int ScriptedObject_get_velocity_y_wrapper(HSQUIRRELVM v) +static int ScriptedObject_get_velocity_y_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_velocity_y' called without instance")); + return SQ_ERROR; + } + + try { + float return_value = _this->get_velocity_y(); + + sq_pushfloat(vm, return_value); + return 1; - float return_value = _this->get_velocity_y(); + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_velocity_y'")); + return SQ_ERROR; + } - sq_pushfloat(v, return_value); - return 1; } -static int ScriptedObject_set_visible_wrapper(HSQUIRRELVM v) +static int ScriptedObject_set_visible_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_visible' called without instance")); + return SQ_ERROR; + } SQBool arg0; - sq_getbool(v, 2, &arg0); + if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a bool")); + return SQ_ERROR; + } - _this->set_visible(arg0); + try { + _this->set_visible(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_visible'")); + return SQ_ERROR; + } - return 0; } -static int ScriptedObject_is_visible_wrapper(HSQUIRRELVM v) +static int ScriptedObject_is_visible_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'is_visible' called without instance")); + return SQ_ERROR; + } - bool return_value = _this->is_visible(); + try { + bool return_value = _this->is_visible(); + + sq_pushbool(vm, return_value); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'is_visible'")); + return SQ_ERROR; + } - sq_pushbool(v, return_value); - return 1; } -static int ScriptedObject_get_name_wrapper(HSQUIRRELVM v) +static int ScriptedObject_get_name_wrapper(HSQUIRRELVM vm) { Scripting::ScriptedObject* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_name' called without instance")); + return SQ_ERROR; + } - std::string return_value = _this->get_name(); + try { + std::string return_value = _this->get_name(); + + sq_pushstring(vm, return_value.c_str(), return_value.size()); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_name'")); + return SQ_ERROR; + } - sq_pushstring(v, return_value.c_str(), return_value.size()); - return 1; } static int Sound_release_hook(SQUserPointer ptr, int ) @@ -361,28 +761,60 @@ static int Sound_release_hook(SQUserPointer ptr, int ) return 0; } -static int Sound_play_music_wrapper(HSQUIRRELVM v) +static int Sound_play_music_wrapper(HSQUIRRELVM vm) { Scripting::Sound* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'play_music' called without instance")); + return SQ_ERROR; + } const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } - _this->play_music(arg0); + try { + _this->play_music(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'play_music'")); + return SQ_ERROR; + } - return 0; } -static int Sound_play_wrapper(HSQUIRRELVM v) +static int Sound_play_wrapper(HSQUIRRELVM vm) { Scripting::Sound* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'play' called without instance")); + return SQ_ERROR; + } const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } - _this->play(arg0); + try { + _this->play(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'play'")); + return SQ_ERROR; + } - return 0; } static int Text_release_hook(SQUserPointer ptr, int ) @@ -392,76 +824,172 @@ static int Text_release_hook(SQUserPointer ptr, int ) return 0; } -static int Text_set_text_wrapper(HSQUIRRELVM v) +static int Text_set_text_wrapper(HSQUIRRELVM vm) { Scripting::Text* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_text' called without instance")); + return SQ_ERROR; + } const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } - _this->set_text(arg0); + try { + _this->set_text(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_text'")); + return SQ_ERROR; + } - return 0; } -static int Text_set_font_wrapper(HSQUIRRELVM v) +static int Text_set_font_wrapper(HSQUIRRELVM vm) { Scripting::Text* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_font' called without instance")); + return SQ_ERROR; + } const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } - _this->set_font(arg0); + try { + _this->set_font(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_font'")); + return SQ_ERROR; + } - return 0; } -static int Text_fade_in_wrapper(HSQUIRRELVM v) +static int Text_fade_in_wrapper(HSQUIRRELVM vm) { Scripting::Text* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'fade_in' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } - _this->fade_in(arg0); + try { + _this->fade_in(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'fade_in'")); + return SQ_ERROR; + } - return 0; } -static int Text_fade_out_wrapper(HSQUIRRELVM v) +static int Text_fade_out_wrapper(HSQUIRRELVM vm) { Scripting::Text* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'fade_out' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } - _this->fade_out(arg0); + try { + _this->fade_out(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'fade_out'")); + return SQ_ERROR; + } - return 0; } -static int Text_set_visible_wrapper(HSQUIRRELVM v) +static int Text_set_visible_wrapper(HSQUIRRELVM vm) { Scripting::Text* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_visible' called without instance")); + return SQ_ERROR; + } SQBool arg0; - sq_getbool(v, 2, &arg0); + if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a bool")); + return SQ_ERROR; + } - _this->set_visible(arg0); + try { + _this->set_visible(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_visible'")); + return SQ_ERROR; + } - return 0; } -static int Text_set_centered_wrapper(HSQUIRRELVM v) +static int Text_set_centered_wrapper(HSQUIRRELVM vm) { Scripting::Text* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_centered' called without instance")); + return SQ_ERROR; + } SQBool arg0; - sq_getbool(v, 2, &arg0); + if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a bool")); + return SQ_ERROR; + } - _this->set_centered(arg0); + try { + _this->set_centered(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_centered'")); + return SQ_ERROR; + } - return 0; } static int Player_release_hook(SQUserPointer ptr, int ) @@ -471,69 +999,153 @@ static int Player_release_hook(SQUserPointer ptr, int ) return 0; } -static int Player_make_invincible_wrapper(HSQUIRRELVM v) +static int Player_make_invincible_wrapper(HSQUIRRELVM vm) { Scripting::Player* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'make_invincible' called without instance")); + return SQ_ERROR; + } - _this->make_invincible(); + try { + _this->make_invincible(); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'make_invincible'")); + return SQ_ERROR; + } - return 0; } -static int Player_deactivate_wrapper(HSQUIRRELVM v) +static int Player_deactivate_wrapper(HSQUIRRELVM vm) { Scripting::Player* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'deactivate' called without instance")); + return SQ_ERROR; + } - _this->deactivate(); + try { + _this->deactivate(); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'deactivate'")); + return SQ_ERROR; + } - return 0; } -static int Player_activate_wrapper(HSQUIRRELVM v) +static int Player_activate_wrapper(HSQUIRRELVM vm) { Scripting::Player* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'activate' called without instance")); + return SQ_ERROR; + } - _this->activate(); + try { + _this->activate(); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'activate'")); + return SQ_ERROR; + } - return 0; } -static int Player_walk_wrapper(HSQUIRRELVM v) +static int Player_walk_wrapper(HSQUIRRELVM vm) { Scripting::Player* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'walk' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } - _this->walk(arg0); + try { + _this->walk(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'walk'")); + return SQ_ERROR; + } - return 0; } -static int Player_set_visible_wrapper(HSQUIRRELVM v) +static int Player_set_visible_wrapper(HSQUIRRELVM vm) { Scripting::Player* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_visible' called without instance")); + return SQ_ERROR; + } SQBool arg0; - sq_getbool(v, 2, &arg0); + if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a bool")); + return SQ_ERROR; + } - _this->set_visible(arg0); + try { + _this->set_visible(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_visible'")); + return SQ_ERROR; + } - return 0; } -static int Player_get_visible_wrapper(HSQUIRRELVM v) +static int Player_get_visible_wrapper(HSQUIRRELVM vm) { Scripting::Player* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_visible' called without instance")); + return SQ_ERROR; + } + + try { + bool return_value = _this->get_visible(); + + sq_pushbool(vm, return_value); + return 1; - bool return_value = _this->get_visible(); + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_visible'")); + return SQ_ERROR; + } - sq_pushbool(v, return_value); - return 1; } static int FloatingImage_release_hook(SQUserPointer ptr, int ) @@ -543,173 +1155,457 @@ static int FloatingImage_release_hook(SQUserPointer ptr, int ) return 0; } -static int FloatingImage_constructor_wrapper(HSQUIRRELVM v) +static int FloatingImage_constructor_wrapper(HSQUIRRELVM vm) { const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } - Scripting::FloatingImage* _this = new Scripting::FloatingImage(arg0); - sq_setinstanceup(v, 1, _this); - sq_setreleasehook(v, 1, FloatingImage_release_hook); + try { + Scripting::FloatingImage* _this = new Scripting::FloatingImage(arg0); + if(SQ_FAILED(sq_setinstanceup(vm, 1, _this))) { + sq_throwerror(vm, _SC("Couldn't setup instance of 'FloatingImage' class")); + return SQ_ERROR; + } + sq_setreleasehook(vm, 1, FloatingImage_release_hook); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'constructor'")); + return SQ_ERROR; + } - return 0; } -static int FloatingImage_set_layer_wrapper(HSQUIRRELVM v) +static int FloatingImage_set_layer_wrapper(HSQUIRRELVM vm) { Scripting::FloatingImage* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_layer' called without instance")); + return SQ_ERROR; + } int arg0; - sq_getinteger(v, 2, &arg0); + if(SQ_FAILED(sq_getinteger(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not an integer")); + return SQ_ERROR; + } - _this->set_layer(arg0); + try { + _this->set_layer(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_layer'")); + return SQ_ERROR; + } - return 0; } -static int FloatingImage_get_layer_wrapper(HSQUIRRELVM v) +static int FloatingImage_get_layer_wrapper(HSQUIRRELVM vm) { Scripting::FloatingImage* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_layer' called without instance")); + return SQ_ERROR; + } + + try { + int return_value = _this->get_layer(); - int return_value = _this->get_layer(); + sq_pushinteger(vm, return_value); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_layer'")); + return SQ_ERROR; + } - sq_pushinteger(v, return_value); - return 1; } -static int FloatingImage_set_pos_wrapper(HSQUIRRELVM v) +static int FloatingImage_set_pos_wrapper(HSQUIRRELVM vm) { Scripting::FloatingImage* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_pos' called without instance")); + return SQ_ERROR; + } float arg0; - sq_getfloat(v, 2, &arg0); + if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } float arg1; - sq_getfloat(v, 3, &arg1); + if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) { + sq_throwerror(vm, _SC("Argument 2 not a float")); + return SQ_ERROR; + } - _this->set_pos(arg0, arg1); + try { + _this->set_pos(arg0, arg1); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_pos'")); + return SQ_ERROR; + } - return 0; } -static int FloatingImage_get_pos_x_wrapper(HSQUIRRELVM v) +static int FloatingImage_get_pos_x_wrapper(HSQUIRRELVM vm) { Scripting::FloatingImage* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_pos_x' called without instance")); + return SQ_ERROR; + } + + try { + float return_value = _this->get_pos_x(); - float return_value = _this->get_pos_x(); + sq_pushfloat(vm, return_value); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_pos_x'")); + return SQ_ERROR; + } - sq_pushfloat(v, return_value); - return 1; } -static int FloatingImage_get_pos_y_wrapper(HSQUIRRELVM v) +static int FloatingImage_get_pos_y_wrapper(HSQUIRRELVM vm) { Scripting::FloatingImage* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_pos_y' called without instance")); + return SQ_ERROR; + } + + try { + float return_value = _this->get_pos_y(); - float return_value = _this->get_pos_y(); + sq_pushfloat(vm, return_value); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_pos_y'")); + return SQ_ERROR; + } - sq_pushfloat(v, return_value); - return 1; } -static int FloatingImage_set_anchor_point_wrapper(HSQUIRRELVM v) +static int FloatingImage_set_anchor_point_wrapper(HSQUIRRELVM vm) { Scripting::FloatingImage* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_anchor_point' called without instance")); + return SQ_ERROR; + } int arg0; - sq_getinteger(v, 2, &arg0); + if(SQ_FAILED(sq_getinteger(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not an integer")); + return SQ_ERROR; + } - _this->set_anchor_point(arg0); + try { + _this->set_anchor_point(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_anchor_point'")); + return SQ_ERROR; + } - return 0; } -static int FloatingImage_get_anchor_point_wrapper(HSQUIRRELVM v) +static int FloatingImage_get_anchor_point_wrapper(HSQUIRRELVM vm) { Scripting::FloatingImage* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_anchor_point' called without instance")); + return SQ_ERROR; + } + + try { + int return_value = _this->get_anchor_point(); - int return_value = _this->get_anchor_point(); + sq_pushinteger(vm, return_value); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_anchor_point'")); + return SQ_ERROR; + } - sq_pushinteger(v, return_value); - return 1; } -static int FloatingImage_set_visible_wrapper(HSQUIRRELVM v) +static int FloatingImage_set_visible_wrapper(HSQUIRRELVM vm) { Scripting::FloatingImage* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'set_visible' called without instance")); + return SQ_ERROR; + } SQBool arg0; - sq_getbool(v, 2, &arg0); + if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a bool")); + return SQ_ERROR; + } - _this->set_visible(arg0); + try { + _this->set_visible(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_visible'")); + return SQ_ERROR; + } - return 0; } -static int FloatingImage_get_visible_wrapper(HSQUIRRELVM v) +static int FloatingImage_get_visible_wrapper(HSQUIRRELVM vm) { Scripting::FloatingImage* _this; - sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0); + if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) { + sq_throwerror(vm, _SC("'get_visible' called without instance")); + return SQ_ERROR; + } + + try { + bool return_value = _this->get_visible(); - bool return_value = _this->get_visible(); + sq_pushbool(vm, return_value); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_visible'")); + return SQ_ERROR; + } - sq_pushbool(v, return_value); - return 1; } -static int display_text_file_wrapper(HSQUIRRELVM v) +static int display_wrapper(HSQUIRRELVM vm) +{ + return Scripting::display(vm); +} + +static int display_text_file_wrapper(HSQUIRRELVM vm) { const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } - Scripting::display_text_file(arg0); + try { + Scripting::display_text_file(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'display_text_file'")); + return SQ_ERROR; + } - return 0; } -static int wait_wrapper(HSQUIRRELVM v) +static int load_worldmap_wrapper(HSQUIRRELVM vm) { - float arg0; - sq_getfloat(v, 2, &arg0); + const char* arg0; + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } + + try { + Scripting::load_worldmap(arg0); + + return 0; - Scripting::wait(arg0); + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'load_worldmap'")); + return SQ_ERROR; + } - return sq_suspendvm(v); } -static int translate_wrapper(HSQUIRRELVM v) +static int load_level_wrapper(HSQUIRRELVM vm) { const char* arg0; - sq_getstring(v, 2, &arg0); + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } + + try { + Scripting::load_level(arg0); + + return 0; - std::string return_value = Scripting::translate(arg0); + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'load_level'")); + return SQ_ERROR; + } + +} + +static int wait_wrapper(HSQUIRRELVM vm) +{ + HSQUIRRELVM arg0 = vm; + float arg1; + if(SQ_FAILED(sq_getfloat(vm, 2, &arg1))) { + sq_throwerror(vm, _SC("Argument 1 not a float")); + return SQ_ERROR; + } + + try { + Scripting::wait(arg0, arg1); + + return sq_suspendvm(vm); + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'wait'")); + return SQ_ERROR; + } + +} + +static int wait_for_screenswitch_wrapper(HSQUIRRELVM vm) +{ + HSQUIRRELVM arg0 = vm; + + try { + Scripting::wait_for_screenswitch(arg0); + + return sq_suspendvm(vm); + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'wait_for_screenswitch'")); + return SQ_ERROR; + } - sq_pushstring(v, return_value.c_str(), return_value.size()); - return 1; } -static int import_wrapper(HSQUIRRELVM v) +static int translate_wrapper(HSQUIRRELVM vm) { - HSQUIRRELVM arg0 = v; + const char* arg0; + if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } + + try { + std::string return_value = Scripting::translate(arg0); + + sq_pushstring(vm, return_value.c_str(), return_value.size()); + return 1; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'translate'")); + return SQ_ERROR; + } + +} + +static int import_wrapper(HSQUIRRELVM vm) +{ + HSQUIRRELVM arg0 = vm; const char* arg1; - sq_getstring(v, 2, &arg1); + if(SQ_FAILED(sq_getstring(vm, 2, &arg1))) { + sq_throwerror(vm, _SC("Argument 1 not a string")); + return SQ_ERROR; + } - Scripting::import(arg0, arg1); + try { + Scripting::import(arg0, arg1); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'import'")); + return SQ_ERROR; + } - return 0; } -static int add_key_wrapper(HSQUIRRELVM v) +static int add_key_wrapper(HSQUIRRELVM vm) { int arg0; - sq_getinteger(v, 2, &arg0); + if(SQ_FAILED(sq_getinteger(vm, 2, &arg0))) { + sq_throwerror(vm, _SC("Argument 1 not an integer")); + return SQ_ERROR; + } - Scripting::add_key(arg0); + try { + Scripting::add_key(arg0); + + return 0; + + } catch(std::exception& e) { + sq_throwerror(vm, e.what()); + return SQ_ERROR; + } catch(...) { + sq_throwerror(vm, _SC("Unexpected exception while executing function 'add_key'")); + return SQ_ERROR; + } - return 0; } } // end of namespace Wrapper @@ -930,153 +1826,139 @@ void register_supertux_wrapper(HSQUIRRELVM v) sq_pushstring(v, "KEY_BRASS", -1); sq_pushinteger(v, 1); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'KEY_BRASS'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'KEY_BRASS'"); } sq_pushstring(v, "KEY_IRON", -1); sq_pushinteger(v, 2); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'KEY_IRON'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'KEY_IRON'"); } sq_pushstring(v, "KEY_BRONZE", -1); sq_pushinteger(v, 4); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'KEY_BRONZE'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'KEY_BRONZE'"); } sq_pushstring(v, "KEY_SILVER", -1); sq_pushinteger(v, 8); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'KEY_SILVER'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'KEY_SILVER'"); } sq_pushstring(v, "KEY_GOLD", -1); sq_pushinteger(v, 16); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'KEY_GOLD'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'KEY_GOLD'"); } sq_pushstring(v, "ANCHOR_TOP", -1); sq_pushinteger(v, 16); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'ANCHOR_TOP'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP'"); } sq_pushstring(v, "ANCHOR_BOTTOM", -1); sq_pushinteger(v, 32); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'ANCHOR_BOTTOM'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM'"); } sq_pushstring(v, "ANCHOR_LEFT", -1); sq_pushinteger(v, 1); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'ANCHOR_LEFT'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'ANCHOR_LEFT'"); } sq_pushstring(v, "ANCHOR_RIGHT", -1); sq_pushinteger(v, 2); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'ANCHOR_RIGHT'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'ANCHOR_RIGHT'"); } sq_pushstring(v, "ANCHOR_MIDDLE", -1); sq_pushinteger(v, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'ANCHOR_MIDDLE'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'ANCHOR_MIDDLE'"); } sq_pushstring(v, "ANCHOR_TOP_LEFT", -1); sq_pushinteger(v, 17); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'ANCHOR_TOP_LEFT'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP_LEFT'"); } sq_pushstring(v, "ANCHOR_TOP_RIGHT", -1); sq_pushinteger(v, 18); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'ANCHOR_TOP_RIGHT'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP_RIGHT'"); } sq_pushstring(v, "ANCHOR_BOTTOM_LEFT", -1); sq_pushinteger(v, 33); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'ANCHOR_BOTTOM_LEFT'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM_LEFT'"); } sq_pushstring(v, "ANCHOR_BOTTOM_RIGHT", -1); sq_pushinteger(v, 34); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register constant'ANCHOR_BOTTOM_RIGHT'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM_RIGHT'"); + } + + sq_pushstring(v, "display", -1); + sq_newclosure(v, &display_wrapper, 0); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'display'"); } sq_pushstring(v, "display_text_file", -1); sq_newclosure(v, &display_text_file_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'display_text_file'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'display_text_file'"); + } + + sq_pushstring(v, "load_worldmap", -1); + sq_newclosure(v, &load_worldmap_wrapper, 0); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'load_worldmap'"); + } + + sq_pushstring(v, "load_level", -1); + sq_newclosure(v, &load_level_wrapper, 0); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'load_level'"); } sq_pushstring(v, "wait", -1); sq_newclosure(v, &wait_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'wait'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'wait'"); + } + + sq_pushstring(v, "wait_for_screenswitch", -1); + sq_newclosure(v, &wait_for_screenswitch_wrapper, 0); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'wait_for_screenswitch'"); } sq_pushstring(v, "translate", -1); sq_newclosure(v, &translate_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'translate'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'translate'"); } sq_pushstring(v, "import", -1); sq_newclosure(v, &import_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'import'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'import'"); } sq_pushstring(v, "add_key", -1); sq_newclosure(v, &add_key_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'add_key'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'add_key'"); } // Register class DisplayEffect @@ -1089,55 +1971,41 @@ void register_supertux_wrapper(HSQUIRRELVM v) sq_pushstring(v, "fade_out", -1); sq_newclosure(v, &DisplayEffect_fade_out_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'fade_out'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'fade_out'"); } sq_pushstring(v, "fade_in", -1); sq_newclosure(v, &DisplayEffect_fade_in_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'fade_in'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'fade_in'"); } sq_pushstring(v, "set_black", -1); sq_newclosure(v, &DisplayEffect_set_black_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_black'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_black'"); } sq_pushstring(v, "is_black", -1); sq_newclosure(v, &DisplayEffect_is_black_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'is_black'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'is_black'"); } sq_pushstring(v, "sixteen_to_nine", -1); sq_newclosure(v, &DisplayEffect_sixteen_to_nine_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'sixteen_to_nine'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'sixteen_to_nine'"); } sq_pushstring(v, "four_to_three", -1); sq_newclosure(v, &DisplayEffect_four_to_three_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'four_to_three'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'four_to_three'"); } if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register class'DisplayEffect'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register class 'DisplayEffect'"); } // Register class Camera @@ -1150,39 +2018,29 @@ void register_supertux_wrapper(HSQUIRRELVM v) sq_pushstring(v, "shake", -1); sq_newclosure(v, &Camera_shake_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'shake'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'shake'"); } sq_pushstring(v, "set_pos", -1); sq_newclosure(v, &Camera_set_pos_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_pos'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_pos'"); } sq_pushstring(v, "set_mode", -1); sq_newclosure(v, &Camera_set_mode_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_mode'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_mode'"); } sq_pushstring(v, "scroll_to", -1); sq_newclosure(v, &Camera_scroll_to_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'scroll_to'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'scroll_to'"); } if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register class'Camera'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register class 'Camera'"); } // Register class Level @@ -1195,31 +2053,23 @@ void register_supertux_wrapper(HSQUIRRELVM v) sq_pushstring(v, "finish", -1); sq_newclosure(v, &Level_finish_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'finish'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'finish'"); } sq_pushstring(v, "spawn", -1); sq_newclosure(v, &Level_spawn_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'spawn'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'spawn'"); } sq_pushstring(v, "flip_vertically", -1); sq_newclosure(v, &Level_flip_vertically_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'flip_vertically'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'flip_vertically'"); } if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register class'Level'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register class 'Level'"); } // Register class ScriptedObject @@ -1232,103 +2082,77 @@ void register_supertux_wrapper(HSQUIRRELVM v) sq_pushstring(v, "set_action", -1); sq_newclosure(v, &ScriptedObject_set_action_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_action'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_action'"); } sq_pushstring(v, "get_action", -1); sq_newclosure(v, &ScriptedObject_get_action_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_action'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_action'"); } sq_pushstring(v, "move", -1); sq_newclosure(v, &ScriptedObject_move_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'move'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'move'"); } sq_pushstring(v, "set_pos", -1); sq_newclosure(v, &ScriptedObject_set_pos_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_pos'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_pos'"); } sq_pushstring(v, "get_pos_x", -1); sq_newclosure(v, &ScriptedObject_get_pos_x_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_pos_x'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_pos_x'"); } sq_pushstring(v, "get_pos_y", -1); sq_newclosure(v, &ScriptedObject_get_pos_y_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_pos_y'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_pos_y'"); } sq_pushstring(v, "set_velocity", -1); sq_newclosure(v, &ScriptedObject_set_velocity_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_velocity'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_velocity'"); } sq_pushstring(v, "get_velocity_x", -1); sq_newclosure(v, &ScriptedObject_get_velocity_x_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_velocity_x'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_velocity_x'"); } sq_pushstring(v, "get_velocity_y", -1); sq_newclosure(v, &ScriptedObject_get_velocity_y_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_velocity_y'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_velocity_y'"); } sq_pushstring(v, "set_visible", -1); sq_newclosure(v, &ScriptedObject_set_visible_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_visible'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_visible'"); } sq_pushstring(v, "is_visible", -1); sq_newclosure(v, &ScriptedObject_is_visible_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'is_visible'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'is_visible'"); } sq_pushstring(v, "get_name", -1); sq_newclosure(v, &ScriptedObject_get_name_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_name'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_name'"); } if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register class'ScriptedObject'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register class 'ScriptedObject'"); } // Register class Sound @@ -1341,23 +2165,17 @@ void register_supertux_wrapper(HSQUIRRELVM v) sq_pushstring(v, "play_music", -1); sq_newclosure(v, &Sound_play_music_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'play_music'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'play_music'"); } sq_pushstring(v, "play", -1); sq_newclosure(v, &Sound_play_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'play'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'play'"); } if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register class'Sound'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register class 'Sound'"); } // Register class Text @@ -1370,55 +2188,41 @@ void register_supertux_wrapper(HSQUIRRELVM v) sq_pushstring(v, "set_text", -1); sq_newclosure(v, &Text_set_text_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_text'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_text'"); } sq_pushstring(v, "set_font", -1); sq_newclosure(v, &Text_set_font_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_font'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_font'"); } sq_pushstring(v, "fade_in", -1); sq_newclosure(v, &Text_fade_in_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'fade_in'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'fade_in'"); } sq_pushstring(v, "fade_out", -1); sq_newclosure(v, &Text_fade_out_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'fade_out'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'fade_out'"); } sq_pushstring(v, "set_visible", -1); sq_newclosure(v, &Text_set_visible_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_visible'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_visible'"); } sq_pushstring(v, "set_centered", -1); sq_newclosure(v, &Text_set_centered_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_centered'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_centered'"); } if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register class'Text'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register class 'Text'"); } // Register class Player @@ -1431,55 +2235,41 @@ void register_supertux_wrapper(HSQUIRRELVM v) sq_pushstring(v, "make_invincible", -1); sq_newclosure(v, &Player_make_invincible_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'make_invincible'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'make_invincible'"); } sq_pushstring(v, "deactivate", -1); sq_newclosure(v, &Player_deactivate_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'deactivate'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'deactivate'"); } sq_pushstring(v, "activate", -1); sq_newclosure(v, &Player_activate_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'activate'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'activate'"); } sq_pushstring(v, "walk", -1); sq_newclosure(v, &Player_walk_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'walk'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'walk'"); } sq_pushstring(v, "set_visible", -1); sq_newclosure(v, &Player_set_visible_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_visible'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_visible'"); } sq_pushstring(v, "get_visible", -1); sq_newclosure(v, &Player_get_visible_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_visible'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_visible'"); } if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register class'Player'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register class 'Player'"); } // Register class FloatingImage @@ -1492,87 +2282,65 @@ void register_supertux_wrapper(HSQUIRRELVM v) sq_pushstring(v, "constructor", -1); sq_newclosure(v, &FloatingImage_constructor_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'constructor'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'constructor'"); } sq_pushstring(v, "set_layer", -1); sq_newclosure(v, &FloatingImage_set_layer_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_layer'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_layer'"); } sq_pushstring(v, "get_layer", -1); sq_newclosure(v, &FloatingImage_get_layer_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_layer'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_layer'"); } sq_pushstring(v, "set_pos", -1); sq_newclosure(v, &FloatingImage_set_pos_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_pos'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_pos'"); } sq_pushstring(v, "get_pos_x", -1); sq_newclosure(v, &FloatingImage_get_pos_x_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_pos_x'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_pos_x'"); } sq_pushstring(v, "get_pos_y", -1); sq_newclosure(v, &FloatingImage_get_pos_y_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_pos_y'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_pos_y'"); } sq_pushstring(v, "set_anchor_point", -1); sq_newclosure(v, &FloatingImage_set_anchor_point_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_anchor_point'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_anchor_point'"); } sq_pushstring(v, "get_anchor_point", -1); sq_newclosure(v, &FloatingImage_get_anchor_point_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_anchor_point'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_anchor_point'"); } sq_pushstring(v, "set_visible", -1); sq_newclosure(v, &FloatingImage_set_visible_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'set_visible'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'set_visible'"); } sq_pushstring(v, "get_visible", -1); sq_newclosure(v, &FloatingImage_get_visible_wrapper, 0); if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register function'get_visible'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register function 'get_visible'"); } if(SQ_FAILED(sq_createslot(v, -3))) { - std::ostringstream msg; - msg << "Couldn't register class'FloatingImage'"; - throw SquirrelError(v, msg.str()); + throw SquirrelError(v, "Couldn't register class 'FloatingImage'"); } sq_pop(v, 1); diff --git a/src/scripting/wrapper.interface.hpp b/src/scripting/wrapper.interface.hpp index 68a98a10a..823db4944 100644 --- a/src/scripting/wrapper.interface.hpp +++ b/src/scripting/wrapper.interface.hpp @@ -1,4 +1,4 @@ -/* This file is processes by miniswig to produce the scripting API */ +/* This file is processed by miniswig to produce the scripting API */ #include "display_effect.hpp" #include "camera.hpp" #include "level.hpp" diff --git a/src/scripting/wrapper_util.cpp b/src/scripting/wrapper_util.cpp index 605ff1b20..2244a8de1 100644 --- a/src/scripting/wrapper_util.cpp +++ b/src/scripting/wrapper_util.cpp @@ -1,9 +1,31 @@ +// $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $ +// +// SuperTux +// Copyright (C) 2005 Matthias Braun +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. #include #include #include #include "wrapper_util.hpp" +namespace Scripting +{ + std::string squirrel2string(HSQUIRRELVM v, int i) { std::ostringstream os; @@ -180,4 +202,37 @@ void print_squirrel_stack(HSQUIRRELVM v) printf("--------------------------------------------------------------\n"); } -/* EOF */ +static SQInteger squirrel_read_char(SQUserPointer file) +{ + std::istream* in = reinterpret_cast (file); + char c = in->get(); + if(in->eof()) + return 0; + return c; +} + +void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename) +{ + if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, sourcename.c_str(), true))) + throw SquirrelError(vm, "Couldn't parse script"); +} + +void compile_and_run(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename) +{ + compile_script(vm, in, sourcename); + + int oldtop = sq_gettop(vm); + + try { + sq_pushroottable(vm); + if(SQ_FAILED(sq_call(vm, 1, false))) + throw SquirrelError(vm, "Couldn't start script"); + } catch(...) { + sq_settop(vm, oldtop); + throw; + } + + sq_settop(vm, oldtop); +} + +} diff --git a/src/scripting/wrapper_util.hpp b/src/scripting/wrapper_util.hpp index a6cfa2360..f18308673 100644 --- a/src/scripting/wrapper_util.hpp +++ b/src/scripting/wrapper_util.hpp @@ -1,11 +1,72 @@ +// $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $ +// +// SuperTux +// Copyright (C) 2005 Matthias Braun +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. #ifndef __WRAPPERUTIL_HPP__ #define __WRAPPERUTIL_HPP__ #include #include +#include #include +#include "wrapper.hpp" +#include "squirrel_error.hpp" -std::string squirrel2string(HSQUIRRELVM v, int i); -void print_squirrel_stack(HSQUIRRELVM v); +namespace Scripting +{ + +std::string squirrel2string(HSQUIRRELVM vm, int i); +void print_squirrel_stack(HSQUIRRELVM vm); +void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename); +void compile_and_run(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename); + +template +void expose_object(HSQUIRRELVM v, int table_idx, T* object, + const std::string& name, bool free = false) +{ + sq_pushstring(v, name.c_str(), -1); + Scripting::create_squirrel_instance(v, object, free); + + if(table_idx < 0) + table_idx -= 2; + + // register instance in root table + if(SQ_FAILED(sq_createslot(v, table_idx))) { + std::ostringstream msg; + msg << "Couldn't register object '" << name << "' in squirrel table"; + throw Scripting::SquirrelError(v, msg.str()); + } +} + +static inline void unexpose_object(HSQUIRRELVM v, int table_idx, const std::string& name) +{ + sq_pushstring(v, name.c_str(), name.length()); + + if(table_idx < 0) + table_idx -= 1; + + if(SQ_FAILED(sq_deleteslot(v, table_idx, SQFalse))) { + std::ostringstream msg; + msg << "Couldn't unregister object '" << name << "' in squirrel root table"; + throw Scripting::SquirrelError(v, msg.str()); + } +} + +} #endif diff --git a/src/sector.cpp b/src/sector.cpp index 3b1926fc4..a710145e0 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -60,26 +60,40 @@ #include "badguy/jumpy.hpp" #include "trigger/sequence_trigger.hpp" #include "player_status.hpp" -#include "scripting/script_interpreter.hpp" -#include "scripting/sound.hpp" -#include "scripting/scripted_object.hpp" -#include "scripting/text.hpp" +#include "script_manager.hpp" +#include "scripting/wrapper_util.hpp" +#include "script_interface.hpp" #include "msg.hpp" Sector* Sector::_current = 0; Sector::Sector() - : gravity(10), player(0), solids(0), camera(0), - currentmusic(LEVEL_MUSIC) + : currentmusic(LEVEL_MUSIC), gravity(10), + player(0), solids(0), camera(0) { - player = new Player(player_status); - add_object(player); + add_object(new Player(player_status)); + add_object(new DisplayEffect()); + add_object(new TextObject()); #ifdef USE_GRID grid = new CollisionGrid(32000, 32000); #else grid = 0; #endif + + // create a new squirrel table for the sector + HSQUIRRELVM vm = script_manager->get_global_vm(); + + sq_newtable(vm); + sq_pushroottable(vm); + if(SQ_FAILED(sq_setdelegate(vm, -2))) + throw Scripting::SquirrelError(vm, "Couldn't set sector_table delegate"); + + sq_resetobject(§or_table); + if(SQ_FAILED(sq_getstackobj(vm, -1, §or_table))) + throw Scripting::SquirrelError(vm, "Couldn't get sector table"); + sq_addref(vm, §or_table); + sq_pop(vm, 1); } Sector::~Sector() @@ -87,19 +101,21 @@ Sector::~Sector() update_game_objects(); assert(gameobjects_new.size() == 0); + deactivate(); + delete grid; for(GameObjects::iterator i = gameobjects.begin(); i != gameobjects.end(); ++i) { + before_object_remove(*i); delete *i; } for(SpawnPoints::iterator i = spawnpoints.begin(); i != spawnpoints.end(); ++i) delete *i; - - if(_current == this) - _current = 0; + + sq_release(script_manager->get_global_vm(), §or_table); } GameObject* @@ -144,9 +160,7 @@ Sector::parse_object(const std::string& name, const lisp::Lisp& reader) void Sector::parse(const lisp::Lisp& sector) -{ - _current = this; - +{ lisp::ListIterator iter(§or); while(iter.next()) { const std::string& token = iter.item(); @@ -187,8 +201,6 @@ Sector::parse(const lisp::Lisp& sector) void Sector::parse_old_format(const lisp::Lisp& reader) { - _current = this; - name = "main"; reader.get("gravity", gravity); @@ -375,6 +387,17 @@ Sector::write(lisp::Writer& writer) } } +HSQUIRRELVM +Sector::run_script(std::istream& in, const std::string& sourcename) +{ + HSQUIRRELVM vm = script_manager->create_thread(); + sq_pushobject(vm, sector_table); + sq_setroottable(vm); + Scripting::compile_and_run(vm, in, sourcename); + + return vm; +} + void Sector::add_object(GameObject* object) { @@ -418,21 +441,64 @@ Sector::activate(const std::string& spawnpoint) } else { activate(sp->pos); } +} + +void +Sector::activate(const Vector& player_pos) +{ + if(_current != this) { + if(_current != NULL) + _current->deactivate(); + _current = this; + + // register sectortable as current_sector in scripting + HSQUIRRELVM vm = script_manager->get_global_vm(); + sq_pushroottable(vm); + sq_pushstring(vm, "current_sector", -1); + sq_pushobject(vm, sector_table); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't set current_sector in roottable"); + sq_pop(vm, 1); + + for(GameObjects::iterator i = gameobjects.begin(); + i != gameobjects.end(); ++i) { + GameObject* object = *i; + + try_expose(object); + } + } + + player->move(player_pos); + camera->reset(player->get_pos()); // Run init script if(init_script != "") { - ScriptInterpreter::add_script_object(this, - std::string("Sector(") + name + ") - init", init_script); + std::istringstream in(init_script); + run_script(in, std::string("Sector(") + name + ") - init"); } } void -Sector::activate(const Vector& player_pos) +Sector::deactivate() { - _current = this; + if(_current != this) + return; + + HSQUIRRELVM vm = script_manager->get_global_vm(); + sq_pushroottable(vm); + sq_pushstring(vm, "current_sector", -1); + if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse))) + throw Scripting::SquirrelError(vm, "Couldn't unset current_sector in roottable"); + sq_pop(vm, 1); + + for(GameObjects::iterator i = gameobjects.begin(); + i != gameobjects.end(); ++i) { + GameObject* object = *i; + + try_unexpose(object); + } - player->move(player_pos); - camera->reset(player->get_pos()); + _current = NULL; } Rect @@ -509,6 +575,8 @@ Sector::update_game_objects() ++i; continue; } + + before_object_remove(object); delete *i; i = gameobjects.erase(i); @@ -519,43 +587,95 @@ Sector::update_game_objects() i != gameobjects_new.end(); ++i) { GameObject* object = *i; + + before_object_add(object); - Bullet* bullet = dynamic_cast (object); - if(bullet) - bullets.push_back(bullet); - - MovingObject* movingobject = dynamic_cast (object); - if(movingobject) { - moving_objects.push_back(movingobject); - #ifdef USE_GRID - grid->add_object(movingobject); + gameobjects.push_back(object); + } + gameobjects_new.clear(); +} + +bool +Sector::before_object_add(GameObject* object) +{ + Bullet* bullet = dynamic_cast (object); + if(bullet) + bullets.push_back(bullet); + + MovingObject* movingobject = dynamic_cast (object); + if(movingobject) { + moving_objects.push_back(movingobject); +#ifdef USE_GRID + grid->add_object(movingobject); #endif + } + + TileMap* tilemap = dynamic_cast (object); + if(tilemap && tilemap->is_solid()) { + if(solids == 0) { + solids = tilemap; + } else { + msg_warning << "Another solid tilemaps added. Ignoring" << std::endl; } - - TileMap* tilemap = dynamic_cast (object); - if(tilemap && tilemap->is_solid()) { - if(solids == 0) { - solids = tilemap; - } else { - msg_warning << "Another solid tilemaps added. Ignoring" << std::endl; - } + } + + Camera* camera = dynamic_cast (object); + if(camera) { + if(this->camera != 0) { + msg_warning << "Multiple cameras added. Ignoring" << std::endl; + return false; } + this->camera = camera; + } - Camera* camera = dynamic_cast (object); - if(camera) { - if(this->camera != 0) { - msg_warning << "Multiple cameras added. Ignoring" << std::endl; - continue; - } - this->camera = camera; + Player* player = dynamic_cast (object); + if(player) { + if(this->player != 0) { + msg_warning << "Multiple players added. Ignoring" << std::endl; + return false; } + this->player = player; + } - gameobjects.push_back(object); + if(_current == this) { + try_expose(object); + } + + return true; +} + +void +Sector::try_expose(GameObject* object) +{ + ScriptInterface* interface = dynamic_cast (object); + if(interface != NULL) { + HSQUIRRELVM vm = script_manager->get_global_vm(); + sq_pushobject(vm, sector_table); + interface->expose(vm, -1); + sq_pop(vm, 1); } - gameobjects_new.clear(); } void +Sector::before_object_remove(GameObject* object) +{ + if(_current == this) + try_unexpose(object); +} + +void +Sector::try_unexpose(GameObject* object) +{ + ScriptInterface* interface = dynamic_cast (object); + if(interface != NULL) { + HSQUIRRELVM vm = script_manager->get_global_vm(); + sq_pushobject(vm, sector_table); + interface->unexpose(vm, -1); + sq_pop(vm, 1); + } +} + +void Sector::draw(DrawingContext& context) { context.push_transform(); diff --git a/src/sector.hpp b/src/sector.hpp index 5bf497a05..80ed7340a 100644 --- a/src/sector.hpp +++ b/src/sector.hpp @@ -21,6 +21,7 @@ #include #include +#include #include "direction.hpp" #include "math/vector.hpp" @@ -67,12 +68,19 @@ public: /// activates this sector (change music, intialize player class, ...) void activate(const std::string& spawnpoint); void activate(const Vector& player_pos); + void deactivate(); void update(float elapsed_time); void update_game_objects(); void draw(DrawingContext& context); + /** + * runs a script in the context of the sector (sector_table will be the + * roottable of this squirrel VM) + */ + HSQUIRRELVM run_script(std::istream& in, const std::string& sourcename); + /// adds a gameobject void add_object(GameObject* object); @@ -112,8 +120,16 @@ public: return std::vector(1, this->player); } + Rect get_active_region(); + private: uint32_t collision_tile_attributes(const Rect& dest) const; + + void before_object_remove(GameObject* object); + bool before_object_add(GameObject* object); + + void try_expose(GameObject* object); + void try_unexpose(GameObject* object); bool collision_static(MovingObject* object, const Vector& movement); @@ -124,44 +140,43 @@ private: void collision_object(MovingObject* object1, MovingObject* object2) const; GameObject* parse_object(const std::string& name, const lisp::Lisp& lisp); - + + void fix_old_tiles(); + + typedef std::vector GameObjects; + typedef std::vector MovingObjects; + typedef std::vector SpawnPoints; + static Sector* _current; std::string name; -public: - std::string music; - float gravity; - - // some special objects, where we need direct access - Player* player; - TileMap* solids; - Camera* camera; - -private: std::vector bullets; std::string init_script; -public: // TODO make this private again - typedef std::vector GameObjects; - GameObjects gameobjects; - typedef std::vector MovingObjects; - MovingObjects moving_objects; - typedef std::vector SpawnPoints; - SpawnPoints spawnpoints; - - Rect get_active_region(); - -private: - void fix_old_tiles(); - /// container for newly created objects, they'll be added in Sector::update GameObjects gameobjects_new; MusicType currentmusic; CollisionGrid* grid; + + HSQOBJECT sector_table; + +public: // TODO make this private again + GameObjects gameobjects; + MovingObjects moving_objects; + SpawnPoints spawnpoints; + + std::string music; + float gravity; + + // some special objects, where we need direct access + // (try to avoid accessing them directly) + Player* player; + TileMap* solids; + Camera* camera; }; #endif diff --git a/src/textscroller.cpp b/src/textscroller.cpp index 45b092c93..5b05d2aca 100644 --- a/src/textscroller.cpp +++ b/src/textscroller.cpp @@ -35,7 +35,6 @@ #include "audio/sound_manager.hpp" #include "main.hpp" #include "control/joystickkeyboardcontroller.hpp" -#include "exceptions.hpp" static const float DEFAULT_SPEED = 20; static const float LEFT_BORDER = 50; @@ -84,8 +83,9 @@ TextScroller::TextScroller(const std::string& filename) text_lisp->get("speed", defaultspeed); text_lisp->get("music", music); } catch(std::exception& e) { - msg_warning << "Couldn't load file '" << filename << "': " << e.what() << std::endl; - return; + std::ostringstream msg; + msg << "Couldn't load file '" << filename << "': " << e.what() << std::endl; + throw std::runtime_error(msg.str()); } // Split text string lines into a vector diff --git a/src/title.cpp b/src/title.cpp index f95c2a872..d2ed7daf0 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -61,7 +61,6 @@ #include "control/joystickkeyboardcontroller.hpp" #include "control/codecontroller.hpp" #include "main.hpp" -#include "exceptions.hpp" #include "msg.hpp" #include "console.hpp" @@ -295,6 +294,13 @@ TitleScreen::setup() } void +TitleScreen::leave() +{ + Sector* sector = titlesession->get_current_sector(); + sector->deactivate(); +} + +void TitleScreen::draw(DrawingContext& context) { Sector* sector = titlesession->get_current_sector(); diff --git a/src/title.hpp b/src/title.hpp index aa264736b..5ff13a119 100644 --- a/src/title.hpp +++ b/src/title.hpp @@ -37,6 +37,7 @@ public: virtual ~TitleScreen(); virtual void setup(); + virtual void leave(); virtual void draw(DrawingContext& context); diff --git a/src/trigger/scripttrigger.cpp b/src/trigger/scripttrigger.cpp index 07939924e..b9e5e109a 100644 --- a/src/trigger/scripttrigger.cpp +++ b/src/trigger/scripttrigger.cpp @@ -29,7 +29,6 @@ #include "lisp/lisp.hpp" #include "lisp/writer.hpp" #include "object_factory.hpp" -#include "scripting/script_interpreter.hpp" #include "sector.hpp" ScriptTrigger::ScriptTrigger(const lisp::Lisp& reader) @@ -87,8 +86,8 @@ ScriptTrigger::event(Player& , EventType type) if(type != triggerevent) return; - ScriptInterpreter::add_script_object(Sector::current(), "trigger - scritp", - script); + std::istringstream stream(script); + Sector::current()->run_script(stream, "ScriptTrigger"); } IMPLEMENT_FACTORY(ScriptTrigger, "scripttrigger"); diff --git a/src/video/font.cpp b/src/video/font.cpp index 7394441e7..f007dabfa 100644 --- a/src/video/font.cpp +++ b/src/video/font.cpp @@ -114,6 +114,9 @@ Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment, l = text.size(); done = true; } + + if(l > sizeof(temp)-1) + l = sizeof(temp)-1; temp[text.copy(temp, l - i, i)] = '\0'; diff --git a/src/world.cpp b/src/world.cpp index 04c2de56b..7999097b3 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -27,7 +27,8 @@ #include "lisp/parser.hpp" #include "lisp/lisp.hpp" #include "physfs/physfs_stream.hpp" -#include "scripting/script_interpreter.hpp" +#include "script_manager.hpp" +#include "scripting/wrapper_util.hpp" #include "msg.hpp" static bool has_suffix(const std::string& data, const std::string& suffix) @@ -92,15 +93,11 @@ World::load(const std::string& filename) void World::run() { - try { - std::string filename = basedir + "/world.nut"; - std::auto_ptr interpeter (new ScriptInterpreter(basedir)); - IFileStream in(filename); - - interpeter->run_script(in, filename, true); - } catch(std::exception& e) { - msg_warning << "Problem running world script: " << e.what() << std::endl; - } + std::string filename = basedir + "/world.nut"; + IFileStream in(filename); + + HSQUIRRELVM vm = script_manager->create_thread(); + Scripting::compile_and_run(vm, in, filename); } const std::string& diff --git a/src/worldmap.cpp b/src/worldmap.cpp index b4b6f1f77..3a080672b 100644 --- a/src/worldmap.cpp +++ b/src/worldmap.cpp @@ -56,8 +56,6 @@ #include "control/joystickkeyboardcontroller.hpp" #include "object/background.hpp" #include "object/tilemap.hpp" -#include "scripting/script_interpreter.hpp" -#include "exceptions.hpp" Menu* worldmap_menu = 0; @@ -608,21 +606,6 @@ WorldMap::on_escape_press() } } -void -WorldMap::get_input() -{ - main_controller->update(); - - SDL_Event event; - while (SDL_PollEvent(&event)) { - if (Menu::current()) - Menu::current()->event(event); - main_controller->process_event(event); - if(event.type == SDL_QUIT) - throw graceful_shutdown(); - } -} - Vector WorldMap::get_next_tile(Vector pos, Direction direction) { @@ -726,6 +709,7 @@ WorldMap::finished_level(const std::string& filename) } if (level->extro_script != "") { + /* TODO try { std::auto_ptr interpreter (new ScriptInterpreter(levels_path)); @@ -735,6 +719,7 @@ WorldMap::finished_level(const std::string& filename) } catch(std::exception& e) { msg_fatal << "Couldn't run level-extro-script:" << e.what() << std::endl; } + */ } if (!level->next_worldmap.empty()) { diff --git a/src/worldmap.hpp b/src/worldmap.hpp index 0833c38e8..a643e4130 100644 --- a/src/worldmap.hpp +++ b/src/worldmap.hpp @@ -229,8 +229,6 @@ public: void load_map(); - void get_input(); - void add_object(GameObject* object); void clear_objects(); diff --git a/tools/miniswig/create_wrapper.cpp b/tools/miniswig/create_wrapper.cpp index c279fa4c9..d0c913192 100644 --- a/tools/miniswig/create_wrapper.cpp +++ b/tools/miniswig/create_wrapper.cpp @@ -242,10 +242,8 @@ WrapperCreator::create_register_slot_code(const std::string& what, const std::string& name) { out << ind << "if(SQ_FAILED(sq_createslot(v, -3))) {\n"; - out << ind << ind << "std::ostringstream msg;\n"; - out << ind << ind << "msg << \"Couldn't register " << what << "'" - << name << "'\";\n"; - out << ind << ind << "throw SquirrelError(v, msg.str());\n"; + out << ind << ind << "throw SquirrelError(v, \"" + << "Couldn't register " << what << " '" << name << "'\");\n"; out << ind << "}\n"; } @@ -265,19 +263,22 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) if(_class != 0) { out << _class->name << "_"; } - out << function->name << "_wrapper(HSQUIRRELVM v)\n" + out << function->name << "_wrapper(HSQUIRRELVM vm)\n" << "{\n"; // avoid warning... if(_class == 0 && function->parameters.empty() && function->return_type.is_void() && function->type != Function::CONSTRUCTOR) { - out << ind << "(void) v;\n"; + out << ind << "(void) vm;\n"; } - // eventually retrieve pointer to class instance + // retrieve pointer to class instance if(_class != 0 && function->type != Function::CONSTRUCTOR) { out << ind << ns_prefix << _class->name << "* _this;\n"; - out << ind << "sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);\n"; + out << ind << "if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast (&_this), 0))) {\n"; + out << ind << ind << "sq_throwerror(vm, _SC(\"'" << function->name << "' called without instance\"));\n"; + out << ind << ind << "return SQ_ERROR;\n"; + out << ind << "}\n"; } // custom function? @@ -296,7 +297,7 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) out << "_this->"; else out << ns_prefix; - out << function->name << "(v);\n"; + out << function->name << "(vm);\n"; out << "}\n"; out << "\n"; return; @@ -308,7 +309,7 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) for(std::vector::iterator p = function->parameters.begin(); p != function->parameters.end(); ++p) { if(i == 0 && p->type.atomic_type == HSQUIRRELVMType::instance()) { - out << ind << "HSQUIRRELVM arg0 = v;\n"; + out << ind << "HSQUIRRELVM arg0 = vm;\n"; arg_offset--; } else { char argname[64]; @@ -320,7 +321,8 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) // call function out << ind << "\n"; - out << ind; + out << ind << "try {\n"; + out << ind << ind; if(!function->return_type.is_void()) { function->return_type.write_c_type(out); out << " return_value = "; @@ -346,8 +348,11 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) } out << ");\n"; if(function->type == Function::CONSTRUCTOR) { - out << ind << "sq_setinstanceup(v, 1, _this);\n"; - out << ind << "sq_setreleasehook(v, 1, " + out << ind << "if(SQ_FAILED(sq_setinstanceup(vm, 1, _this))) {\n"; + out << ind << ind << "sq_throwerror(vm, _SC(\"Couldn't setup instance of '" << _class->name << "' class\"));\n"; + out << ind << ind << "return SQ_ERROR;\n"; + out << ind << "}\n"; + out << ind << "sq_setreleasehook(vm, 1, " << _class->name << "_release_hook);\n"; } out << ind << "\n"; @@ -359,13 +364,24 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) << " but has a return value."; throw std::runtime_error(msg.str()); } - out << ind << "return sq_suspendvm(v);\n"; + out << ind << ind << "return sq_suspendvm(vm);\n"; } else if(function->return_type.is_void()) { - out << ind << "return 0;\n"; + out << ind << ind << "return 0;\n"; } else { push_to_stack(function->return_type, "return_value"); - out << ind << "return 1;\n"; + out << ind << ind << "return 1;\n"; } + + out << ind << "\n"; + out << ind << "} catch(std::exception& e) {\n"; + out << ind << ind << "sq_throwerror(vm, e.what());\n"; + out << ind << ind << "return SQ_ERROR;\n"; + out << ind << "} catch(...) {\n"; + out << ind << ind << "sq_throwerror(vm, _SC(\"Unexpected exception while executing function '" << function->name << "'\"));\n"; + out << ind << ind << "return SQ_ERROR;\n"; + out << ind << "}\n"; + out << ind << "\n"; + out << "}\n"; out << "\n"; } @@ -380,16 +396,28 @@ WrapperCreator::prepare_argument(const Type& type, size_t index, throw std::runtime_error("Pointers not handled yet"); if(type.atomic_type == &BasicType::INT) { out << ind << "int " << var << ";\n"; - out << ind << "sq_getinteger(v, " << index << ", &" << var << ");\n"; + out << ind << "if(SQ_FAILED(sq_getinteger(vm, " << index << ", &" << var << "))) {\n"; + out << ind << ind << "sq_throwerror(vm, _SC(\"Argument " << (index-1) << " not an integer\"));\n"; + out << ind << ind << "return SQ_ERROR;\n"; + out << ind << "}\n"; } else if(type.atomic_type == &BasicType::FLOAT) { out << ind << "float " << var << ";\n"; - out << ind << "sq_getfloat(v, " << index << ", &" << var << ");\n"; + out << ind << "if(SQ_FAILED(sq_getfloat(vm, " << index << ", &" << var << "))) {\n"; + out << ind << ind << "sq_throwerror(vm, _SC(\"Argument " << (index-1) << " not a float\"));\n"; + out << ind << ind << "return SQ_ERROR;\n"; + out << ind << "}\n"; } else if(type.atomic_type == &BasicType::BOOL) { out << ind << "SQBool " << var << ";\n"; - out << ind << "sq_getbool(v, " << index << ", &" << var << ");\n"; + out << ind << "if(SQ_FAILED(sq_getbool(vm, " << index << ", &" << var << "))) {\n"; + out << ind << ind << "sq_throwerror(vm, _SC(\"Argument " << (index-1) << " not a bool\"));\n"; + out << ind << ind << "return SQ_ERROR;\n"; + out << ind << "}\n"; } else if(type.atomic_type == StringType::instance()) { out << ind << "const char* " << var << ";\n"; - out << ind << "sq_getstring(v, " << index << ", &" << var << ");\n"; + out << ind << "if(SQ_FAILED(sq_getstring(vm, " << index << ", &" << var << "))) {\n"; + out << ind << ind << "sq_throwerror(vm, _SC(\"Argument " << (index-1) << " not a string\"));\n"; + out << ind << ind << "return SQ_ERROR;\n"; + out << ind << "}\n"; } else { std::ostringstream msg; msg << "Type '" << type.atomic_type->name << "' not supported yet."; @@ -404,15 +432,15 @@ WrapperCreator::push_to_stack(const Type& type, const std::string& var) throw std::runtime_error("References not handled yet"); if(type.pointer > 0) throw std::runtime_error("Pointers not handled yet"); - out << ind; + out << ind << ind; if(type.atomic_type == &BasicType::INT) { - out << "sq_pushinteger(v, " << var << ");\n"; + out << "sq_pushinteger(vm, " << var << ");\n"; } else if(type.atomic_type == &BasicType::FLOAT) { - out << "sq_pushfloat(v, " << var << ");\n"; + out << "sq_pushfloat(vm, " << var << ");\n"; } else if(type.atomic_type == &BasicType::BOOL) { - out << "sq_pushbool(v, " << var << ");\n"; + out << "sq_pushbool(vm, " << var << ");\n"; } else if(type.atomic_type == StringType::instance()) { - out << "sq_pushstring(v, " << var << ".c_str(), " + out << "sq_pushstring(vm, " << var << ".c_str(), " << var << ".size());\n"; } else { std::ostringstream msg;