(svn r15467) -Fix [NoAI]: AIs with an error in their info.nut are no longer available in-game.
This commit is contained in:
@@ -45,9 +45,9 @@ AILibrary::~AILibrary()
|
||||
free((void *)this->category);
|
||||
}
|
||||
|
||||
void AIFileInfo::GetSettings() const
|
||||
bool AIFileInfo::GetSettings()
|
||||
{
|
||||
this->engine->CallMethod(*this->SQ_instance, "GetSettings", NULL, -1);
|
||||
return this->engine->CallMethod(*this->SQ_instance, "GetSettings", NULL, -1);
|
||||
}
|
||||
|
||||
bool AIFileInfo::CheckMethod(const char *name) const
|
||||
@@ -90,13 +90,13 @@ bool AIFileInfo::CheckMethod(const char *name) const
|
||||
info->main_script = strdup(info->base->GetMainScript());
|
||||
|
||||
/* Cache the data the info file gives us. */
|
||||
info->author = info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetAuthor");
|
||||
info->name = info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetName");
|
||||
info->short_name = info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetShortName");
|
||||
info->description = info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetDescription");
|
||||
info->date = info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetDate");
|
||||
info->version = info->engine->CallIntegerMethod(*info->SQ_instance, "GetVersion");
|
||||
info->instance_name = info->engine->CallStringMethodStrdup(*info->SQ_instance, "CreateInstance");
|
||||
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetAuthor", &info->author)) return SQ_ERROR;
|
||||
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetName", &info->name)) return SQ_ERROR;
|
||||
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetShortName", &info->short_name)) return SQ_ERROR;
|
||||
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetDescription", &info->description)) return SQ_ERROR;
|
||||
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetDate", &info->date)) return SQ_ERROR;
|
||||
if (!info->engine->CallIntegerMethod(*info->SQ_instance, "GetVersion", &info->version)) return SQ_ERROR;
|
||||
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "CreateInstance", &info->instance_name)) return SQ_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -118,10 +118,10 @@ bool AIFileInfo::CheckMethod(const char *name) const
|
||||
|
||||
/* Check if we have settings */
|
||||
if (info->engine->MethodExists(*info->SQ_instance, "GetSettings")) {
|
||||
info->GetSettings();
|
||||
if (!info->GetSettings()) return SQ_ERROR;
|
||||
}
|
||||
if (info->engine->MethodExists(*info->SQ_instance, "MinVersionToLoad")) {
|
||||
info->min_loadable_version = info->engine->CallIntegerMethod(*info->SQ_instance, "MinVersionToLoad");
|
||||
if (!info->engine->CallIntegerMethod(*info->SQ_instance, "MinVersionToLoad", &info->min_loadable_version)) return SQ_ERROR;
|
||||
} else {
|
||||
info->min_loadable_version = info->GetVersion();
|
||||
}
|
||||
@@ -367,7 +367,10 @@ int AIInfo::GetSettingDefaultValue(const char *name) const
|
||||
}
|
||||
|
||||
/* Cache the category */
|
||||
library->category = library->engine->CallStringMethodStrdup(*library->SQ_instance, "GetCategory");
|
||||
if (!library->engine->CallStringMethodStrdup(*library->SQ_instance, "GetCategory", &library->category)) {
|
||||
delete library;
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
/* Register the Library to the base system */
|
||||
library->base->RegisterLibrary(library);
|
||||
|
@@ -72,7 +72,7 @@ public:
|
||||
/**
|
||||
* Get the settings of the AI.
|
||||
*/
|
||||
void GetSettings() const;
|
||||
bool GetSettings();
|
||||
|
||||
/**
|
||||
* Get the date of the AI.
|
||||
|
@@ -249,6 +249,11 @@ void AIInstance::Died()
|
||||
void AIInstance::GameLoop()
|
||||
{
|
||||
if (this->is_dead) 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.
|
||||
@@ -275,12 +280,12 @@ void AIInstance::GameLoop()
|
||||
AIObject::SetAllowDoCommand(false);
|
||||
/* Run the constructor if it exists. Don't allow any DoCommands in it. */
|
||||
if (this->engine->MethodExists(*this->instance, "constructor")) {
|
||||
this->engine->CallMethod(*this->instance, "constructor");
|
||||
if (!this->engine->CallMethod(*this->instance, "constructor")) { this->Died(); return; }
|
||||
}
|
||||
this->CallLoad();
|
||||
if (!this->CallLoad()) { this->Died(); return; }
|
||||
AIObject::SetAllowDoCommand(true);
|
||||
/* Start the AI by calling Start() */
|
||||
if (!this->engine->CallMethod(*this->instance, "Start", _settings_game.ai.ai_max_opcode_till_suspend)) this->Died();
|
||||
if (!this->engine->CallMethod(*this->instance, "Start", _settings_game.ai.ai_max_opcode_till_suspend) || !this->engine->IsSuspended()) this->Died();
|
||||
} catch (AI_VMSuspend e) {
|
||||
this->suspend = e.GetSuspendTime();
|
||||
this->callback = e.GetSuspendCallback();
|
||||
@@ -500,8 +505,8 @@ enum {
|
||||
|
||||
void AIInstance::Save()
|
||||
{
|
||||
/* Don't save data if the AI didn't start yet. */
|
||||
if (this->engine == NULL) {
|
||||
/* Don't save data if the AI didn't start yet or if it crashed. */
|
||||
if (this->engine == NULL || this->engine->HasScriptCrashed()) {
|
||||
SaveEmpty();
|
||||
return;
|
||||
}
|
||||
@@ -526,7 +531,12 @@ void AIInstance::Save()
|
||||
/* We don't want to be interrupted during the save function. */
|
||||
bool backup_allow = AIObject::GetAllowDoCommand();
|
||||
AIObject::SetAllowDoCommand(false);
|
||||
this->engine->CallMethod(*this->instance, "Save", &savedata);
|
||||
if (!this->engine->CallMethod(*this->instance, "Save", &savedata)) {
|
||||
/* The script crashed in the Save function. We can't kill
|
||||
* it here, but do so in the next AI tick. */
|
||||
SaveEmpty();
|
||||
return;
|
||||
}
|
||||
AIObject::SetAllowDoCommand(backup_allow);
|
||||
|
||||
if (!sq_istable(savedata)) {
|
||||
@@ -637,21 +647,21 @@ void AIInstance::Load(int version)
|
||||
sq_pushbool(vm, true);
|
||||
}
|
||||
|
||||
void AIInstance::CallLoad()
|
||||
bool AIInstance::CallLoad()
|
||||
{
|
||||
HSQUIRRELVM vm = this->engine->GetVM();
|
||||
/* Is there save data that we should load? */
|
||||
SQBool res;
|
||||
sq_getbool(vm, -1, &res);
|
||||
sq_poptop(vm);
|
||||
if (!res) return;
|
||||
if (!res) return true;
|
||||
|
||||
if (!this->engine->MethodExists(*this->instance, "Load")) {
|
||||
AILog::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;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Go to the instance-root */
|
||||
@@ -668,8 +678,9 @@ void AIInstance::CallLoad()
|
||||
|
||||
/* Call the AI load function. sq_call removes the arguments (but not the
|
||||
* function pointer) from the stack. */
|
||||
sq_call(vm, 3, SQFalse, SQFalse);
|
||||
if (SQ_FAILED(sq_call(vm, 3, SQFalse, SQFalse))) return false;
|
||||
|
||||
/* Pop 1) The version, 2) the savegame data, 3) the object instance, 4) the function pointer. */
|
||||
sq_pop(vm, 4);
|
||||
return true;
|
||||
}
|
||||
|
@@ -100,7 +100,7 @@ public:
|
||||
* Call the AI Load function if it exists and data was loaded
|
||||
* from a savegame.
|
||||
*/
|
||||
void CallLoad();
|
||||
bool CallLoad();
|
||||
|
||||
/**
|
||||
* Load and discard data from a savegame.
|
||||
|
@@ -88,6 +88,8 @@ void AIScanner::ScanDir(const char *dirname, bool library_scan, bool library_rec
|
||||
if (!FioCheckFileExists(info_script, AI_DIR) || !FioCheckFileExists(main_script, AI_DIR)) continue;
|
||||
|
||||
DEBUG(ai, 6, "Loading AI at location '%s'", main_script);
|
||||
/* We don't care if one of the other scripst failed to load. */
|
||||
this->engine->ResetCrashed();
|
||||
this->engine->LoadScript(info_script);
|
||||
} else {
|
||||
char library_script[MAX_PATH];
|
||||
@@ -100,6 +102,8 @@ void AIScanner::ScanDir(const char *dirname, bool library_scan, bool library_rec
|
||||
if (!FioCheckFileExists(library_script, AI_LIBRARY_DIR) || !FioCheckFileExists(main_script, AI_LIBRARY_DIR)) continue;
|
||||
|
||||
DEBUG(ai, 6, "Loading AI Library at location '%s'", main_script);
|
||||
/* We don't care if one of the other scripst failed to load. */
|
||||
this->engine->ResetCrashed();
|
||||
this->engine->LoadScript(library_script);
|
||||
}
|
||||
}
|
||||
@@ -157,6 +161,7 @@ AIScanner::AIScanner() :
|
||||
this->ScanAIDir();
|
||||
|
||||
/* Create the dummy AI */
|
||||
this->engine->ResetCrashed();
|
||||
extern void AI_CreateAIInfoDummy(HSQUIRRELVM vm);
|
||||
AI_CreateAIInfoDummy(this->engine->GetVM());
|
||||
}
|
||||
|
Reference in New Issue
Block a user