diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ai/ai.hpp | 4 | ||||
-rw-r--r-- | src/ai/ai_core.cpp | 4 | ||||
-rw-r--r-- | src/ai/ai_info.cpp | 11 | ||||
-rw-r--r-- | src/ai/ai_info.hpp | 7 | ||||
-rw-r--r-- | src/ai/ai_instance.cpp | 5 | ||||
-rw-r--r-- | src/ai/ai_instance.hpp | 1 | ||||
-rw-r--r-- | src/ai/ai_scanner.cpp | 79 | ||||
-rw-r--r-- | src/ai/ai_scanner.hpp | 7 | ||||
-rw-r--r-- | src/ai/api/ai_controller.cpp | 86 | ||||
-rw-r--r-- | src/ai/api/ai_controller.hpp | 27 | ||||
-rw-r--r-- | src/ai/api/ai_controller.hpp.sq | 5 | ||||
-rw-r--r-- | src/script/squirrel.hpp | 1 | ||||
-rw-r--r-- | src/script/squirrel_helper.hpp | 1 |
13 files changed, 106 insertions, 132 deletions
diff --git a/src/ai/ai.hpp b/src/ai/ai.hpp index 73e95efee..c8e5036b5 100644 --- a/src/ai/ai.hpp +++ b/src/ai/ai.hpp @@ -134,8 +134,8 @@ public: static const AIInfoList *GetUniqueInfoList(); /** Wrapper function for AIScanner::FindInfo */ static AIInfo *FindInfo(const char *name, int version, bool force_exact_match); - /** Wrapper function for AIScanner::ImportLibrary */ - static bool ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm); + /** Wrapper function for AIScanner::FindLibrary */ + static class AILibrary *FindLibrary(const char *library, int version); /** * Rescans all searchpaths for available AIs. If a used AI is no longer diff --git a/src/ai/ai_core.cpp b/src/ai/ai_core.cpp index 0e7667ba4..a370bda9d 100644 --- a/src/ai/ai_core.cpp +++ b/src/ai/ai_core.cpp @@ -322,9 +322,9 @@ void CcAI(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2) return AI::ai_scanner->FindInfo(name, version, force_exact_match); } -/* static */ bool AI::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm) +/* static */ AILibrary *AI::FindLibrary(const char *library, int version) { - return AI::ai_scanner->ImportLibrary(library, class_name, version, vm, AIObject::GetActiveInstance()->GetController()); + return AI::ai_scanner->FindLibrary(library, version); } /* static */ void AI::Rescan() diff --git a/src/ai/ai_info.cpp b/src/ai/ai_info.cpp index 630f04b82..a729cb482 100644 --- a/src/ai/ai_info.cpp +++ b/src/ai/ai_info.cpp @@ -372,14 +372,3 @@ int AIInfo::GetSettingDefaultValue(const char *name) const return 0; } - -/* static */ SQInteger AILibrary::Import(HSQUIRRELVM vm) -{ - SQConvert::SQAutoFreePointers ptr; - const char *library = GetParam(SQConvert::ForceType<const char *>(), vm, 2, &ptr); - const char *class_name = GetParam(SQConvert::ForceType<const char *>(), vm, 3, &ptr); - int version = GetParam(SQConvert::ForceType<int>(), vm, 4, &ptr); - - if (!AI::ImportLibrary(library, class_name, version, vm)) return -1; - return 1; -} diff --git a/src/ai/ai_info.hpp b/src/ai/ai_info.hpp index c618930d9..6ddb23330 100644 --- a/src/ai/ai_info.hpp +++ b/src/ai/ai_info.hpp @@ -147,13 +147,6 @@ public: static SQInteger Constructor(HSQUIRRELVM vm); /** - * Import a library in the current AI. This function can be used by AIs - * by calling import. - * @param vm The squirrel vm of the calling AI. - */ - static SQInteger Import(HSQUIRRELVM vm); - - /** * Get the category this library is in. */ const char *GetCategory() const { return this->category; } diff --git a/src/ai/ai_instance.cpp b/src/ai/ai_instance.cpp index b99b8a108..45e142c24 100644 --- a/src/ai/ai_instance.cpp +++ b/src/ai/ai_instance.cpp @@ -122,10 +122,7 @@ void AIInstance::Initialize(AIInfo *info) this->controller = new AIController(); - /* The import method is available at a very early stage */ - this->engine->AddMethod("import", &AILibrary::Import, 4, ".ssi"); - - /* Register the AIController */ + /* Register the AIController (including the "import" command) */ SQAIController_Register(this->engine); /* Register the API functions and classes */ diff --git a/src/ai/ai_instance.hpp b/src/ai/ai_instance.hpp index b0b32b3b5..085e2cbca 100644 --- a/src/ai/ai_instance.hpp +++ b/src/ai/ai_instance.hpp @@ -78,6 +78,7 @@ private: class AIInstance { public: friend class AIObject; + friend class AIController; /** * Create a new AI. diff --git a/src/ai/ai_scanner.cpp b/src/ai/ai_scanner.cpp index a2954c6d9..6e78d1c19 100644 --- a/src/ai/ai_scanner.cpp +++ b/src/ai/ai_scanner.cpp @@ -95,7 +95,7 @@ AIScanner::~AIScanner() delete this->info_dummy; } -bool AIScanner::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm, AIController *controller) +AILibrary *AIScanner::FindLibrary(const char *library, int version) { /* Internally we store libraries as 'library.version' */ char library_name[1024]; @@ -104,82 +104,9 @@ bool AIScanner::ImportLibrary(const char *library, const char *class_name, int v /* Check if the library + version exists */ AILibraryList::iterator iter = this->library_list.find(library_name); - if (iter == this->library_list.end()) { - char error[1024]; - - /* Now see if the version doesn't exist, or the library */ - iter = this->library_list.find(library); - if (iter == this->library_list.end()) { - snprintf(error, sizeof(error), "couldn't find library '%s'", library); - } else { - snprintf(error, sizeof(error), "couldn't find library '%s' version %d. The latest version available is %d", library, version, (*iter).second->GetVersion()); - } - sq_throwerror(vm, OTTD2SQ(error)); - return false; - } - - /* Get the current table/class we belong to */ - HSQOBJECT parent; - sq_getstackobj(vm, 1, &parent); - - char fake_class[1024]; - int next_number; - - if (!controller->LoadedLibrary(library_name, &next_number, &fake_class[0], sizeof(fake_class))) { - /* 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 (!this->engine->LoadScript(vm, (*iter).second->GetMainScript(), false)) { - char error[1024]; - snprintf(error, sizeof(error), "there was a compile error when importing '%s' version %d", library, version); - sq_throwerror(vm, OTTD2SQ(error)); - return false; - } - /* Create the fake class */ - sq_newslot(vm, -3, SQFalse); - sq_pop(vm, 1); - - controller->AddLoadedLibrary(library_name, fake_class); - } - - /* 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))) { - sq_throwerror(vm, _SC("internal error assigning library class")); - return false; - } - sq_pushstring(vm, OTTD2SQ((*iter).second->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", (*iter).second->GetInstanceName(), library, version); - sq_throwerror(vm, OTTD2SQ(error)); - return false; - } - HSQOBJECT obj; - sq_getstackobj(vm, -1, &obj); - sq_pop(vm, 3); - - if (StrEmpty(class_name)) { - sq_pushobject(vm, obj); - return true; - } - - /* 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); + if (iter == this->library_list.end()) return NULL; - sq_pushobject(vm, obj); - return true; + return (*iter).second; } void AIScanner::RegisterLibrary(AILibrary *library) diff --git a/src/ai/ai_scanner.hpp b/src/ai/ai_scanner.hpp index f3d0776c6..cbc778069 100644 --- a/src/ai/ai_scanner.hpp +++ b/src/ai/ai_scanner.hpp @@ -24,9 +24,12 @@ public: ~AIScanner(); /** - * Import a library inside the Squirrel VM. + * Find a library by name + version. + * @param library The name of the library to find. + * @param version The prefered version of the library. + * @return The library if found, NULL otherwise. */ - bool ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm, class AIController *controller); + AILibrary *FindLibrary(const char *library, int version); /** * Register a library to be put in the available list. 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; } diff --git a/src/ai/api/ai_controller.hpp b/src/ai/api/ai_controller.hpp index 0df721109..8f3dd4b66 100644 --- a/src/ai/api/ai_controller.hpp +++ b/src/ai/api/ai_controller.hpp @@ -109,6 +109,16 @@ public: */ static void Print(bool error_msg, const char *message); + /** + * Import a library. + * @param library The name of the library to import. + * @param class_name Under which name you want it to be available (or "" if you just want the returning object). + * @param version Which version you want specificly. + * @return The loaded library object. If class_name is set, it is also available (under the scope of the import) under that name. + * @note This command can be called from the global space, and does not need an instance. + */ + static HSQOBJECT Import(const char *library, const char *class_name, int version); + private: typedef std::map<const char *, const char *, StringCompare> LoadedLibraryList; ///< The type for loaded libraries. @@ -120,23 +130,6 @@ private: * Register all classes that are known inside the NoAI API. */ void RegisterClasses(); - - /** - * Check if a library is already loaded. If found, fake_class_name is filled - * with the fake class name as given via AddLoadedLibrary. If not found, - * next_number is set to the next number available for the fake namespace. - * @param library_name The library to check if already loaded. - * @param next_number The next available number for a library if not already loaded. - * @param fake_class_name The name the library has if already loaded. - * @param fake_class_name_len The maximum length of fake_class_name. - * @return True if the library is already loaded. - */ - bool LoadedLibrary(const char *library_name, int *next_number, char *fake_class_name, int fake_class_name_len); - - /** - * Add a library as loaded. - */ - void AddLoadedLibrary(const char *library_name, const char *fake_class_name); }; #endif /* AI_CONTROLLER_HPP */ diff --git a/src/ai/api/ai_controller.hpp.sq b/src/ai/api/ai_controller.hpp.sq index 8a0e70ccd..26b627c7b 100644 --- a/src/ai/api/ai_controller.hpp.sq +++ b/src/ai/api/ai_controller.hpp.sq @@ -15,6 +15,7 @@ void SQAIController_Register(Squirrel *engine) { DefSQClass <AIController> SQAIController("AIController"); SQAIController.PreRegister(engine); + SQAIController.DefSQStaticMethod(engine, &AIController::GetTick, "GetTick", 1, "."); SQAIController.DefSQStaticMethod(engine, &AIController::GetOpsTillSuspend, "GetOpsTillSuspend", 1, "."); SQAIController.DefSQStaticMethod(engine, &AIController::SetCommandDelay, "SetCommandDelay", 2, ".i"); @@ -22,5 +23,9 @@ void SQAIController_Register(Squirrel *engine) SQAIController.DefSQStaticMethod(engine, &AIController::GetSetting, "GetSetting", 2, ".s"); SQAIController.DefSQStaticMethod(engine, &AIController::GetVersion, "GetVersion", 1, "."); SQAIController.DefSQStaticMethod(engine, &AIController::Print, "Print", 3, ".bs"); + SQAIController.PostRegister(engine); + + /* Register the import statement to the global scope */ + SQAIController.DefSQStaticMethod(engine, &AIController::Import, "import", 4, ".ssi"); } diff --git a/src/script/squirrel.hpp b/src/script/squirrel.hpp index 9dd8b3e4f..163d9b655 100644 --- a/src/script/squirrel.hpp +++ b/src/script/squirrel.hpp @@ -58,6 +58,7 @@ protected: public: friend class AIScanner; friend class AIInstance; + friend class AIController; friend void squirrel_register_std(Squirrel *engine); Squirrel(); diff --git a/src/script/squirrel_helper.hpp b/src/script/squirrel_helper.hpp index 29deba674..a5a242539 100644 --- a/src/script/squirrel_helper.hpp +++ b/src/script/squirrel_helper.hpp @@ -92,6 +92,7 @@ namespace SQConvert { template <> inline int Return<char *> (HSQUIRRELVM vm, char *res) { if (res == NULL) sq_pushnull(vm); else { sq_pushstring(vm, OTTD2SQ(res), -1); free(res); } return 1; } template <> inline int Return<const char *>(HSQUIRRELVM vm, const char *res) { if (res == NULL) sq_pushnull(vm); else { sq_pushstring(vm, OTTD2SQ(res), -1); } return 1; } template <> inline int Return<void *> (HSQUIRRELVM vm, void *res) { sq_pushuserpointer(vm, res); return 1; } + template <> inline int Return<HSQOBJECT> (HSQUIRRELVM vm, HSQOBJECT res) { sq_pushobject(vm, res); return 1; } /** * To get a param from squirrel, we call this function. It converts to the right format. |