From 3da8b5097a4643d531182173df36ca4d3b45a4e2 Mon Sep 17 00:00:00 2001 From: truebrain Date: Tue, 29 Nov 2011 23:21:33 +0000 Subject: (svn r23360) -Codechange: move AIInstance to ScriptInstance, making it reusable by other script API instances --- src/ai/ai_instance.cpp | 622 +----------------------------------------- src/ai/ai_instance.hpp | 165 +---------- src/ai/api/squirrel_export.sh | 1 - 3 files changed, 13 insertions(+), 775 deletions(-) (limited to 'src/ai') diff --git a/src/ai/ai_instance.cpp b/src/ai/ai_instance.cpp index a4a30334f..bf6af96f3 100644 --- a/src/ai/ai_instance.cpp +++ b/src/ai/ai_instance.cpp @@ -80,105 +80,25 @@ #include "../company_func.h" #include "../fileio_func.h" -/** The maximum number of operations for saving or loading the data of an AI. */ -static const int MAX_SL_OPS = 100000; -/** The maximum number of operations for initial start of an AI. */ -static const int MAX_CONSTRUCTOR_OPS = 100000; - -ScriptStorage::~ScriptStorage() -{ - /* Free our pointers */ - if (event_data != NULL) ScriptEventController::FreeEventPointer(); - if (log_data != NULL) ScriptLog::FreeLogPointer(); -} - -/** - * Callback called by squirrel when an AI uses "print" and for error messages. - * @param error_msg Is this an error message? - * @param message The actual message text. - */ -static void PrintFunc(bool error_msg, const SQChar *message) -{ - /* Convert to OpenTTD internal capable string */ - ScriptController::Print(error_msg, SQ2OTTD(message)); -} - AIInstance::AIInstance() : - controller(NULL), - storage(NULL), - engine(NULL), - instance(NULL), - is_started(false), - is_dead(false), - is_save_data_on_stack(false), - suspend(0), - callback(NULL) -{ - this->storage = new ScriptStorage(); - this->engine = new Squirrel("AI"); - this->engine->SetPrintFunction(&PrintFunc); -} + ScriptInstance("AI") +{} void AIInstance::Initialize(AIInfo *info) { - ScriptObject::ActiveInstance active(this); - - this->controller = new ScriptController(); + this->versionAPI = info->GetAPIVersion(); /* Register the AIController (including the "import" command) */ SQAIController_Register(this->engine); - /* Register the API functions and classes */ - this->RegisterAPI(); - - if (!this->LoadCompatibilityScripts(info->GetAPIVersion())) { - this->Died(); - return; - } - - try { - ScriptObject::SetAllowDoCommand(false); - /* Load and execute the script for this AI */ - const char *main_script = info->GetMainScript(); - if (strcmp(main_script, "%_dummy") == 0) { - extern void AI_CreateAIDummy(HSQUIRRELVM vm); - AI_CreateAIDummy(this->engine->GetVM()); - } else if (!this->engine->LoadScript(main_script) || this->engine->IsSuspended()) { - if (this->engine->IsSuspended()) ScriptLog::Error("This AI took too long to load script. AI is not started."); - this->Died(); - return; - } - - /* Create the main-class */ - this->instance = MallocT(1); - if (!this->engine->CreateClassInstance(info->GetInstanceName(), this->controller, this->instance)) { - this->Died(); - return; - } - ScriptObject::SetAllowDoCommand(true); - } catch (Script_FatalError e) { - this->is_dead = true; - this->engine->ThrowError(e.GetErrorMessage()); - this->engine->ResumeError(); - this->Died(); - } -} - -AIInstance::~AIInstance() -{ - ScriptObject::ActiveInstance active(this); - - if (instance != NULL) this->engine->ReleaseObject(this->instance); - if (engine != NULL) delete this->engine; - delete this->storage; - delete this->controller; - free(this->instance); + ScriptInstance::Initialize(info->GetMainScript(), info->GetInstanceName()); } void AIInstance::RegisterAPI() { + ScriptInstance::RegisterAPI(); + /* Register all classes */ - squirrel_register_std(this->engine); SQAIList_Register(this->engine); SQAIAccounting_Register(this->engine); SQAIAirport_Register(this->engine); @@ -266,7 +186,7 @@ void AIInstance::RegisterAPI() SQAIWaypointList_Register(this->engine); SQAIWaypointList_Vehicle_Register(this->engine); - this->engine->SetGlobalPointer(this->engine); + if (!this->LoadCompatibilityScripts(this->versionAPI)) this->Died(); } bool AIInstance::LoadCompatibilityScripts(const char *api_version) @@ -291,21 +211,9 @@ bool AIInstance::LoadCompatibilityScripts(const char *api_version) return true; } -void AIInstance::Continue() -{ - assert(this->suspend < 0); - this->suspend = -this->suspend - 1; -} - void AIInstance::Died() { - DEBUG(ai, 0, "The AI died unexpectedly."); - this->is_dead = true; - - if (this->instance != NULL) this->engine->ReleaseObject(this->instance); - delete this->engine; - this->instance = NULL; - this->engine = NULL; + ScriptInstance::Died(); ShowAIDebugWindow(_current_company); @@ -319,517 +227,3 @@ void AIInstance::Died() } } } - -void AIInstance::GameLoop() -{ - ScriptObject::ActiveInstance active(this); - - if (this->IsDead()) return; - if (this->engine->HasScriptCrashed()) { - /* The script crashed during saving, kill it here. */ - this->Died(); - return; - } - this->controller->ticks++; - - if (this->suspend < -1) this->suspend++; // Multiplayer suspend, increase up to -1. - if (this->suspend < 0) return; // Multiplayer suspend, wait for Continue(). - if (--this->suspend > 0) return; // Singleplayer suspend, decrease to 0. - - /* If there is a callback to call, call that first */ - if (this->callback != NULL) { - if (this->is_save_data_on_stack) { - sq_poptop(this->engine->GetVM()); - this->is_save_data_on_stack = false; - } - try { - this->callback(this); - } catch (Script_Suspend e) { - this->suspend = e.GetSuspendTime(); - this->callback = e.GetSuspendCallback(); - - return; - } - } - - this->suspend = 0; - this->callback = NULL; - - if (!this->is_started) { - try { - ScriptObject::SetAllowDoCommand(false); - /* Run the constructor if it exists. Don't allow any DoCommands in it. */ - if (this->engine->MethodExists(*this->instance, "constructor")) { - if (!this->engine->CallMethod(*this->instance, "constructor", MAX_CONSTRUCTOR_OPS) || this->engine->IsSuspended()) { - if (this->engine->IsSuspended()) ScriptLog::Error("This AI took too long to initialize. AI is not started."); - this->Died(); - return; - } - } - if (!this->CallLoad() || this->engine->IsSuspended()) { - if (this->engine->IsSuspended()) ScriptLog::Error("This AI took too long in the Load function. AI is not started."); - this->Died(); - return; - } - ScriptObject::SetAllowDoCommand(true); - /* Start the AI by calling Start() */ - if (!this->engine->CallMethod(*this->instance, "Start", _settings_game.ai.ai_max_opcode_till_suspend) || !this->engine->IsSuspended()) this->Died(); - } catch (Script_Suspend e) { - this->suspend = e.GetSuspendTime(); - this->callback = e.GetSuspendCallback(); - } catch (Script_FatalError e) { - this->is_dead = true; - this->engine->ThrowError(e.GetErrorMessage()); - this->engine->ResumeError(); - this->Died(); - } - - this->is_started = true; - return; - } - if (this->is_save_data_on_stack) { - sq_poptop(this->engine->GetVM()); - this->is_save_data_on_stack = false; - } - - /* Continue the VM */ - try { - if (!this->engine->Resume(_settings_game.ai.ai_max_opcode_till_suspend)) this->Died(); - } catch (Script_Suspend e) { - this->suspend = e.GetSuspendTime(); - this->callback = e.GetSuspendCallback(); - } catch (Script_FatalError e) { - this->is_dead = true; - this->engine->ThrowError(e.GetErrorMessage()); - this->engine->ResumeError(); - this->Died(); - } -} - -void AIInstance::CollectGarbage() const -{ - if (this->is_started && !this->IsDead()) this->engine->CollectGarbage(); -} - -/* static */ void AIInstance::DoCommandReturn(AIInstance *instance) -{ - instance->engine->InsertResult(ScriptObject::GetLastCommandRes()); -} - -/* static */ void AIInstance::DoCommandReturnVehicleID(AIInstance *instance) -{ - instance->engine->InsertResult(ScriptObject::GetNewVehicleID()); -} - -/* static */ void AIInstance::DoCommandReturnSignID(AIInstance *instance) -{ - instance->engine->InsertResult(ScriptObject::GetNewSignID()); -} - -/* static */ void AIInstance::DoCommandReturnGroupID(AIInstance *instance) -{ - instance->engine->InsertResult(ScriptObject::GetNewGroupID()); -} - -ScriptStorage *AIInstance::GetStorage() -{ - return this->storage; -} - -void *AIInstance::GetLogPointer() -{ - ScriptObject::ActiveInstance active(this); - - return ScriptObject::GetLogPointer(); -} - -/* - * All data is stored in the following format: - * First 1 byte indicating if there is a data blob at all. - * 1 byte indicating the type of data. - * The data itself, this differs per type: - * - integer: a binary representation of the integer (int32). - * - string: First one byte with the string length, then a 0-terminated char - * array. The string can't be longer than 255 bytes (including - * terminating '\0'). - * - array: All data-elements of the array are saved recursive in this - * format, and ended with an element of the type - * SQSL_ARRAY_TABLE_END. - * - table: All key/value pairs are saved in this format (first key 1, then - * value 1, then key 2, etc.). All keys and values can have an - * arbitrary type (as long as it is supported by the save function - * of course). The table is ended with an element of the type - * SQSL_ARRAY_TABLE_END. - * - bool: A single byte with value 1 representing true and 0 false. - * - null: No data. - */ - -/** The type of the data that follows in the savegame. */ -enum SQSaveLoadType { - SQSL_INT = 0x00, ///< The following data is an integer. - SQSL_STRING = 0x01, ///< The following data is an string. - SQSL_ARRAY = 0x02, ///< The following data is an array. - SQSL_TABLE = 0x03, ///< The following data is an table. - SQSL_BOOL = 0x04, ///< The following data is a boolean. - SQSL_NULL = 0x05, ///< A null variable. - SQSL_ARRAY_TABLE_END = 0xFF, ///< Marks the end of an array or table, no data follows. -}; - -static byte _ai_sl_byte; ///< Used as source/target by the AI saveload code to store/load a single byte. - -/** SaveLoad array that saves/loads exactly one byte. */ -static const SaveLoad _ai_byte[] = { - SLEG_VAR(_ai_sl_byte, SLE_UINT8), - SLE_END() -}; - -static const uint AISAVE_MAX_DEPTH = 25; ///< The maximum recursive depth for items stored in the savegame. - -/* static */ bool AIInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test) -{ - if (max_depth == 0) { - ScriptLog::Error("Savedata can only be nested to 25 deep. No data saved."); - return false; - } - - switch (sq_gettype(vm, index)) { - case OT_INTEGER: { - if (!test) { - _ai_sl_byte = SQSL_INT; - SlObject(NULL, _ai_byte); - } - SQInteger res; - sq_getinteger(vm, index, &res); - if (!test) { - int value = (int)res; - SlArray(&value, 1, SLE_INT32); - } - return true; - } - - case OT_STRING: { - if (!test) { - _ai_sl_byte = SQSL_STRING; - SlObject(NULL, _ai_byte); - } - const SQChar *res; - sq_getstring(vm, index, &res); - /* @bug if a string longer than 512 characters is given to SQ2OTTD, the - * internal buffer overflows. */ - const char *buf = SQ2OTTD(res); - size_t len = strlen(buf) + 1; - if (len >= 255) { - ScriptLog::Error("Maximum string length is 254 chars. No data saved."); - return false; - } - if (!test) { - _ai_sl_byte = (byte)len; - SlObject(NULL, _ai_byte); - SlArray(const_cast(buf), len, SLE_CHAR); - } - return true; - } - - case OT_ARRAY: { - if (!test) { - _ai_sl_byte = SQSL_ARRAY; - SlObject(NULL, _ai_byte); - } - sq_pushnull(vm); - while (SQ_SUCCEEDED(sq_next(vm, index - 1))) { - /* Store the value */ - bool res = SaveObject(vm, -1, max_depth - 1, test); - sq_pop(vm, 2); - if (!res) { - sq_pop(vm, 1); - return false; - } - } - sq_pop(vm, 1); - if (!test) { - _ai_sl_byte = SQSL_ARRAY_TABLE_END; - SlObject(NULL, _ai_byte); - } - return true; - } - - case OT_TABLE: { - if (!test) { - _ai_sl_byte = SQSL_TABLE; - SlObject(NULL, _ai_byte); - } - sq_pushnull(vm); - while (SQ_SUCCEEDED(sq_next(vm, index - 1))) { - /* Store the key + value */ - bool res = SaveObject(vm, -2, max_depth - 1, test) && SaveObject(vm, -1, max_depth - 1, test); - sq_pop(vm, 2); - if (!res) { - sq_pop(vm, 1); - return false; - } - } - sq_pop(vm, 1); - if (!test) { - _ai_sl_byte = SQSL_ARRAY_TABLE_END; - SlObject(NULL, _ai_byte); - } - return true; - } - - case OT_BOOL: { - if (!test) { - _ai_sl_byte = SQSL_BOOL; - SlObject(NULL, _ai_byte); - } - SQBool res; - sq_getbool(vm, index, &res); - if (!test) { - _ai_sl_byte = res ? 1 : 0; - SlObject(NULL, _ai_byte); - } - return true; - } - - case OT_NULL: { - if (!test) { - _ai_sl_byte = SQSL_NULL; - SlObject(NULL, _ai_byte); - } - return true; - } - - default: - ScriptLog::Error("You tried to save an unsupported type. No data saved."); - return false; - } -} - -/* static */ void AIInstance::SaveEmpty() -{ - _ai_sl_byte = 0; - SlObject(NULL, _ai_byte); -} - -void AIInstance::Save() -{ - ScriptObject::ActiveInstance active(this); - - /* Don't save data if the AI didn't start yet or if it crashed. */ - if (this->engine == NULL || this->engine->HasScriptCrashed()) { - SaveEmpty(); - return; - } - - HSQUIRRELVM vm = this->engine->GetVM(); - if (this->is_save_data_on_stack) { - _ai_sl_byte = 1; - SlObject(NULL, _ai_byte); - /* Save the data that was just loaded. */ - SaveObject(vm, -1, AISAVE_MAX_DEPTH, false); - } else if (!this->is_started) { - SaveEmpty(); - return; - } else if (this->engine->MethodExists(*this->instance, "Save")) { - HSQOBJECT savedata; - /* We don't want to be interrupted during the save function. */ - bool backup_allow = ScriptObject::GetAllowDoCommand(); - ScriptObject::SetAllowDoCommand(false); - try { - if (!this->engine->CallMethod(*this->instance, "Save", &savedata, MAX_SL_OPS)) { - /* The script crashed in the Save function. We can't kill - * it here, but do so in the next AI tick. */ - SaveEmpty(); - this->engine->CrashOccurred(); - return; - } - } catch (Script_FatalError e) { - /* If we don't mark the AI as dead here cleaning up the squirrel - * stack could throw Script_FatalError again. */ - this->is_dead = true; - this->engine->ThrowError(e.GetErrorMessage()); - this->engine->ResumeError(); - SaveEmpty(); - /* We can't kill the AI here, so mark it as crashed (not dead) and - * kill it in the next AI tick. */ - this->is_dead = false; - this->engine->CrashOccurred(); - return; - } - ScriptObject::SetAllowDoCommand(backup_allow); - - if (!sq_istable(savedata)) { - ScriptLog::Error(this->engine->IsSuspended() ? "This AI took too long to Save." : "Save function should return a table."); - SaveEmpty(); - this->engine->CrashOccurred(); - return; - } - sq_pushobject(vm, savedata); - if (SaveObject(vm, -1, AISAVE_MAX_DEPTH, true)) { - _ai_sl_byte = 1; - SlObject(NULL, _ai_byte); - SaveObject(vm, -1, AISAVE_MAX_DEPTH, false); - this->is_save_data_on_stack = true; - } else { - SaveEmpty(); - this->engine->CrashOccurred(); - } - } else { - ScriptLog::Warning("Save function is not implemented"); - _ai_sl_byte = 0; - SlObject(NULL, _ai_byte); - } -} - -void AIInstance::Suspend() -{ - HSQUIRRELVM vm = this->engine->GetVM(); - Squirrel::DecreaseOps(vm, _settings_game.ai.ai_max_opcode_till_suspend); -} - -/* static */ bool AIInstance::LoadObjects(HSQUIRRELVM vm) -{ - SlObject(NULL, _ai_byte); - switch (_ai_sl_byte) { - case SQSL_INT: { - int value; - SlArray(&value, 1, SLE_INT32); - if (vm != NULL) sq_pushinteger(vm, (SQInteger)value); - return true; - } - - case SQSL_STRING: { - SlObject(NULL, _ai_byte); - static char buf[256]; - SlArray(buf, _ai_sl_byte, SLE_CHAR); - if (vm != NULL) sq_pushstring(vm, OTTD2SQ(buf), -1); - return true; - } - - case SQSL_ARRAY: { - if (vm != NULL) sq_newarray(vm, 0); - while (LoadObjects(vm)) { - if (vm != NULL) sq_arrayappend(vm, -2); - /* The value is popped from the stack by squirrel. */ - } - return true; - } - - case SQSL_TABLE: { - if (vm != NULL) sq_newtable(vm); - while (LoadObjects(vm)) { - LoadObjects(vm); - if (vm != NULL) sq_rawset(vm, -3); - /* The key (-2) and value (-1) are popped from the stack by squirrel. */ - } - return true; - } - - case SQSL_BOOL: { - SlObject(NULL, _ai_byte); - if (vm != NULL) sq_pushinteger(vm, (SQBool)(_ai_sl_byte != 0)); - return true; - } - - case SQSL_NULL: { - if (vm != NULL) sq_pushnull(vm); - return true; - } - - case SQSL_ARRAY_TABLE_END: { - return false; - } - - default: NOT_REACHED(); - } -} - -/* static */ void AIInstance::LoadEmpty() -{ - SlObject(NULL, _ai_byte); - /* Check if there was anything saved at all. */ - if (_ai_sl_byte == 0) return; - - LoadObjects(NULL); -} - -void AIInstance::Load(int version) -{ - ScriptObject::ActiveInstance active(this); - - if (this->engine == NULL || version == -1) { - LoadEmpty(); - return; - } - HSQUIRRELVM vm = this->engine->GetVM(); - - SlObject(NULL, _ai_byte); - /* Check if there was anything saved at all. */ - if (_ai_sl_byte == 0) return; - - sq_pushinteger(vm, version); - LoadObjects(vm); - this->is_save_data_on_stack = true; -} - -bool AIInstance::CallLoad() -{ - HSQUIRRELVM vm = this->engine->GetVM(); - /* Is there save data that we should load? */ - if (!this->is_save_data_on_stack) return true; - /* Whatever happens, after CallLoad the savegame data is removed from the stack. */ - this->is_save_data_on_stack = false; - - if (!this->engine->MethodExists(*this->instance, "Load")) { - ScriptLog::Warning("Loading failed: there was data for the AI to load, but the AI does not have a Load() function."); - - /* Pop the savegame data and version. */ - sq_pop(vm, 2); - return true; - } - - /* Go to the instance-root */ - sq_pushobject(vm, *this->instance); - /* Find the function-name inside the script */ - sq_pushstring(vm, OTTD2SQ("Load"), -1); - /* Change the "Load" string in a function pointer */ - sq_get(vm, -2); - /* Push the main instance as "this" object */ - sq_pushobject(vm, *this->instance); - /* Push the version data and savegame data as arguments */ - sq_push(vm, -5); - sq_push(vm, -5); - - /* Call the AI load function. sq_call removes the arguments (but not the - * function pointer) from the stack. */ - if (SQ_FAILED(sq_call(vm, 3, SQFalse, SQFalse, MAX_SL_OPS))) return false; - - /* Pop 1) The version, 2) the savegame data, 3) the object instance, 4) the function pointer. */ - sq_pop(vm, 4); - return true; -} - -SQInteger AIInstance::GetOpsTillSuspend() -{ - return this->engine->GetOpsTillSuspend(); -} - -void AIInstance::DoCommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2) -{ - ScriptObject::ActiveInstance active(this); - - ScriptObject::SetLastCommandRes(result.Succeeded()); - - if (result.Failed()) { - ScriptObject::SetLastError(ScriptError::StringToError(result.GetErrorMessage())); - } else { - ScriptObject::IncreaseDoCommandCosts(result.GetCost()); - ScriptObject::SetLastCost(result.GetCost()); - } -} - -void AIInstance::InsertEvent(class ScriptEvent *event) -{ - ScriptObject::ActiveInstance active(this); - - ScriptEventController::InsertEvent(event); -} diff --git a/src/ai/ai_instance.hpp b/src/ai/ai_instance.hpp index 60caaefd2..560155b2c 100644 --- a/src/ai/ai_instance.hpp +++ b/src/ai/ai_instance.hpp @@ -13,19 +13,12 @@ #define AI_INSTANCE_HPP #include -#include "../script/script_suspend.hpp" +#include "../script/script_instance.hpp" /** Runtime information about an AI like a pointer to the squirrel vm and the current state. */ -class AIInstance { +class AIInstance : public ScriptInstance { public: - friend class ScriptObject; - friend class ScriptController; - - /** - * Create a new AI. - */ AIInstance(); - ~AIInstance(); /** * Initialize the AI and prepare it for its first run. @@ -33,164 +26,16 @@ public: */ void Initialize(class AIInfo *info); - /** - * An AI in multiplayer waits for the server to handle his DoCommand. - * It keeps waiting for this until this function is called. - */ - void Continue(); - - /** - * Run the GameLoop of an AI. - */ - void GameLoop(); - - /** - * Let the VM collect any garbage. - */ - void CollectGarbage() const; - - /** - * Get the storage of this AI. - */ - class ScriptStorage *GetStorage(); - - /** - * Get the log pointer of this AI. - */ - void *GetLogPointer(); - - /** - * Return a true/false reply for a DoCommand. - */ - static void DoCommandReturn(AIInstance *instance); - - /** - * Return a VehicleID reply for a DoCommand. - */ - static void DoCommandReturnVehicleID(AIInstance *instance); - - /** - * Return a SignID reply for a DoCommand. - */ - static void DoCommandReturnSignID(AIInstance *instance); - - /** - * Return a GroupID reply for a DoCommand. - */ - static void DoCommandReturnGroupID(AIInstance *instance); - - /** - * Get the controller attached to the instance. - */ - class ScriptController *GetController() { return controller; } - - /** - * Return the "this AI died" value - */ - inline bool IsDead() const { return this->is_dead; } - - /** - * Call the AI Save function and save all data in the savegame. - */ - void Save(); - - /** - * Don't save any data in the savegame. - */ - static void SaveEmpty(); - - /** - * Load data from a savegame and store it on the stack. - * @param version The version of the AI when saving, or -1 if this was - * not the original AI saving the game. - */ - void Load(int version); - - /** - * Load and discard data from a savegame. - */ - static void LoadEmpty(); - - /** - * Reduces the number of opcodes the AI have left to zero. Unless - * the AI is in a state where it cannot suspend it will be suspended - * for the reminder of the current tick. This function is safe to - * call from within a function called by the AI. - */ - void Suspend(); - - /** - * Get the number of operations the AI can execute before being suspended. - * This function is safe to call from within a function called by the AI. - * @return The number of operations to execute. - */ - SQInteger GetOpsTillSuspend(); - - /** - * DoCommand callback function for all commands executed by AIs. - * @param result The result of the command. - * @param tile The tile on which the command was executed. - * @param p1 p1 as given to DoCommandPInternal. - * @param p2 p2 as given to DoCommandPInternal. - */ - void DoCommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2); - - /** - * Insert an event for this AI. - * @param event The event to insert. - */ - void InsertEvent(class ScriptEvent *event); - private: - class ScriptController *controller; ///< The AI main class. - class ScriptStorage *storage; ///< Some global information for each running AI. - class Squirrel *engine; ///< A wrapper around the squirrel vm. - SQObject *instance; ///< Squirrel-pointer to the AI main class. + const char *versionAPI; ///< Current API used by this script. - bool is_started; ///< Is the AIs constructor executed? - bool is_dead; ///< True if the AI has been stopped. - bool is_save_data_on_stack; ///< Is the save data still on the squirrel stack? - int suspend; ///< The amount of ticks to suspend this AI before it's allowed to continue. - Script_SuspendCallbackProc *callback; ///< Callback that should be called in the next tick the AI runs. - - /** - * Register all API functions to the VM. - */ - void RegisterAPI(); + /* virtual */ void RegisterAPI(); + /* virtual */ void Died(); /** * Load squirrel scripts to emulate an older API. */ bool LoadCompatibilityScripts(const char *api_version); - - /** - * Tell the AI it died. - */ - void Died(); - - /** - * Call the AI Load function if it exists and data was loaded - * from a savegame. - */ - bool CallLoad(); - - /** - * Save one object (int / string / array / table) to the savegame. - * @param vm The virtual machine to get all the data from. - * @param index The index on the squirrel stack of the element to save. - * @param max_depth The maximum depth recursive arrays / tables will be stored - * with before an error is returned. - * @param test If true, don't really store the data but only check if it is - * valid. - * @return True if the saving was successful. - */ - static bool SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test); - - /** - * Load all objects from a savegame. - * @return True if the loading was successful. - */ - static bool LoadObjects(HSQUIRRELVM vm); }; #endif /* AI_INSTANCE_HPP */ diff --git a/src/ai/api/squirrel_export.sh b/src/ai/api/squirrel_export.sh index 725890951..4cb66a7e2 100755 --- a/src/ai/api/squirrel_export.sh +++ b/src/ai/api/squirrel_export.sh @@ -91,7 +91,6 @@ echo " /\/\* Register all classes \*\// { print \$0 gsub(\"^.*/\", \"\") - print \" squirrel_register_std(this->engine);\" \$0 # List needs to be registered with squirrel before all List subclasses. print \" SQ${apiuc}List_Register(this->engine);\" \$0 split(\"`grep '^void SQ'${apiuc}'.*_Register(Squirrel \*engine)$' *.hpp.sq | grep -v 'SQ'${apiuc}'List_Register' | sed 's/^.*void //;s/Squirrel \*/this->/;s/$/;/;s/_Register/0000Register/g;' | sort | sed 's/0000Register/_Register/g' | tr -d '\r' | tr '\n' ' '`\", regs, \" \") -- cgit v1.2.3-70-g09d2