X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fscripting%2Fscript_interpreter.cpp;h=1047ed7f7761093678c96e6add3ceec8dc780729;hb=85a02e771388b133940b45e29768e697a29c1a36;hp=095c6afca5850f410dacf10b8992864a5deb2665;hpb=523d415707de9f777729534f467779d4c5acdf6e;p=supertux.git diff --git a/src/scripting/script_interpreter.cpp b/src/scripting/script_interpreter.cpp index 095c6afca..1047ed7f7 100644 --- a/src/scripting/script_interpreter.cpp +++ b/src/scripting/script_interpreter.cpp @@ -1,10 +1,11 @@ #include -#include "script_interpreter.h" +#include "script_interpreter.hpp" #include #include #include +#include #include #include #include @@ -12,15 +13,21 @@ #include #include -#include "wrapper.h" -#include "wrapper_util.h" -#include "sector.h" -#include "object/text_object.h" -#include "object/scripted_object.h" -#include "object/display_effect.h" -#include "scripting/sound.h" -#include "scripting/scripted_object.h" -#include "scripting/display_effect.h" +#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, ...) { @@ -32,8 +39,8 @@ static void printfunc(HSQUIRRELVM, const char* str, ...) ScriptInterpreter* ScriptInterpreter::_current = 0; -ScriptInterpreter::ScriptInterpreter(Sector* sector) - : sound(0), level(0) +ScriptInterpreter::ScriptInterpreter(const std::string& new_working_directory) + : working_directory(new_working_directory), sound(0), level(0) { v = sq_open(1024); if(v == 0) @@ -44,23 +51,33 @@ ScriptInterpreter::ScriptInterpreter(Sector* sector) // register squirrel libs sq_pushroottable(v); if(sqstd_register_bloblib(v) < 0) - throw SquirrelError(v, "Couldn't register blob lib"); + throw Scripting::SquirrelError(v, "Couldn't register blob lib"); if(sqstd_register_iolib(v) < 0) - throw SquirrelError(v, "Couldn't register io lib"); + throw Scripting::SquirrelError(v, "Couldn't register io lib"); if(sqstd_register_systemlib(v) < 0) - throw SquirrelError(v, "Couldn't register system lib"); + throw Scripting::SquirrelError(v, "Couldn't register system lib"); if(sqstd_register_mathlib(v) < 0) - throw SquirrelError(v, "Couldn't register math lib"); + throw Scripting::SquirrelError(v, "Couldn't register math lib"); if(sqstd_register_stringlib(v) < 0) - throw SquirrelError(v, "Couldn't register string lib"); + throw Scripting::SquirrelError(v, "Couldn't register string lib"); // register print function sq_setprintfunc(v, printfunc); // register supertux API - register_functions(v, supertux_global_functions); - register_classes(v, supertux_classes); + 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) { @@ -70,26 +87,20 @@ ScriptInterpreter::ScriptInterpreter(Sector* sector) if(!scripted_object) continue; - expose_object(scripted_object, scripted_object->get_name(), - "ScriptedObject"); + expose_object(scripted_object, scripted_object->get_name()); } - // expose some "global" objects - sound = new Scripting::Sound(); - expose_object(sound, "Sound", "Sound"); - - level = new Scripting::Level(); - expose_object(level, "Level", "Level"); + 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", "Text"); + 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", "DisplayEffect"); + expose_object(display_effect_api, "DisplayEffect"); } ScriptInterpreter::~ScriptInterpreter() @@ -108,59 +119,25 @@ static SQInteger squirrel_read_char(SQUserPointer file) return c; } - void -ScriptInterpreter::load_script(std::istream& in, const std::string& sourcename) +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 SquirrelError(v, "Couldn't parse script"); -} - -void -ScriptInterpreter::start_script() -{ + throw Scripting::SquirrelError(v, "Couldn't parse script"); + _current = this; sq_push(v, -2); if(sq_call(v, 1, false) < 0) - throw SquirrelError(v, "Couldn't start script"); + throw Scripting::SquirrelError(v, "Couldn't start script"); _current = 0; if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) { - printf("script ended...\n"); - remove_me(); - } -} - -void -ScriptInterpreter::expose_object(void* object, const std::string& name, - const std::string& type) -{ - // part1 of registration of the instance in the root table - sq_pushroottable(v); - sq_pushstring(v, name.c_str(), -1); - - // resolve class name - sq_pushroottable(v); - sq_pushstring(v, type.c_str(), -1); - if(sq_get(v, -2) < 0) { - std::ostringstream msg; - msg << "Couldn't resolve squirrel type '" << type << "'."; - throw std::runtime_error(msg.str()); - } - sq_remove(v, -2); // remove roottable - - // create an instance and set pointer to c++ object - if(sq_createinstance(v, -1) < 0 || sq_setinstanceup(v, -1, object)) { - std::ostringstream msg; - msg << "Couldn't setup squirrel instance for object '" - << name << "' of type '" << type << "'."; - throw SquirrelError(v, msg.str()); + if(remove_when_terminated) { + remove_me(); + } + // remove closure from stack + sq_pop(v, 1); } - - sq_remove(v, -2); // remove class from stack - - // part2 of registration of the instance in the root table - if(sq_createslot(v, -3) < 0) - throw SquirrelError(v, "Couldn't register object in squirrel root table"); sq_pop(v, 1); } void @@ -177,7 +154,7 @@ ScriptInterpreter::update(float ) _current = this; if(sq_wakeupvm(v, false, false) < 0) - throw SquirrelError(v, "Couldn't resume script"); + throw Scripting::SquirrelError(v, "Couldn't resume script"); _current = 0; if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) { printf("script ended...\n"); @@ -189,3 +166,41 @@ 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) { + std::cerr << "Couldn't start '" << name << "' script: " << e.what() << "\n"; + } +} +