X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fscripting%2Fsquirrel_util.cpp;h=a5b1c1dda9d9c5dfccd1fde941ecaacfe68186ca;hb=d0d4f2a10842e956e90af678e8270fec96536164;hp=f9cb64835775a2c9c5ce3390f21b1553848e687f;hpb=c62711567861587107d124642db29e2674ee6533;p=supertux.git diff --git a/src/scripting/squirrel_util.cpp b/src/scripting/squirrel_util.cpp index f9cb64835..a5b1c1dda 100644 --- a/src/scripting/squirrel_util.cpp +++ b/src/scripting/squirrel_util.cpp @@ -31,6 +31,7 @@ #include "log.hpp" #include "level.hpp" #include "physfs/physfs_stream.hpp" +#include "random_generator.hpp" #ifdef ENABLE_SQDBG #include @@ -59,34 +60,41 @@ void init_squirrel(bool enable_debugger) if(global_vm == NULL) throw std::runtime_error("Couldn't initialize squirrel vm"); -#ifdef ENABLE_SQDBG if(enable_debugger) { +#ifdef ENABLE_SQDBG sq_enabledebuginfo(global_vm, SQTrue); debugger = sq_rdbg_init(global_vm, 1234, SQFalse); if(debugger == NULL) throw SquirrelError(global_vm, "Couldn't initialize squirrel debugger"); - + sq_enabledebuginfo(global_vm, SQTrue); log_info << "Waiting for debug client..." << std::endl; if(SQ_FAILED(sq_rdbg_waitforconnections(debugger))) throw SquirrelError(global_vm, "Waiting for debug clients failed"); log_info << "debug client connected." << std::endl; - } #endif + } sq_pushroottable(global_vm); - if(sqstd_register_bloblib(global_vm) < 0) + if(SQ_FAILED(sqstd_register_bloblib(global_vm))) throw SquirrelError(global_vm, "Couldn't register blob lib"); - if(sqstd_register_mathlib(global_vm) < 0) + if(SQ_FAILED(sqstd_register_mathlib(global_vm))) throw SquirrelError(global_vm, "Couldn't register math lib"); - if(sqstd_register_stringlib(global_vm) < 0) + if(SQ_FAILED(sqstd_register_stringlib(global_vm))) throw SquirrelError(global_vm, "Couldn't register string lib"); + + // remove rand and srand calls from sqstdmath, we'll provide our own + sq_pushstring(global_vm, "srand", -1); + sq_deleteslot(global_vm, -2, SQFalse); + sq_pushstring(global_vm, "rand", -1); + sq_deleteslot(global_vm, -2, SQFalse); + // register supertux API register_supertux_wrapper(global_vm); - // TODO remove this at some point... it shoud just be functions not an object + // TODO remove this at some point... it should just be functions not an object expose_object(global_vm, -1, new Scripting::Level(), "Level", true); - + sq_pop(global_vm, 1); // register print function @@ -112,7 +120,10 @@ void exit_squirrel() debugger = NULL; } #endif - sq_close(global_vm); + + if (global_vm) + sq_close(global_vm); + global_vm = NULL; } @@ -124,40 +135,40 @@ void update_debugger() #endif } -std::string squirrel2string(HSQUIRRELVM v, int i) +std::string squirrel2string(HSQUIRRELVM v, SQInteger i) { std::ostringstream os; switch(sq_gettype(v, i)) { case OT_NULL: - os << ""; + os << ""; break; case OT_BOOL: { SQBool p; sq_getbool(v, i, &p); - if (p) + if (p) os << "true"; else os << "false"; break; } case OT_INTEGER: { - int val; + SQInteger val; sq_getinteger(v, i, &val); os << val; break; } case OT_FLOAT: { - float val; + SQFloat val; sq_getfloat(v, i, &val); os << val; break; } case OT_STRING: { - const char* val; + const SQChar* val; sq_getstring(v, i, &val); os << "\"" << val << "\""; - break; + break; } case OT_TABLE: { bool first = true; @@ -171,9 +182,9 @@ std::string squirrel2string(HSQUIRRELVM v, int i) first = false; //here -1 is the value and -2 is the key - os << squirrel2string(v, -2) << " => " + os << squirrel2string(v, -2) << " => " << squirrel2string(v, -1); - + sq_pop(v,2); //pops key and val before the nex iteration } sq_pop(v, 1); @@ -194,7 +205,7 @@ std::string squirrel2string(HSQUIRRELVM v, int i) //here -1 is the value and -2 is the key // we ignore the key, since that is just the index in an array os << squirrel2string(v, -1); - + sq_pop(v,2); //pops key and val before the nex iteration } sq_pop(v, 1); @@ -204,7 +215,7 @@ std::string squirrel2string(HSQUIRRELVM v, int i) case OT_USERDATA: os << ""; break; - case OT_CLOSURE: + case OT_CLOSURE: os << ""; break; case OT_NATIVECLOSURE: @@ -244,25 +255,25 @@ void print_squirrel_stack(HSQUIRRELVM v) switch(sq_gettype(v, i)) { case OT_NULL: - printf("null"); + printf("null"); break; case OT_INTEGER: { - int val; + SQInteger val; sq_getinteger(v, i, &val); - printf("integer (%d)", val); + printf("integer (%d)", static_cast (val)); break; } case OT_FLOAT: { - float val; + SQFloat val; sq_getfloat(v, i, &val); printf("float (%f)", val); break; } case OT_STRING: { - const char* val; + const SQChar* val; sq_getstring(v, i, &val); printf("string (%s)", val); - break; + break; } case OT_TABLE: printf("table"); @@ -273,8 +284,8 @@ void print_squirrel_stack(HSQUIRRELVM v) case OT_USERDATA: printf("userdata"); break; - case OT_CLOSURE: - printf("closure(function)"); + case OT_CLOSURE: + printf("closure(function)"); break; case OT_NATIVECLOSURE: printf("native closure(C function)"); @@ -318,15 +329,15 @@ static SQInteger squirrel_read_char(SQUserPointer file) 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"); + 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); + + SQInteger oldtop = sq_gettop(vm); try { sq_pushroottable(vm); @@ -354,7 +365,7 @@ HSQOBJECT create_thread(HSQUIRRELVM vm) if(SQ_FAILED(sq_getstackobj(vm, -1, &vm_object))) throw SquirrelError(vm, "Couldn't get squirrel thread from stack"); sq_addref(vm, &vm_object); - + sq_pop(vm, 1); return vm_object; @@ -378,4 +389,168 @@ HSQUIRRELVM object_to_vm(HSQOBJECT object) return object._unVal.pThread; } +// begin: serialization functions + +void store_float(HSQUIRRELVM vm, const char* name, float val) +{ + sq_pushstring(vm, name, -1); + sq_pushfloat(vm, val); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); +} + +void store_int(HSQUIRRELVM vm, const char* name, int val) +{ + sq_pushstring(vm, name, -1); + sq_pushinteger(vm, val); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't add int value to table"); +} + +void store_string(HSQUIRRELVM vm, const char* name, const std::string& val) +{ + sq_pushstring(vm, name, -1); + sq_pushstring(vm, val.c_str(), val.length()); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); +} + +void store_bool(HSQUIRRELVM vm, const char* name, bool val) +{ + sq_pushstring(vm, name, -1); + sq_pushbool(vm, val ? SQTrue : SQFalse); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw Scripting::SquirrelError(vm, "Couldn't add float value to table"); +} + +bool has_float(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if (SQ_FAILED(sq_get(vm, -2))) return false; + sq_pop(vm, 1); + return true; +} + +bool has_int(HSQUIRRELVM vm, const char* name) +{ + return has_float(vm, name); +} + +bool has_string(HSQUIRRELVM vm, const char* name) +{ + return has_float(vm, name); +} + +bool has_bool(HSQUIRRELVM vm, const char* name) +{ + return has_float(vm, name); +} + +float read_float(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if(SQ_FAILED(sq_get(vm, -2))) { + std::ostringstream msg; + msg << "Couldn't get float value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + + float result; + if(SQ_FAILED(sq_getfloat(vm, -1, &result))) { + std::ostringstream msg; + msg << "Couldn't get float value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + sq_pop(vm, 1); + + return result; +} + +int read_int(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if(SQ_FAILED(sq_get(vm, -2))) { + std::ostringstream msg; + msg << "Couldn't get int value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + + SQInteger result; + if(SQ_FAILED(sq_getinteger(vm, -1, &result))) { + std::ostringstream msg; + msg << "Couldn't get int value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + sq_pop(vm, 1); + + return result; +} + + +std::string read_string(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if(SQ_FAILED(sq_get(vm, -2))) { + std::ostringstream msg; + msg << "Couldn't get string value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + + const char* result; + if(SQ_FAILED(sq_getstring(vm, -1, &result))) { + std::ostringstream msg; + msg << "Couldn't get string value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + sq_pop(vm, 1); + + return std::string(result); +} + +bool read_bool(HSQUIRRELVM vm, const char* name) +{ + sq_pushstring(vm, name, -1); + if(SQ_FAILED(sq_get(vm, -2))) { + std::ostringstream msg; + msg << "Couldn't get bool value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + + SQBool result; + if(SQ_FAILED(sq_getbool(vm, -1, &result))) { + std::ostringstream msg; + msg << "Couldn't get bool value for '" << name << "' from table"; + throw Scripting::SquirrelError(vm, msg.str()); + } + sq_pop(vm, 1); + + return result == SQTrue; +} + +bool get_float(HSQUIRRELVM vm, const char* name, float& val) { + if (!has_float(vm, name)) return false; + val = read_float(vm, name); + return true; +} + +bool get_int(HSQUIRRELVM vm, const char* name, int& val) { + if (!has_int(vm, name)) return false; + val = read_int(vm, name); + return true; +} + +bool get_string(HSQUIRRELVM vm, const char* name, std::string& val) { + if (!has_string(vm, name)) return false; + val = read_string(vm, name); + return true; +} + +bool get_bool(HSQUIRRELVM vm, const char* name, bool& val) { + if (!has_bool(vm, name)) return false; + val = read_bool(vm, name); + return true; +} + +// end: serialization functions + }