(svn r23295) -Codechange: put ImportLibrary in AIController (and document the parameters for NoAI docs)

This commit is contained in:
truebrain
2011-11-23 13:39:36 +00:00
parent 492c96d214
commit d03bbdd4ac
13 changed files with 106 additions and 132 deletions

View File

@@ -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);
void AIController::AddLoadedLibrary(const char *library_name, const char *fake_class_name)
{
this->loaded_library[strdup(library_name)] = strdup(fake_class_name);
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);
}
/* 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;
}

View File

@@ -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 */

View File

@@ -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");
}