src/ai/ai_squirrel.cpp
branchnoai
changeset 10958 65088d587094
parent 10942 cd3f2d07199f
child 11024 631db8573db2
equal deleted inserted replaced
10957:7a140b4cd91d 10958:65088d587094
    15 
    15 
    16 #include <squirrel.h>
    16 #include <squirrel.h>
    17 #include "../squirrel.hpp"
    17 #include "../squirrel.hpp"
    18 #include "ai_info.hpp"
    18 #include "ai_info.hpp"
    19 #include "ai_squirrel.hpp"
    19 #include "ai_squirrel.hpp"
       
    20 #include "api/ai_controller.hpp"
    20 
    21 
    21 void AISquirrel::ScanDir(const char *dirname, bool library_dir, char *library_depth)
    22 void AISquirrel::ScanDir(const char *dirname, bool library_dir, char *library_depth)
    22 {
    23 {
    23 	extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
    24 	extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
    24 	extern bool FiosIsHiddenFile(const struct dirent *ent);
    25 	extern bool FiosIsHiddenFile(const struct dirent *ent);
   130 	this->ScanAIDir();
   131 	this->ScanAIDir();
   131 }
   132 }
   132 
   133 
   133 AISquirrel::AISquirrel()
   134 AISquirrel::AISquirrel()
   134 {
   135 {
   135 	this->library_instance_count = 0;
       
   136 	this->engine = new Squirrel();
   136 	this->engine = new Squirrel();
   137 
   137 
   138 	/* Create the AIInfo class, and add the RegisterAI function */
   138 	/* Create the AIInfo class, and add the RegisterAI function */
   139 	this->engine->AddClassBegin("AIInfo");
   139 	this->engine->AddClassBegin("AIInfo");
   140 	this->engine->AddClassEnd();
   140 	this->engine->AddClassEnd();
   160 	}
   160 	}
   161 
   161 
   162 	delete this->engine;
   162 	delete this->engine;
   163 }
   163 }
   164 
   164 
   165 bool AISquirrel::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm)
   165 bool AISquirrel::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm, AIController *controller)
   166 {
   166 {
   167 	AILibraryList::iterator iter = this->library_list.find(library);
   167 	AILibraryList::iterator iter = this->library_list.find(library);
   168 	/* Check if the library exists */
   168 	/* Check if the library exists */
   169 	if (iter == this->library_list.end()) {
   169 	if (iter == this->library_list.end()) {
   170 		char error[1024];
   170 		char error[1024];
   179 		snprintf(error, sizeof(error), "this AI is expected library '%s' to be version %d, but it is version %d", library, version, (*iter).second->GetVersion());
   179 		snprintf(error, sizeof(error), "this AI is expected library '%s' to be version %d, but it is version %d", library, version, (*iter).second->GetVersion());
   180 		sq_throwerror(vm, OTTD2FS(error));
   180 		sq_throwerror(vm, OTTD2FS(error));
   181 		return false;
   181 		return false;
   182 	}
   182 	}
   183 
   183 
   184 	/* Create a fake internal name */
       
   185 	char fake_class[1024];
       
   186 	snprintf(fake_class, sizeof(fake_class), "_internalNA%d", ++this->library_instance_count);
       
   187 
       
   188 	/* Get the current table/class we belong to */
   184 	/* Get the current table/class we belong to */
   189 	HSQOBJECT parent;
   185 	HSQOBJECT parent;
   190 	sq_getstackobj(vm, 1, &parent);
   186 	sq_getstackobj(vm, 1, &parent);
   191 
   187 
   192 	/* Load the library in a 'fake' namespace, so we can link it to the name the user requested */
   188 	char fake_class[1024];
   193 	sq_pushroottable(vm);
   189 	int next_number;
   194 	sq_pushstring(vm, OTTD2FS(fake_class), -1);
   190 	/* Check if we already have this library loaded.. if so, fill fake_class
   195 	sq_newclass(vm, SQFalse);
   191 	 *  with the class-name it is nested in */
   196 	/* Load the library */
   192 	if (!controller->LoadedLibrary(library, &next_number, &fake_class[0], sizeof(fake_class))) {
   197 	if (!Squirrel::LoadScript(vm, (*iter).second->GetScriptName(), false)) {
   193 		/* Create a new fake internal name */
   198 		char error[1024];
   194 		snprintf(fake_class, sizeof(fake_class), "_internalNA%d", next_number);
   199 		snprintf(error, sizeof(error), "there was a compile error when importing '%s'", library);
   195 
   200 		sq_throwerror(vm, OTTD2FS(error));
   196 		/* Load the library in a 'fake' namespace, so we can link it to the name the user requested */
   201 		return false;
   197 		sq_pushroottable(vm);
   202 	}
   198 		sq_pushstring(vm, OTTD2FS(fake_class), -1);
   203 	/* Create the fake class */
   199 		sq_newclass(vm, SQFalse);
   204 	sq_newslot(vm, -3, SQFalse);
   200 		/* Load the library */
   205 	sq_pop(vm, 1);
   201 		if (!Squirrel::LoadScript(vm, (*iter).second->GetScriptName(), false)) {
       
   202 			char error[1024];
       
   203 			snprintf(error, sizeof(error), "there was a compile error when importing '%s'", library);
       
   204 			sq_throwerror(vm, OTTD2FS(error));
       
   205 			return false;
       
   206 		}
       
   207 		/* Create the fake class */
       
   208 		sq_newslot(vm, -3, SQFalse);
       
   209 		sq_pop(vm, 1);
       
   210 
       
   211 		controller->AddLoadedLibrary(library, fake_class);
       
   212 	}
   206 
   213 
   207 	/* Find the real class inside the fake class (like 'sets.Vector') */
   214 	/* Find the real class inside the fake class (like 'sets.Vector') */
   208 	sq_pushroottable(vm);
   215 	sq_pushroottable(vm);
   209 	sq_pushstring(vm, OTTD2FS(fake_class), -1);
   216 	sq_pushstring(vm, OTTD2FS(fake_class), -1);
   210 	if (SQ_FAILED(sq_get(vm, -2))) {
   217 	if (SQ_FAILED(sq_get(vm, -2))) {