1 // $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $
4 // Copyright (C) 2005 Matthias Braun <matze@braunis.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 #include "script_manager.hpp"
30 #include <sqstdblob.h>
31 #include <sqstdsystem.h>
32 #include <sqstdmath.h>
33 #include <sqstdstring.h>
36 #include "console.hpp"
37 #include "scripting/wrapper.hpp"
38 #include "scripting/wrapper_util.hpp"
39 #include "scripting/squirrel_error.hpp"
40 #include "physfs/physfs_stream.hpp"
42 using namespace Scripting;
44 ScriptManager* script_manager = 0;
46 static void printfunc(HSQUIRRELVM, const char* str, ...)
50 va_start(arglist, str);
51 vsprintf(buf, str, arglist);
52 Console::output << (const char*) buf << std::flush;
56 ScriptManager::ScriptManager()
60 throw std::runtime_error("Couldn't initialize squirrel vm");
62 // register default error handlers
63 sqstd_seterrorhandlers(v);
64 // register squirrel libs
66 if(sqstd_register_bloblib(v) < 0)
67 throw SquirrelError(v, "Couldn't register blob lib");
68 if(sqstd_register_iolib(v) < 0)
69 throw SquirrelError(v, "Couldn't register io lib");
70 if(sqstd_register_systemlib(v) < 0)
71 throw SquirrelError(v, "Couldn't register system lib");
72 if(sqstd_register_mathlib(v) < 0)
73 throw SquirrelError(v, "Couldn't register math lib");
74 if(sqstd_register_stringlib(v) < 0)
75 throw SquirrelError(v, "Couldn't register string lib");
77 // register print function
78 sq_setprintfunc(v, printfunc);
80 // register supertux API
81 register_supertux_wrapper(v);
84 ScriptManager::~ScriptManager()
86 for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i)
87 sq_release(v, &(i->vm_obj));
93 ScriptManager::create_thread()
95 HSQUIRRELVM vm = sq_newthread(v, 1024);
97 throw SquirrelError(v, "Couldn't create new VM");
99 // retrieve reference to thread from stack and increase refcounter
101 sq_resetobject(&vm_obj);
102 if(SQ_FAILED(sq_getstackobj(v, -1, &vm_obj))) {
103 throw SquirrelError(v, "Couldn't get coroutine vm from stack");
105 sq_addref(v, &vm_obj);
108 squirrel_vms.push_back(SquirrelVM(vm, vm_obj));
114 ScriptManager::update()
116 for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ) {
117 SquirrelVM& squirrel_vm = *i;
118 int vm_state = sq_getvmstate(squirrel_vm.vm);
120 if(vm_state == SQ_VMSTATE_SUSPENDED && squirrel_vm.wakeup_time > 0 && game_time >= squirrel_vm.wakeup_time) {
121 squirrel_vm.waiting_for_events = WakeupData(NO_EVENT);
123 if(SQ_FAILED(sq_wakeupvm(squirrel_vm.vm, false, false))) {
124 throw SquirrelError(squirrel_vm.vm, "Couldn't resume script");
126 } catch(std::exception& e) {
127 std::cerr << "Problem executing script: " << e.what() << "\n";
128 sq_release(v, &squirrel_vm.vm_obj);
129 i = squirrel_vms.erase(i);
134 if (vm_state != SQ_VMSTATE_SUSPENDED) {
135 sq_release(v, &(squirrel_vm.vm_obj));
136 i = squirrel_vms.erase(i);
144 ScriptManager::set_wakeup_event(HSQUIRRELVM vm, WakeupData event, float timeout)
146 assert(event.type >= 0 && event.type < WAKEUP_EVENT_COUNT);
147 // find the VM in the list and update it
148 for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i) {
149 SquirrelVM& squirrel_vm = *i;
150 if(squirrel_vm.vm == vm)
152 squirrel_vm.waiting_for_events = event;
155 squirrel_vm.wakeup_time = -1;
157 squirrel_vm.wakeup_time = game_time + timeout;
165 ScriptManager::fire_wakeup_event(WakeupData event)
167 assert(event.type >= 0 && event.type < WAKEUP_EVENT_COUNT);
168 for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i)
171 if(vm.waiting_for_events.type == event.type && vm.waiting_for_events.type != NO_EVENT)
173 vm.wakeup_time = game_time;
180 ScriptManager::set_wakeup_event(HSQUIRRELVM vm, WakeupEvent event, float timeout)
182 set_wakeup_event(vm, WakeupData(event), timeout);
186 ScriptManager::fire_wakeup_event(WakeupEvent event)
188 fire_wakeup_event(WakeupData(event));
191 ScriptManager::SquirrelVM::SquirrelVM(HSQUIRRELVM arg_vm, HSQOBJECT arg_obj)
192 : vm(arg_vm), vm_obj(arg_obj)
194 waiting_for_events = WakeupData(NO_EVENT);