diff options
Diffstat (limited to 'src/ai/api/ai_controller.cpp')
-rw-r--r-- | src/ai/api/ai_controller.cpp | 86 |
1 files changed, 75 insertions, 11 deletions
diff --git a/src/ai/api/ai_controller.cpp b/src/ai/api/ai_controller.cpp index 78dee1d21..c99c4c0a2 100644 --- a/src/ai/api/ai_controller.cpp +++ b/src/ai/api/ai_controller.cpp @@ -13,11 +13,13 @@ #include "../../string_func.h" #include "../../company_base.h" #include "../../company_func.h" +#include "../../script/squirrel.hpp" #include "../../rev.h" #include "ai_controller.hpp" #include "../ai_instance.hpp" #include "../ai_config.hpp" +#include "../ai.hpp" #include "ai_log.hpp" /* static */ void AIController::SetCommandDelay(int ticks) @@ -81,19 +83,81 @@ AIController::~AIController() return _openttd_newgrf_version; } -bool AIController::LoadedLibrary(const char *library_name, int *next_number, char *fake_class_name, int fake_class_name_len) +/* static */ HSQOBJECT AIController::Import(const char *library, const char *class_name, int version) { - LoadedLibraryList::iterator iter = this->loaded_library.find(library_name); - if (iter == this->loaded_library.end()) { - *next_number = ++this->loaded_library_count; - return false; + AIController *controller = AIObject::GetActiveInstance()->GetController(); + Squirrel *engine = AIObject::GetActiveInstance()->engine; + HSQUIRRELVM vm = engine->GetVM(); + + /* Internally we store libraries as 'library.version' */ + char library_name[1024]; + snprintf(library_name, sizeof(library_name), "%s.%d", library, version); + strtolower(library_name); + + AILibrary *lib = AI::FindLibrary(library, version); + if (lib == NULL) { + char error[1024]; + snprintf(error, sizeof(error), "couldn't find library '%s' with version %d", library, version); + throw sq_throwerror(vm, OTTD2SQ(error)); } - ttd_strlcpy(fake_class_name, (*iter).second, fake_class_name_len); - return true; -} + /* Get the current table/class we belong to */ + HSQOBJECT parent; + sq_getstackobj(vm, 1, &parent); + + char fake_class[1024]; + + LoadedLibraryList::iterator iter = controller->loaded_library.find(library_name); + if (iter != controller->loaded_library.end()) { + ttd_strlcpy(fake_class, (*iter).second, sizeof(fake_class)); + } else { + int next_number = ++controller->loaded_library_count; + + /* Create a new fake internal name */ + snprintf(fake_class, sizeof(fake_class), "_internalNA%d", next_number); + + /* Load the library in a 'fake' namespace, so we can link it to the name the user requested */ + sq_pushroottable(vm); + sq_pushstring(vm, OTTD2SQ(fake_class), -1); + sq_newclass(vm, SQFalse); + /* Load the library */ + if (!engine->LoadScript(vm, lib->GetMainScript(), false)) { + char error[1024]; + snprintf(error, sizeof(error), "there was a compile error when importing '%s' version %d", library, version); + throw sq_throwerror(vm, OTTD2SQ(error)); + } + /* Create the fake class */ + sq_newslot(vm, -3, SQFalse); + sq_pop(vm, 1); + + controller->loaded_library[strdup(library_name)] = strdup(fake_class); + } -void AIController::AddLoadedLibrary(const char *library_name, const char *fake_class_name) -{ - this->loaded_library[strdup(library_name)] = strdup(fake_class_name); + /* Find the real class inside the fake class (like 'sets.Vector') */ + sq_pushroottable(vm); + sq_pushstring(vm, OTTD2SQ(fake_class), -1); + if (SQ_FAILED(sq_get(vm, -2))) { + throw sq_throwerror(vm, _SC("internal error assigning library class")); + } + sq_pushstring(vm, OTTD2SQ(lib->GetInstanceName()), -1); + if (SQ_FAILED(sq_get(vm, -2))) { + char error[1024]; + snprintf(error, sizeof(error), "unable to find class '%s' in the library '%s' version %d", lib->GetInstanceName(), library, version); + throw sq_throwerror(vm, OTTD2SQ(error)); + } + HSQOBJECT obj; + sq_getstackobj(vm, -1, &obj); + sq_pop(vm, 3); + + if (StrEmpty(class_name)) return obj; + + /* Now link the name the user wanted to our 'fake' class */ + sq_pushobject(vm, parent); + sq_pushstring(vm, OTTD2SQ(class_name), -1); + sq_pushobject(vm, obj); + sq_newclass(vm, SQTrue); + sq_newslot(vm, -3, SQFalse); + sq_pop(vm, 1); + + return obj; } |