(svn r12277) [NoAI] -Change: overlay GlobalPointer with local instance access and create sub-node to contain data
[NoAI] -Change: relay PrintFunc to redirect via overlay and supply AIController with Print, in order to establish bypass of the log created by the AI
[/STARTREK VOYAGER]
--- a/src/ai/ai_squirrel.cpp Tue Feb 26 18:39:33 2008 +0000
+++ b/src/ai/ai_squirrel.cpp Tue Feb 26 21:35:22 2008 +0000
@@ -302,6 +302,7 @@
AIControllerSquirrel::AIControllerSquirrel(const char *script, const char *class_name)
{
this->engine = new Squirrel();
+ this->engine->SetPrintFunction(&AIControllerSquirrel::PrintFunc);
this->RegisterClasses();
this->engine->LoadScript(script);
/* Create the main-class */
--- a/src/ai/ai_squirrel.hpp Tue Feb 26 18:39:33 2008 +0000
+++ b/src/ai/ai_squirrel.hpp Tue Feb 26 21:35:22 2008 +0000
@@ -26,6 +26,7 @@
uint GetTick() { return AIController::GetTick(); }
void Sleep(uint ticks) { return AIController::Sleep(ticks); }
+ static void PrintFunc(bool error_msg, const char *message) { AIController::Print(error_msg, message); }
};
class FSquirrel: public AIFactory<FSquirrel> {
--- a/src/ai/api/ai_controller.cpp Tue Feb 26 18:39:33 2008 +0000
+++ b/src/ai/api/ai_controller.cpp Tue Feb 26 21:35:22 2008 +0000
@@ -8,7 +8,13 @@
#include "../../player_func.h"
#include "../ai_threads.h"
-void AIController::Sleep(uint ticks)
+/* static */ void AIController::Sleep(uint ticks)
{
AI_SuspendPlayer(_current_player, ticks);
}
+
+/* static */ void AIController::Print(bool error_msg, const char *message)
+{
+ if (error_msg) fprintf(stderr, "%s", message);
+ else printf("%s", message);
+}
--- a/src/ai/api/ai_controller.hpp Tue Feb 26 18:39:33 2008 +0000
+++ b/src/ai/api/ai_controller.hpp Tue Feb 26 21:35:22 2008 +0000
@@ -69,7 +69,14 @@
* @post the value of GetTick() will be changed exactly 'ticks' in value after
* calling this.
*/
- void Sleep(uint ticks);
+ static void Sleep(uint ticks);
+
+ /**
+ * Print a message to the AI log.
+ * @param error_msg If true, it is marked as error message.
+ * @param message The message you want to log.
+ */
+ static void Print(bool error_msg, const char *message);
};
#endif /* AI_CONTROLLER_HPP */
--- a/src/ai/api/ai_controller.hpp.sq Tue Feb 26 18:39:33 2008 +0000
+++ b/src/ai/api/ai_controller.hpp.sq Tue Feb 26 21:35:22 2008 +0000
@@ -3,7 +3,8 @@
void SQAIController_Register(Squirrel *engine) {
DefSQClass <AIControllerSquirrel> SQAIController("AIController");
SQAIController.PreRegister(engine);
- SQAIController.DefSQMethod(engine, &AIControllerSquirrel::GetTick, "GetTick");
- SQAIController.DefSQMethod(engine, &AIControllerSquirrel::Sleep, "Sleep");
+ SQAIController.DefSQMethod(engine, &AIControllerSquirrel::GetTick, "GetTick", 1, "x");
+ SQAIController.DefSQStaticMethod(engine, &AIControllerSquirrel::Sleep, "Sleep", 2, "xi");
+ SQAIController.DefSQStaticMethod(engine, &AIControllerSquirrel::Print, "Print", 3, "xbs");
SQAIController.PostRegister(engine);
}
--- a/src/squirrel.cpp Tue Feb 26 18:39:33 2008 +0000
+++ b/src/squirrel.cpp Tue Feb 26 21:35:22 2008 +0000
@@ -27,9 +27,16 @@
void Squirrel::ErrorPrintFunc(HSQUIRRELVM vm, const SQChar *s, ...)
{
va_list arglist;
+ char buf[1024];
+
va_start(arglist, s);
- scvfprintf(stderr, s, arglist);
+ vsnprintf(buf, lengthof(buf), s, arglist);
va_end(arglist);
+
+ /* Check if we have a custom print function */
+ SQPrintFunc *func = ((Squirrel *)sq_getforeignptr(vm))->print_func;
+ if (func == NULL) fprintf(stderr, "%s", buf);
+ else (*func)(true, buf);
}
void Squirrel::RunError(HSQUIRRELVM vm, const char *error)
@@ -37,7 +44,14 @@
/* Set the print function to something that prints to stderr */
SQPRINTFUNCTION pf = sq_getprintfunc(vm);
sq_setprintfunc(vm, &Squirrel::ErrorPrintFunc);
- DEBUG(misc, 0, "Your script made an error: %s", error);
+
+ /* Check if we have a custom print function */
+ char buf[1024];
+ snprintf(buf, lengthof(buf), "Your script made an error: %s\n", error);
+ SQPrintFunc *func = ((Squirrel *)sq_getforeignptr(vm))->print_func;
+ if (func == NULL) fprintf(stderr, "%s", buf);
+ else (*func)(true, buf);
+
/* Print below the error the stack, so the users knows what is happening */
sqstd_printcallstack(vm);
/* Reset the old print function */
@@ -62,10 +76,17 @@
void Squirrel::PrintFunc(HSQUIRRELVM vm, const SQChar *s, ...)
{
va_list arglist;
+ char buf[1024];
+
va_start(arglist, s);
- scvprintf(s, arglist);
+ vsnprintf(buf, lengthof(buf) - 2, s, arglist);
va_end(arglist);
- printf("\n");
+ strcat(buf, "\n");
+
+ /* Check if we have a custom print function */
+ SQPrintFunc *func = ((Squirrel *)sq_getforeignptr(vm))->print_func;
+ if (func == NULL) printf("%s", buf);
+ else (*func)(false, buf);
}
void Squirrel::AddMethod(const char *method_name, SQFUNCTION proc, uint nparam, const char *params, void *userdata, int size)
@@ -198,6 +219,8 @@
Squirrel::Squirrel()
{
this->vm = sq_open(1024);
+ this->print_func = NULL;
+ this->global_pointer = NULL;
/* Handle compile-errors ourself, so we can display it nicely */
sq_setcompilererrorhandler(this->vm, &Squirrel::CompileError);
@@ -208,6 +231,9 @@
sq_newclosure(this->vm, &Squirrel::_RunError, 0);
sq_seterrorhandler(this->vm);
+ /* Set the foreigh pointer, so we can always find this instance from within the VM */
+ sq_setforeignptr(this->vm, this);
+
sq_pushroottable(this->vm);
squirrel_register_global_std(this);
}
--- a/src/squirrel.hpp Tue Feb 26 18:39:33 2008 +0000
+++ b/src/squirrel.hpp Tue Feb 26 21:35:22 2008 +0000
@@ -7,7 +7,11 @@
class Squirrel {
private:
- HSQUIRRELVM vm; ///< The VirtualMachine instnace for squirrel
+ typedef void (SQPrintFunc)(bool error_msg, const char *message);
+
+ HSQUIRRELVM vm; ///< The VirtualMachine instnace for squirrel
+ void *global_pointer; ///< Can be set by who ever initializes Squirrel
+ SQPrintFunc *print_func; ///< Points to either NULL, or a custom print handler
/**
* The internal RunError handler. It looks up the real error and calls RunError with it.
@@ -129,15 +133,20 @@
static int ObjectToInteger(HSQOBJECT *ptr) { return sq_objtointeger(ptr); }
/**
- * Sets a pointer in the VM that is reasable from where ever you are, what
- * ever your state is. Useful to keep track of the main instance.
+ * Sets a pointer in the VM that is reachable from where ever you are in SQ.
+ * Useful to keep track of the main instance.
*/
- void SetGlobalPointer(void *ptr) { sq_setforeignptr(this->vm, ptr); }
+ void SetGlobalPointer(void *ptr) { this->global_pointer = ptr; }
/**
* Get the pointer as set by SetGlobalPointer.
*/
- static void *GetGlobalPointer(HSQUIRRELVM vm) { return sq_getforeignptr(vm); }
+ static void *GetGlobalPointer(HSQUIRRELVM vm) { return ((Squirrel *)sq_getforeignptr(vm))->global_pointer; }
+
+ /**
+ * Set a custom print function, so you can handle outputs from SQ yourself.
+ */
+ void SetPrintFunction(SQPrintFunc *func) { this->print_func = func; }
/**
* Throw a Squirrel error that will be nicely displayed to the user.