src/ai/squirrel/squirrel.cpp
branchnoai
changeset 9393 04bd925b9069
parent 9387 4255a0a2d272
child 9395 4337e022594c
--- a/src/ai/squirrel/squirrel.cpp	Wed Mar 14 23:01:30 2007 +0000
+++ b/src/ai/squirrel/squirrel.cpp	Thu Mar 15 00:01:33 2007 +0000
@@ -5,7 +5,6 @@
 #include "squirrel.hpp"
 #include <sqstdio.h>
 #include <sqstdaux.h>
-#include <stdarg.h>
 #include "../../debug.h"
 
 #define SQUIRREL_CLASS
@@ -16,48 +15,6 @@
 #include "../core/ai_map.hpp"
 #include "../core/ai_town.hpp"
 
-/**
- * Here we handle errors that come from squirrel.
- */
-static void Squirrel_CompileError(HSQUIRRELVM vm, const SQChar *desc, const SQChar *source, SQInteger line, SQInteger column)
-{
-#ifdef _SQ64
-	printf("Error %s:%ld/%ld: %s\n", source, line, column, desc);
-#else
-	printf("Error %s:%d/%d: %s\n", source, line, column, desc);
-#endif
-}
-
-/**
- * Here we handle run-time errors that come from squirrel.
- */
-static SQInteger Squirrel_RunError(HSQUIRRELVM vm)
-{
-	const SQChar *sErr = 0;
-
-	if (sq_gettop(vm) >= 1) {
-		if (SQ_SUCCEEDED(sq_getstring(vm, -1, &sErr))) {
-			printf("%s\n", sErr);
-		} else {
-			printf("Unknown error\n");
-		}
-	}
-
-	return 0;
-}
-
-/**
- * Here we handle 'print' command within squirrel script.
- */
-static void Squirrel_PrintFunc(HSQUIRRELVM vm, const SQChar *s, ...)
-{
-	va_list arglist;
-	va_start(arglist, s);
-	vprintf(s, arglist);
-	va_end(arglist);
-	printf("\n");
-}
-
 SQInteger Squirrel::SQDestructor(SQUserPointer p, SQInteger size)
 {
 	return 1;
@@ -71,52 +28,18 @@
 
 SQInteger Squirrel::SQGetTick(HSQUIRRELVM vm)
 {
-	SQUserPointer ptr;
+	SQUserPointer self;
 
-	/* Find the 'self' pointer */
-	if (SQ_FAILED(sq_getinstanceup(vm, 1, &ptr, 0))) {
-		DEBUG(ai, 0, "[squirrel] Failed to find the instance-pointer");
+	if (!SquirrelCore::GetInstance(vm, &self)) {
+		DEBUG(ai, 0, "[squirrel] Failed to find instance pointer");
 		return SQ_ERROR;
 	}
 
 	/* Return the value */
-	sq_pushinteger(vm, ((Squirrel *)ptr)->GetTick());
+	sq_pushinteger(vm, ((Squirrel *)self)->GetTick());
 	return 1;
 }
 
-bool Squirrel::SQCreateClass(const char *classname)
-{
-	int oldtop = sq_gettop(this->vm);
-
-	/* First, find the class */
-	sq_pushroottable(this->vm);
-	sq_pushstring(this->vm, classname, -1);
-	sq_get(this->vm, -2);
-
-	/* Create the instance */
-	if (SQ_FAILED(sq_createinstance(this->vm, -1))) {
-		DEBUG(ai, 0, "[squirrel] Failed to create instance for class '%s'", classname);
-		sq_settop(this->vm, oldtop);
-		return false;
-	}
-
-	/* Find our instance */
-	sq_getstackobj(this->vm, -1, &this->SQ_instance);
-	/* Add a reference to it, so it survives for ever */
-	sq_addref(this->vm, &this->SQ_instance);
-	/* Store it in the class */
-	sq_setinstanceup(this->vm, -1, this);
-	/* Make sure we get called when the AI is destroyed */
-	sq_setreleasehook(this->vm, -1, &Squirrel::SQDestructor);
-
-	/* Reset the top */
-	sq_settop(this->vm, oldtop);
-
-	DEBUG(ai, 1, "[squirrel] Created an instance of class '%s' with pointer '%p'", classname, this->SQ_instance._unVal.pUserPointer);
-
-	return true;
-}
-
 SQInteger Squirrel::SQRegisterAI(HSQUIRRELVM vm)
 {
 	const SQChar *classname = NULL;
@@ -142,111 +65,56 @@
 	sq_setforeignptr(vm, NULL);
 
 	/* Create the new class */
-	if (!self->SQCreateClass(classname)) {
+	if (!self->core->CreateClassInstance(classname, self, &self->SQ_instance)) {
 		return SQ_ERROR;
 	}
 
 	return 0;
 }
 
-inline void Squirrel::SQAddMethod(const char *name, SQFUNCTION proc, uint nparam, const char *params)
-{
-	sq_pushstring(this->vm, name, -1);
-	sq_newclosure(this->vm, proc, 0);
-	sq_setparamscheck(this->vm, nparam, params);
-	sq_setnativeclosurename(this->vm, -1, name);
-	sq_createslot(this->vm, -3);
-}
-
 void Squirrel::RegisterClasses()
 {
-	SQInteger top = sq_gettop(this->vm);
+	HSQUIRRELVM vm = this->core->GetVM();
+	SQInteger top = sq_gettop(vm);
 
 	/* Store 'this' so we can find it back later on */
-	sq_setforeignptr(this->vm, this);
+	sq_setforeignptr(vm, this);
 
-	/* Create AIController class (the 'main' of it all) */
-	sq_pushroottable(this->vm);
-	sq_pushstring(this->vm, "AIController", -1);
-	sq_newclass(this->vm, SQFalse);
+	this->core->AddClassBegin("AIController");
 
 	/* Create a constructor, so we can assign the right 'this' */
-	this->SQAddMethod("constructor", &Squirrel::SQConstructor, 1, "x");
+	this->core->AddMethod("constructor", &Squirrel::SQConstructor, 1, "x");
 	/* Assign other functions as AIController won't be done via the normal way */
-	this->SQAddMethod("GetTick", &Squirrel::SQGetTick, 1, "x");
+	this->core->AddMethod("GetTick", &Squirrel::SQGetTick, 1, "x");
 
-	/* Finally really create the class */
-	sq_createslot(this->vm, -3);
+	this->core->AddClassEnd();
 
 	/* Register the 'RegisterAI()' function */
-	sq_pushroottable(this->vm);
-	this->SQAddMethod("RegisterAI", &Squirrel::SQRegisterAI, 2, "ts");
+	sq_pushroottable(vm);
+	this->core->AddMethod("RegisterAI", &Squirrel::SQRegisterAI, 2, "ts");
 
-	SQAIBaseRegister(this->vm);
-	SQAICompanyRegister(this->vm);
-	SQAIMapRegister(this->vm);
-	SQAITownRegister(this->vm);
+	SQAIBaseRegister(vm);
+	SQAICompanyRegister(vm);
+	SQAIMapRegister(vm);
+	SQAITownRegister(vm);
 
 	/* Reset top */
-	sq_settop(this->vm, top);
+	sq_settop(vm, top);
 }
 
-Squirrel::Squirrel(const char *script_dir)
+Squirrel::Squirrel(const char *script)
 {
-	char filename[1024];
-
-	this->vm = sq_open(1024);
-
-	/* Handle compile-errors ourself, so we can display it nicely */
-	sq_setcompilererrorhandler(this->vm, Squirrel_CompileError);
-	sq_notifyallexceptions(this->vm, SQTrue);
-	/* Set a good print-function */
-	sq_setprintfunc(this->vm, Squirrel_PrintFunc);
-	/* Handle runtime-errors ourself, so we can display it nicely */
-	sq_newclosure(this->vm, &Squirrel_RunError, 0);
-	sq_seterrorhandler(this->vm);
-
-	/* TODO -- This is ugly! */
-	strcpy(filename, "ai/");
-	strcat(filename, script_dir);
-	strcat(filename, PATHSEP);
-	strcat(filename, "main.nut");
-
-	DEBUG(ai, 1, "[squirrel] Starting AI with script in '%s'", filename);
-
-	sq_pushroottable(this->vm);
+	this->core = new SquirrelCore();
 	this->RegisterClasses();
-
-	/* Load and run the script */
-	if (SQ_FAILED(sqstd_dofile(this->vm, filename, SQFalse, SQTrue))) {
-		DEBUG(ai, 0, "[squirrel] Failed to compile '%s'", filename);
-		return;
-	}
+	this->core->LoadScript(script);
 }
 
 Squirrel::~Squirrel()
 {
-	/* Clean up the stuff */
-	sq_pop(this->vm, 1);
-	sq_close(this->vm);
+	delete this->core;
 }
 
 /* virtual */ void Squirrel::GameLoop()
 {
-	/* Store the current top */
-	int top = sq_gettop(this->vm);
-	/* Go to the instance-root */
-	sq_pushobject(this->vm, this->SQ_instance);
-	/* Find the function-name inside the script */
-	sq_pushstring(this->vm, "GameLoop", -1);
-	if (SQ_FAILED(sq_get(this->vm, -2))) {
-		DEBUG(ai, 0, "[squirrel] Could not find 'GameLoop' in the AIController class");
-		sq_settop(this->vm, top);
-		return;
-	}
-	/* Call the method */
-	sq_pushobject(this->vm, this->SQ_instance);
-	sq_call(this->vm, 1, 0, 0);
-	/* Reset the top */
-	sq_settop(this->vm, top);
+	this->core->CallMethod(this->SQ_instance, "GameLoop");
 }