From: Matthias Braun Date: Tue, 11 Apr 2006 17:48:50 +0000 (+0000) Subject: hopefully fixed the crash on exit, keep sectors script bundled in the sector and... X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=acd1950b9b853d6b7c56a2cb43e77ec3147b2369;p=supertux.git hopefully fixed the crash on exit, keep sectors script bundled in the sector and destroy them when the sector gets destroyed SVN-Revision: 3300 --- diff --git a/configure.ac b/configure.ac index f591dee3f..21cc76504 100644 --- a/configure.ac +++ b/configure.ac @@ -26,6 +26,11 @@ CXXFLAGS="$CXXFLAGS -ffast-math" AC_PROG_CC AC_PROG_CXX AC_PROG_INSTALL +AC_PATH_PROG(AR, ar) +if test "$AR" = "" ; then + AC_MSG_ERROR([Couldn't find ar]) +fi +AR="$AR ru" AC_C_BIGENDIAN diff --git a/data/levels/misc/menu.stl b/data/levels/misc/menu.stl index 144b13333..cfdc5fbfc 100644 --- a/data/levels/misc/menu.stl +++ b/data/levels/misc/menu.stl @@ -10,7 +10,8 @@ logo <- FloatingImage(\"images/objects/logo/logo.sprite\"); logo.set_anchor_point(ANCHOR_TOP); logo.set_pos(0, 30); logo.set_visible(true); -wait(10000); +// Suspend (this is needed so that logo doesn't get deleted) +suspend(); ") (background (image "images/background/arctis.jpg") diff --git a/src/console.cpp b/src/console.cpp index 091619ccc..257172c77 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -72,7 +72,7 @@ Console::execute_script(const std::string& command) { using namespace Scripting; - HSQUIRRELVM vm = script_manager->get_global_vm(); + HSQUIRRELVM vm = ScriptManager::instance->get_vm(); if(command == "") return; diff --git a/src/game_session.cpp b/src/game_session.cpp index f0da60304..6fc8fb3ac 100644 --- a/src/game_session.cpp +++ b/src/game_session.cpp @@ -473,8 +473,6 @@ GameSession::process_menu() main_loop->exit_screen(); break; } - } else if(menu == options_menu) { - process_options_menu(); } } } diff --git a/src/main.cpp b/src/main.cpp index 8874b003e..900079e65 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -379,9 +379,9 @@ static void init_audio() static void init_scripting() { - script_manager = new ScriptManager(); + ScriptManager::instance = new ScriptManager(); - HSQUIRRELVM vm = script_manager->get_global_vm(); + HSQUIRRELVM vm = ScriptManager::instance->get_vm(); sq_pushroottable(vm); expose_object(vm, -1, new Scripting::Sound(), "Sound", true); expose_object(vm, -1, new Scripting::Level(), "Level", true); @@ -516,9 +516,8 @@ int main(int argc, char** argv) } free_menu(); - delete script_manager; - script_manager = NULL; - printf("crashunloadshared?\n"); + delete ScriptManager::instance; + ScriptManager::instance = NULL; unload_shared(); quit_audio(); diff --git a/src/mainloop.cpp b/src/mainloop.cpp index afd60ae08..575005bb8 100644 --- a/src/mainloop.cpp +++ b/src/mainloop.cpp @@ -26,7 +26,6 @@ #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" @@ -105,7 +104,7 @@ MainLoop::run() } next_screen->setup(); - script_manager->fire_wakeup_event(ScriptManager::SCREEN_SWITCHED); + ScriptManager::instance->fire_wakeup_event(ScriptManager::SCREEN_SWITCHED); current_screen.reset(next_screen.release()); next_screen.reset(NULL); nextpush = false; @@ -164,7 +163,7 @@ MainLoop::run() elapsed_time *= speed; game_time += elapsed_time; - script_manager->update(); + ScriptManager::instance->update(); current_screen->update(elapsed_time); main_controller->update(); diff --git a/src/misc.cpp b/src/misc.cpp index 047ab3e20..2004302ff 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -27,79 +27,36 @@ #include "resources.hpp" #include "worldmap.hpp" #include "gettext.hpp" +#include "options_menu.hpp" #include "control/joystickkeyboardcontroller.hpp" Menu* main_menu = 0; Menu* game_menu = 0; -Menu* options_menu = 0; - -void process_options_menu() -{ - switch (options_menu->check()) { - case MNID_FULLSCREEN: - if(config->use_fullscreen != options_menu->is_toggled(MNID_FULLSCREEN)) { - config->use_fullscreen = !config->use_fullscreen; - init_video(); - config->save(); - } - break; - case MNID_SOUND: - if(config->sound_enabled != options_menu->is_toggled(MNID_SOUND)) { - config->sound_enabled = !config->sound_enabled; - sound_manager->enable_sound(config->sound_enabled); - config->save(); - } - break; - case MNID_MUSIC: - if(config->music_enabled != options_menu->is_toggled(MNID_MUSIC)) { - config->music_enabled = !config->music_enabled; - sound_manager->enable_music(config->music_enabled); - config->save(); - } - break; - default: - break; - } -} void setup_menu() { main_menu = new Menu(); - options_menu = new Menu(); game_menu = new Menu(); worldmap_menu = new Menu(); main_menu->set_pos(SCREEN_WIDTH/2, 335); main_menu->add_entry(MNID_STARTGAME, _("Start Game")); main_menu->add_entry(MNID_LEVELS_CONTRIB, _("Contrib Levels")); - main_menu->add_submenu(_("Options"), options_menu); - //main_menu->add_entry(MNID_LEVELEDITOR, _("Level Editor")); + main_menu->add_submenu(_("Options"), get_options_menu()); main_menu->add_entry(MNID_CREDITS, _("Credits")); main_menu->add_entry(MNID_QUITMAINMENU, _("Quit")); - options_menu->add_label(_("Options")); - options_menu->add_hl(); - options_menu->add_toggle(MNID_FULLSCREEN,_("Fullscreen"), config->use_fullscreen); - options_menu->add_toggle(MNID_SOUND, _("Sound"), config->sound_enabled); - options_menu->add_toggle(MNID_MUSIC, _("Music"), config->music_enabled); - options_menu->add_submenu(_("Setup Keys"), - main_controller->get_key_options_menu()); - options_menu->add_submenu(_("Setup Joystick"), - main_controller->get_joystick_options_menu()); - options_menu->add_hl(); - options_menu->add_back(_("Back")); - game_menu->add_label(_("Pause")); game_menu->add_hl(); game_menu->add_entry(MNID_CONTINUE, _("Continue")); - game_menu->add_submenu(_("Options"), options_menu); + game_menu->add_submenu(_("Options"), get_options_menu()); game_menu->add_hl(); game_menu->add_entry(MNID_ABORTLEVEL, _("Abort Level")); worldmap_menu->add_label(_("Pause")); worldmap_menu->add_hl(); worldmap_menu->add_entry(WorldMapNS::MNID_RETURNWORLDMAP, _("Continue")); - worldmap_menu->add_submenu(_("Options"), options_menu); + worldmap_menu->add_submenu(_("Options"), get_options_menu()); worldmap_menu->add_hl(); worldmap_menu->add_entry(WorldMapNS::MNID_QUITWORLDMAP, _("Quit Game")); } @@ -109,6 +66,6 @@ void free_menu() delete worldmap_menu; delete main_menu; delete game_menu; - delete options_menu; + free_options_menu(); } diff --git a/src/misc.hpp b/src/misc.hpp index 7b97edd17..a158a7727 100644 --- a/src/misc.hpp +++ b/src/misc.hpp @@ -26,15 +26,6 @@ enum MainMenuIDs { MNID_QUITMAINMENU }; -enum OptionsMenuIDs { - MNID_FULLSCREEN, - MNID_SOUND, - MNID_MUSIC -}; - -/* Handle changes made to global settings in the options menu. */ -void process_options_menu(); - /* Create and setup menus. */ void setup_menu(); void free_menu(); diff --git a/src/object/floating_image.cpp b/src/object/floating_image.cpp index 1933b9bd7..b8fb087bb 100644 --- a/src/object/floating_image.cpp +++ b/src/object/floating_image.cpp @@ -11,15 +11,13 @@ #include "floating_image.hpp" FloatingImage::FloatingImage(const std::string& spritefile) - : sprite(NULL), layer(LAYER_FOREGROUND1 + 1), visible(false), - anchor(ANCHOR_MIDDLE) + : layer(LAYER_FOREGROUND1 + 1), visible(false), anchor(ANCHOR_MIDDLE) { - sprite = sprite_manager->create(spritefile); + sprite.reset(sprite_manager->create(spritefile)); } FloatingImage::~FloatingImage() { - delete sprite; } void diff --git a/src/object/floating_image.hpp b/src/object/floating_image.hpp index 917f3f16c..0f46d9342 100644 --- a/src/object/floating_image.hpp +++ b/src/object/floating_image.hpp @@ -4,6 +4,7 @@ #include "game_object.hpp" #include "math/vector.hpp" #include "anchor_point.hpp" +#include class Sprite; @@ -46,7 +47,7 @@ public: void draw(DrawingContext& context); private: - Sprite* sprite; + std::auto_ptr sprite; int layer; bool visible; AnchorPoint anchor; diff --git a/src/object/player.cpp b/src/object/player.cpp index 659328d0f..176981104 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -122,9 +122,9 @@ void Player::init() { if(is_big()) - bbox.set_size(31.8, 63.8); + bbox.set_size(31.8, 62.8); else - bbox.set_size(31.8, 31.8); + bbox.set_size(31.8, 30.8); adjust_height = 0; dir = RIGHT; @@ -540,7 +540,7 @@ Player::set_bonus(BonusType type, bool animate) return; if(player_status->bonus == NO_BONUS) { - adjust_height = 63.8; + adjust_height = 62.8; if(animate) growing_timer.start(GROWING_TIME); } @@ -849,7 +849,7 @@ Player::kill(HurtMode mode) { //growing_timer.start(GROWING_TIME); safe_timer.start(TUX_SAFE_TIME /* + GROWING_TIME */); - adjust_height = 31.8; + adjust_height = 30.8; duck = false; player_status->bonus = NO_BONUS; } diff --git a/src/options_menu.cpp b/src/options_menu.cpp new file mode 100644 index 000000000..495e0f7f1 --- /dev/null +++ b/src/options_menu.cpp @@ -0,0 +1,103 @@ +// $Id$ +// Copyright (C) 2004 Tobas Glaesser +// +// 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 "options_menu.hpp" +#include "gui/menu.hpp" +#include "audio/sound_manager.hpp" +#include "control/joystickkeyboardcontroller.hpp" +#include "main.hpp" +#include "gettext.hpp" +#include "gameconfig.hpp" + +Menu* options_menu = 0; + +enum OptionsMenuIDs { + MNID_FULLSCREEN, + MNID_SOUND, + MNID_MUSIC +}; + +class OptionsMenu : public Menu +{ +public: + OptionsMenu(); + virtual ~OptionsMenu(); + + virtual void menu_action(MenuItem* item); +}; + +OptionsMenu::OptionsMenu() +{ + add_label(_("Options")); + add_hl(); + add_toggle(MNID_FULLSCREEN,_("Fullscreen"), config->use_fullscreen); + add_toggle(MNID_SOUND, _("Sound"), config->sound_enabled); + add_toggle(MNID_MUSIC, _("Music"), config->music_enabled); + add_submenu(_("Setup Keys"), main_controller->get_key_options_menu()); + add_submenu(_("Setup Joystick"),main_controller->get_joystick_options_menu()); + add_hl(); + add_back(_("Back")); +} + +OptionsMenu::~OptionsMenu() +{ +} + +void +OptionsMenu::menu_action(MenuItem* item) +{ + switch (item->id) { + case MNID_FULLSCREEN: + if(config->use_fullscreen != options_menu->is_toggled(MNID_FULLSCREEN)) { + config->use_fullscreen = !config->use_fullscreen; + init_video(); + config->save(); + } + break; + case MNID_SOUND: + if(config->sound_enabled != options_menu->is_toggled(MNID_SOUND)) { + config->sound_enabled = !config->sound_enabled; + sound_manager->enable_sound(config->sound_enabled); + config->save(); + } + break; + case MNID_MUSIC: + if(config->music_enabled != options_menu->is_toggled(MNID_MUSIC)) { + config->music_enabled = !config->music_enabled; + sound_manager->enable_music(config->music_enabled); + config->save(); + } + break; + default: + break; + } +} + +Menu* get_options_menu() +{ + if(options_menu == NULL) + options_menu = new OptionsMenu(); + + return options_menu; +} + +void free_options_menu() +{ + delete options_menu; + options_menu = NULL; +} diff --git a/src/options_menu.hpp b/src/options_menu.hpp new file mode 100644 index 000000000..5a11e8eb6 --- /dev/null +++ b/src/options_menu.hpp @@ -0,0 +1,24 @@ +// $Id$ +// Copyright (C) 2004 Tobas Glaesser +// +// 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 __OPTIONS_MENU_HPP__ +#define __OPTIONS_MENU_HPP__ + +class Menu; +Menu* get_options_menu(); +void free_options_menu(); + +#endif diff --git a/src/resources.cpp b/src/resources.cpp index b5615782f..fdb043f5b 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -112,41 +112,29 @@ 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/resources.hpp b/src/resources.hpp index 811ff53a0..9885ef796 100644 --- a/src/resources.hpp +++ b/src/resources.hpp @@ -32,7 +32,6 @@ extern TileManager* tile_manager; extern Menu* main_menu; extern Menu* game_menu; -extern Menu* options_menu; extern MouseCursor* mouse_cursor; diff --git a/src/script_manager.cpp b/src/script_manager.cpp index d0656a57d..2cd084238 100644 --- a/src/script_manager.cpp +++ b/src/script_manager.cpp @@ -25,10 +25,8 @@ #include #include #include -#include #include #include -#include #include #include @@ -41,7 +39,7 @@ using namespace Scripting; -ScriptManager* script_manager = 0; +ScriptManager* ScriptManager::instance = NULL; static void printfunc(HSQUIRRELVM, const char* str, ...) { @@ -54,60 +52,75 @@ static void printfunc(HSQUIRRELVM, const char* str, ...) } ScriptManager::ScriptManager() + : parent(NULL) { - v = sq_open(1024); - if(v == 0) + vm = sq_open(1024); + if(vm == 0) throw std::runtime_error("Couldn't initialize squirrel vm"); + sq_setforeignptr(vm, (SQUserPointer) this); - // 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"); + sq_pushroottable(vm); + if(sqstd_register_bloblib(vm) < 0) + throw SquirrelError(vm, "Couldn't register blob lib"); + if(sqstd_register_mathlib(vm) < 0) + throw SquirrelError(vm, "Couldn't register math lib"); + if(sqstd_register_stringlib(vm) < 0) + throw SquirrelError(vm, "Couldn't register string lib"); + // register supertux API + register_supertux_wrapper(vm); + sq_pop(vm, 1); // register print function - sq_setprintfunc(v, printfunc); - - // register supertux API - register_supertux_wrapper(v); + sq_setprintfunc(vm, printfunc); + // register default error handlers + sqstd_seterrorhandlers(vm); } -ScriptManager::~ScriptManager() +ScriptManager::ScriptManager(ScriptManager* parent) { - for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i) - sq_release(v, &(i->vm_obj)); + this->parent = parent; + vm = parent->vm; + parent->childs.push_back(this); +} - sq_close(v); +ScriptManager::~ScriptManager() +{ + for(SquirrelVMs::iterator i = squirrel_vms.begin(); + i != squirrel_vms.end(); ++i) + sq_release(vm, &(i->vm_obj)); + + if(parent != NULL) { + parent->childs.erase( + std::remove(parent->childs.begin(), parent->childs.end(), this), + parent->childs.end()); + } else { + sq_close(vm); + } } HSQUIRRELVM -ScriptManager::create_thread() +ScriptManager::create_thread(bool leave_thread_on_stack) { - HSQUIRRELVM vm = sq_newthread(v, 1024); - if(vm == NULL) - throw SquirrelError(v, "Couldn't create new VM"); + HSQUIRRELVM new_vm = sq_newthread(vm, 1024); + if(new_vm == NULL) + throw SquirrelError(vm, "Couldn't create new VM"); + sq_setforeignptr(new_vm, (SQUserPointer) this); // 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"); + if(SQ_FAILED(sq_getstackobj(vm, -1, &vm_obj))) { + throw SquirrelError(vm, "Couldn't get coroutine vm from stack"); } - sq_addref(v, &vm_obj); - sq_pop(v, 1); + sq_addref(vm, &vm_obj); + + if(!leave_thread_on_stack) + sq_pop(vm, 1); - squirrel_vms.push_back(SquirrelVM(vm, vm_obj)); + squirrel_vms.push_back(SquirrelVM(new_vm, vm_obj)); - return vm; + return new_vm; } void @@ -125,14 +138,14 @@ ScriptManager::update() } } catch(std::exception& e) { std::cerr << "Problem executing script: " << e.what() << "\n"; - sq_release(v, &squirrel_vm.vm_obj); + sq_release(vm, &squirrel_vm.vm_obj); i = squirrel_vms.erase(i); continue; } } if (vm_state != SQ_VMSTATE_SUSPENDED) { - sq_release(v, &(squirrel_vm.vm_obj)); + sq_release(vm, &(squirrel_vm.vm_obj)); i = squirrel_vms.erase(i); } else { ++i; @@ -145,7 +158,8 @@ 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) { + for(SquirrelVMs::iterator i = squirrel_vms.begin(); + i != squirrel_vms.end(); ++i) { SquirrelVM& squirrel_vm = *i; if(squirrel_vm.vm == vm) { @@ -165,15 +179,21 @@ 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; - } + 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; } + } + + for(std::vector::iterator i = childs.begin(); + i != childs.end(); ++i) { + ScriptManager* child = *i; + child->fire_wakeup_event(event); + } } void diff --git a/src/script_manager.hpp b/src/script_manager.hpp index bbcbbf1b7..90906c85e 100644 --- a/src/script_manager.hpp +++ b/src/script_manager.hpp @@ -37,6 +37,7 @@ class ScriptManager { public: ScriptManager(); + ScriptManager(ScriptManager* parent); ~ScriptManager(); void update(); @@ -45,11 +46,11 @@ public: * Creates a new thread and registers it with the script manager * (so it can suspend and register for wakeup events) */ - HSQUIRRELVM create_thread(); + HSQUIRRELVM create_thread(bool leave_thread_on_stack = false); - HSQUIRRELVM get_global_vm() const + HSQUIRRELVM get_vm() const { - return v; + return vm; } enum WakeupEvent { @@ -75,6 +76,9 @@ public: void set_wakeup_event(HSQUIRRELVM vm, WakeupData event, float timeout = -1); void fire_wakeup_event(WakeupEvent event); void fire_wakeup_event(WakeupData event); + + // global (root) instance of the ScriptManager + static ScriptManager* instance; private: class SquirrelVM @@ -91,10 +95,10 @@ private: typedef std::list SquirrelVMs; SquirrelVMs squirrel_vms; - HSQUIRRELVM v; + HSQUIRRELVM vm; + ScriptManager* parent; + std::vector childs; }; -extern ScriptManager* script_manager; - #endif diff --git a/src/scripting/floating_image.cpp b/src/scripting/floating_image.cpp index bfb7db95e..113935835 100644 --- a/src/scripting/floating_image.cpp +++ b/src/scripting/floating_image.cpp @@ -9,6 +9,7 @@ namespace Scripting FloatingImage::FloatingImage(const std::string& spritefile) { + assert(Sector::current() != NULL); floating_image = new _FloatingImage(spritefile); Sector::current()->add_object(floating_image); } diff --git a/src/scripting/functions.cpp b/src/scripting/functions.cpp index 21712a647..c3a4bf89d 100644 --- a/src/scripting/functions.cpp +++ b/src/scripting/functions.cpp @@ -50,11 +50,15 @@ int display(HSQUIRRELVM vm) void wait(HSQUIRRELVM vm, float seconds) { + SQUserPointer ptr = sq_getforeignptr(vm); + ScriptManager* script_manager = reinterpret_cast (ptr); script_manager->set_wakeup_event(vm, ScriptManager::TIME, seconds); } void wait_for_screenswitch(HSQUIRRELVM vm) { + SQUserPointer ptr = sq_getforeignptr(vm); + ScriptManager* script_manager = reinterpret_cast (ptr); script_manager->set_wakeup_event(vm, ScriptManager::SCREEN_SWITCHED); } diff --git a/src/scripting/wrapper.cpp b/src/scripting/wrapper.cpp index b31ccceff..532ad14a7 100644 --- a/src/scripting/wrapper.cpp +++ b/src/scripting/wrapper.cpp @@ -1822,7 +1822,6 @@ void register_supertux_wrapper(HSQUIRRELVM v) { using namespace Wrapper; - sq_pushroottable(v); sq_pushstring(v, "KEY_BRASS", -1); sq_pushinteger(v, 1); if(SQ_FAILED(sq_createslot(v, -3))) { @@ -2343,7 +2342,6 @@ void register_supertux_wrapper(HSQUIRRELVM v) throw SquirrelError(v, "Couldn't register class 'FloatingImage'"); } - sq_pop(v, 1); } } // end of namespace Scripting diff --git a/src/sector.cpp b/src/sector.cpp index a710145e0..69571e106 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -76,13 +76,13 @@ Sector::Sector() add_object(new TextObject()); #ifdef USE_GRID - grid = new CollisionGrid(32000, 32000); -#else - grid = 0; + grid.reset(new CollisionGrid(32000, 32000)); #endif + script_manager.reset(new ScriptManager(ScriptManager::instance)); + // create a new squirrel table for the sector - HSQUIRRELVM vm = script_manager->get_global_vm(); + HSQUIRRELVM vm = ScriptManager::instance->get_vm(); sq_newtable(vm); sq_pushroottable(vm); @@ -98,13 +98,14 @@ Sector::Sector() Sector::~Sector() { + deactivate(); + + script_manager.reset(NULL); + sq_release(ScriptManager::instance->get_vm(), §or_table); + 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); @@ -114,8 +115,6 @@ Sector::~Sector() for(SpawnPoints::iterator i = spawnpoints.begin(); i != spawnpoints.end(); ++i) delete *i; - - sq_release(script_manager->get_global_vm(), §or_table); } GameObject* @@ -390,9 +389,13 @@ Sector::write(lisp::Writer& writer) HSQUIRRELVM Sector::run_script(std::istream& in, const std::string& sourcename) { + // create new thread and keep a weakref HSQUIRRELVM vm = script_manager->create_thread(); + + // set sector_table as roottable for the thread sq_pushobject(vm, sector_table); sq_setroottable(vm); + Scripting::compile_and_run(vm, in, sourcename); return vm; @@ -452,12 +455,12 @@ Sector::activate(const Vector& player_pos) _current = this; // register sectortable as current_sector in scripting - HSQUIRRELVM vm = script_manager->get_global_vm(); + HSQUIRRELVM vm = ScriptManager::instance->get_vm(); sq_pushroottable(vm); - sq_pushstring(vm, "current_sector", -1); + sq_pushstring(vm, "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"); + throw Scripting::SquirrelError(vm, "Couldn't set sector in roottable"); sq_pop(vm, 1); for(GameObjects::iterator i = gameobjects.begin(); @@ -484,11 +487,12 @@ Sector::deactivate() if(_current != this) return; - HSQUIRRELVM vm = script_manager->get_global_vm(); + // remove sector entry from global vm + HSQUIRRELVM vm = ScriptManager::instance->get_vm(); sq_pushroottable(vm); - sq_pushstring(vm, "current_sector", -1); + sq_pushstring(vm, "sector", -1); if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse))) - throw Scripting::SquirrelError(vm, "Couldn't unset current_sector in roottable"); + throw Scripting::SquirrelError(vm, "Couldn't unset sector in roottable"); sq_pop(vm, 1); for(GameObjects::iterator i = gameobjects.begin(); @@ -512,6 +516,8 @@ Sector::get_active_region() void Sector::update(float elapsed_time) { + script_manager->update(); + player->check_bounds(camera); #if 0 @@ -649,7 +655,7 @@ Sector::try_expose(GameObject* object) { ScriptInterface* interface = dynamic_cast (object); if(interface != NULL) { - HSQUIRRELVM vm = script_manager->get_global_vm(); + HSQUIRRELVM vm = script_manager->get_vm(); sq_pushobject(vm, sector_table); interface->expose(vm, -1); sq_pop(vm, 1); @@ -668,7 +674,7 @@ Sector::try_unexpose(GameObject* object) { ScriptInterface* interface = dynamic_cast (object); if(interface != NULL) { - HSQUIRRELVM vm = script_manager->get_global_vm(); + HSQUIRRELVM vm = script_manager->get_vm(); sq_pushobject(vm, sector_table); interface->unexpose(vm, -1); sq_pop(vm, 1); diff --git a/src/sector.hpp b/src/sector.hpp index 80ed7340a..67efe384e 100644 --- a/src/sector.hpp +++ b/src/sector.hpp @@ -21,9 +21,11 @@ #include #include +#include #include #include "direction.hpp" +#include "script_manager.hpp" #include "math/vector.hpp" #include "video/drawing_context.hpp" @@ -50,8 +52,9 @@ enum MusicType { HERRING_MUSIC }; -/** This class holds a sector (a part of a level) and all the game objects - * (badguys, player, background, tilemap, ...) +/** + * This class holds a sector (a part of a level) and all the game objects in + * the sector */ class Sector { @@ -160,9 +163,11 @@ private: MusicType currentmusic; - CollisionGrid* grid; + std::auto_ptr grid; HSQOBJECT sector_table; + /// sector scripts + std::auto_ptr script_manager; public: // TODO make this private again GameObjects gameobjects; diff --git a/src/title.cpp b/src/title.cpp index d2ed7daf0..1d1111436 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -163,6 +163,8 @@ TitleScreen::check_levels_contrib_menu() if(!world.is_levelset) { // TODO fade out world.run(); + world.set_savegame_filename("save/test.save"); + world.save(); } if (current_world != index) { @@ -265,16 +267,8 @@ TitleScreen::TitleScreen() controller.reset(new CodeController()); titlesession.reset(new GameSession("levels/misc/menu.stl", ST_GL_DEMO_GAME)); - // delete contrib_world_menu; - // contrib_world_menu = new Menu(); - - titlesession->get_current_sector()->activate("main"); - titlesession->set_current(); - Player* player = titlesession->get_current_sector()->player; player->set_controller(controller.get()); - - Menu::set_current(main_menu); } TitleScreen::~TitleScreen() @@ -287,8 +281,10 @@ TitleScreen::setup() player_status->reset(); Sector* sector = titlesession->get_current_sector(); - sector->play_music(LEVEL_MUSIC); - sector->activate(sector->player->get_pos()); + if(Sector::current() != sector) { + sector->play_music(LEVEL_MUSIC); + sector->activate(sector->player->get_pos()); + } Menu::set_current(main_menu); } @@ -357,8 +353,6 @@ TitleScreen::update(float elapsed_time) main_loop->quit(); break; } - } else if(menu == options_menu) { - process_options_menu(); } else if(menu == load_game_menu.get()) { /* if(event.key.keysym.sym == SDLK_DELETE) { diff --git a/src/world.cpp b/src/world.cpp index 71d60cfbd..bdd4407e7 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -30,6 +30,7 @@ #include "physfs/physfs_stream.hpp" #include "script_manager.hpp" #include "scripting/wrapper_util.hpp" +#include "scripting/serialize.hpp" #include "msg.hpp" static bool has_suffix(const std::string& data, const std::string& suffix) @@ -51,6 +52,12 @@ World::~World() } void +World::set_savegame_filename(const std::string& filename) +{ + this->savegame_filename = filename; +} + +void World::load(const std::string& filename) { basedir = FileSystem::dirname(filename); @@ -94,15 +101,47 @@ World::load(const std::string& filename) void World::run() { + // create new squirrel table for persisten game state + HSQUIRRELVM vm = ScriptManager::instance->get_vm(); + + sq_pushroottable(vm); + sq_pushstring(vm, "state", -1); + sq_newtable(vm); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't create state table"); + sq_pop(vm, 1); + std::string filename = basedir + "/world.nut"; - std::cout << filename << std::endl; - if (!PHYSFS_exists(filename.c_str())) - return; - IFileStream in(filename); - HSQUIRRELVM vm = script_manager->create_thread(); - Scripting::compile_and_run(vm, in, filename); + HSQUIRRELVM new_vm = ScriptManager::instance->create_thread(); + Scripting::compile_and_run(new_vm, in, filename); +} + +void +World::save() +{ + lisp::Writer writer(savegame_filename); + + writer.start_list("supertux-savegame"); + writer.write_int("version", 1); + + writer.start_list("tux"); + player_status->write(writer); + writer.end_list("tux"); + + writer.start_list("state"); + HSQUIRRELVM vm = ScriptManager::instance->get_vm(); + sq_pushroottable(vm); + sq_pushstring(vm, "state", -1); + if(SQ_SUCCEEDED(sq_get(vm, -2))) { + Scripting::save_squirrel_table(vm, -1, writer); + sq_pop(vm, 1); + } + sq_pop(vm, 1); + writer.end_list("state"); + + writer.end_list("supertux-savegame"); } const std::string& diff --git a/src/world.hpp b/src/world.hpp index 12e775951..60ec26bd3 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -1,7 +1,7 @@ -// $Id: worldmap.hpp 2800 2005-10-02 22:57:31Z matzebraun $ +// $Id$ // // SuperTux -// Copyright (C) 2004 Ingo Ruhnke +// Copyright (C) 2006 Matthias Braun // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -21,18 +21,26 @@ #include #include +#include class World { private: std::vector levels; std::string basedir; + std::string savegame_filename; + /// squirrel table that saves persistent state (about the world) + HSQOBJECT state_table; public: World(); ~World(); + void set_savegame_filename(const std::string& filename); void load(const std::string& filename); + + void save(); + void load(); const std::string& get_level_filename(unsigned int i) const; unsigned int get_num_levels() const; diff --git a/src/worldmap.cpp b/src/worldmap.cpp index 3a080672b..209ea1473 100644 --- a/src/worldmap.cpp +++ b/src/worldmap.cpp @@ -748,8 +748,6 @@ WorldMap::update(float delta) main_loop->exit_screen(); break; } - } else if(menu == options_menu) { - process_options_menu(); } return; diff --git a/tools/miniswig/create_wrapper.cpp b/tools/miniswig/create_wrapper.cpp index d0c913192..e072b6fe3 100644 --- a/tools/miniswig/create_wrapper.cpp +++ b/tools/miniswig/create_wrapper.cpp @@ -100,15 +100,13 @@ WrapperCreator::create_wrapper(Namespace* ns) out << "void register_" << modulename << "_wrapper(HSQUIRRELVM v)\n" << "{\n" << ind << "using namespace Wrapper;\n" - << "\n" - << ind << "sq_pushroottable(v);\n"; + << "\n"; create_register_constants_code(ns); create_register_functions_code(ns); create_register_classes_code(ns); - out << ind << "sq_pop(v, 1);\n" - << "}\n" + out << "}\n" << "\n" << "} // end of namespace Scripting\n" << "\n";