00001
00002
00005 #include "../stdafx.h"
00006 #include "../debug.h"
00007 #include "../settings_type.h"
00008 #include "../vehicle_base.h"
00009 #include "../saveload/saveload.h"
00010 #include "../gui.h"
00011 #include "table/strings.h"
00012
00013 #include <squirrel.h>
00014 #include "../script/squirrel.hpp"
00015 #include "../script/squirrel_helper.hpp"
00016 #include "../script/squirrel_class.hpp"
00017 #include "../script/squirrel_std.hpp"
00018
00019 #define DEFINE_SCRIPT_FILES
00020
00021 #include "ai_info.hpp"
00022 #include "ai_config.hpp"
00023 #include "ai_storage.hpp"
00024 #include "ai_instance.hpp"
00025 #include "ai_gui.hpp"
00026
00027
00028
00029 #include "api/ai_abstractlist.hpp.sq"
00030 #include "api/ai_accounting.hpp.sq"
00031 #include "api/ai_airport.hpp.sq"
00032 #include "api/ai_base.hpp.sq"
00033 #include "api/ai_bridge.hpp.sq"
00034 #include "api/ai_bridgelist.hpp.sq"
00035 #include "api/ai_cargo.hpp.sq"
00036 #include "api/ai_cargolist.hpp.sq"
00037 #include "api/ai_company.hpp.sq"
00038 #include "api/ai_controller.hpp.sq"
00039 #include "api/ai_date.hpp.sq"
00040 #include "api/ai_depotlist.hpp.sq"
00041 #include "api/ai_engine.hpp.sq"
00042 #include "api/ai_enginelist.hpp.sq"
00043 #include "api/ai_error.hpp.sq"
00044 #include "api/ai_event.hpp.sq"
00045 #include "api/ai_event_types.hpp.sq"
00046 #include "api/ai_execmode.hpp.sq"
00047 #include "api/ai_gamesettings.hpp.sq"
00048 #include "api/ai_group.hpp.sq"
00049 #include "api/ai_grouplist.hpp.sq"
00050 #include "api/ai_industry.hpp.sq"
00051 #include "api/ai_industrylist.hpp.sq"
00052 #include "api/ai_industrytype.hpp.sq"
00053 #include "api/ai_industrytypelist.hpp.sq"
00054 #include "api/ai_list.hpp.sq"
00055 #include "api/ai_log.hpp.sq"
00056 #include "api/ai_map.hpp.sq"
00057 #include "api/ai_marine.hpp.sq"
00058 #include "api/ai_order.hpp.sq"
00059 #include "api/ai_rail.hpp.sq"
00060 #include "api/ai_railtypelist.hpp.sq"
00061 #include "api/ai_road.hpp.sq"
00062 #include "api/ai_sign.hpp.sq"
00063 #include "api/ai_signlist.hpp.sq"
00064 #include "api/ai_station.hpp.sq"
00065 #include "api/ai_stationlist.hpp.sq"
00066 #include "api/ai_subsidy.hpp.sq"
00067 #include "api/ai_subsidylist.hpp.sq"
00068 #include "api/ai_testmode.hpp.sq"
00069 #include "api/ai_tile.hpp.sq"
00070 #include "api/ai_tilelist.hpp.sq"
00071 #include "api/ai_town.hpp.sq"
00072 #include "api/ai_townlist.hpp.sq"
00073 #include "api/ai_tunnel.hpp.sq"
00074 #include "api/ai_vehicle.hpp.sq"
00075 #include "api/ai_vehiclelist.hpp.sq"
00076 #include "api/ai_waypoint.hpp.sq"
00077 #include "api/ai_waypointlist.hpp.sq"
00078
00079 #undef DEFINE_SCRIPT_FILES
00080
00081 AIInstance *AIInstance::current_instance = NULL;
00082
00083 AIStorage::~AIStorage()
00084 {
00085
00086 if (event_data != NULL) AIEventController::FreeEventPointer();
00087 if (log_data != NULL) AILog::FreeLogPointer();
00088 }
00089
00090 static void PrintFunc(bool error_msg, const SQChar *message)
00091 {
00092
00093 AIController::Print(error_msg, FS2OTTD(message));
00094 }
00095
00096 AIInstance::AIInstance(AIInfo *info) :
00097 controller(NULL),
00098 storage(NULL),
00099 engine(NULL),
00100 instance(NULL),
00101 is_started(false),
00102 is_dead(false),
00103 is_save_data_on_stack(false),
00104 suspend(0),
00105 callback(NULL)
00106 {
00107
00108 GetCompany(_current_company)->ai_instance = this;
00109 AIInstance::current_instance = this;
00110
00111 this->controller = new AIController();
00112 this->storage = new AIStorage();
00113 this->engine = new Squirrel();
00114 this->engine->SetPrintFunction(&PrintFunc);
00115
00116
00117 this->engine->AddMethod("import", &AILibrary::Import, 4, ".ssi");
00118
00119
00120 SQAIController_Register(this->engine);
00121
00122
00123 this->RegisterAPI();
00124
00125 try {
00126 AIObject::SetAllowDoCommand(false);
00127
00128 const char *main_script = info->GetMainScript();
00129 if (strcmp(main_script, "%_dummy") == 0) {
00130 extern void AI_CreateAIDummy(HSQUIRRELVM vm);
00131 AI_CreateAIDummy(this->engine->GetVM());
00132 } else if (!this->engine->LoadScript(main_script) || this->engine->IsSuspended()) {
00133 if (this->engine->IsSuspended()) AILog::Error("This AI took too long to load script. AI is not started.");
00134 this->Died();
00135 return;
00136 }
00137
00138
00139 this->instance = MallocT<SQObject>(1);
00140 if (!this->engine->CreateClassInstance(info->GetInstanceName(), this->controller, this->instance)) {
00141 this->Died();
00142 return;
00143 }
00144 AIObject::SetAllowDoCommand(true);
00145 } catch (AI_FatalError e) {
00146 this->is_dead = true;
00147 this->engine->ThrowError(e.GetErrorMessage());
00148 this->engine->ResumeError();
00149 this->Died();
00150 }
00151 }
00152
00153 AIInstance::~AIInstance()
00154 {
00155 if (instance != NULL) this->engine->ReleaseObject(this->instance);
00156 if (engine != NULL) delete this->engine;
00157 delete this->storage;
00158 delete this->controller;
00159 free(this->instance);
00160 }
00161
00162 void AIInstance::RegisterAPI()
00163 {
00164
00165 squirrel_register_std(this->engine);
00166 SQAIAbstractList_Register(this->engine);
00167 SQAIAccounting_Register(this->engine);
00168 SQAIAirport_Register(this->engine);
00169 SQAIBase_Register(this->engine);
00170 SQAIBridge_Register(this->engine);
00171 SQAIBridgeList_Register(this->engine);
00172 SQAIBridgeList_Length_Register(this->engine);
00173 SQAICargo_Register(this->engine);
00174 SQAICargoList_Register(this->engine);
00175 SQAICargoList_IndustryAccepting_Register(this->engine);
00176 SQAICargoList_IndustryProducing_Register(this->engine);
00177 SQAICompany_Register(this->engine);
00178 SQAIDate_Register(this->engine);
00179 SQAIDepotList_Register(this->engine);
00180 SQAIEngine_Register(this->engine);
00181 SQAIEngineList_Register(this->engine);
00182 SQAIError_Register(this->engine);
00183 SQAIEvent_Register(this->engine);
00184 SQAIEventCompanyBankrupt_Register(this->engine);
00185 SQAIEventCompanyInTrouble_Register(this->engine);
00186 SQAIEventCompanyMerger_Register(this->engine);
00187 SQAIEventCompanyNew_Register(this->engine);
00188 SQAIEventController_Register(this->engine);
00189 SQAIEventDisasterZeppelinerCleared_Register(this->engine);
00190 SQAIEventDisasterZeppelinerCrashed_Register(this->engine);
00191 SQAIEventEngineAvailable_Register(this->engine);
00192 SQAIEventEnginePreview_Register(this->engine);
00193 SQAIEventIndustryClose_Register(this->engine);
00194 SQAIEventIndustryOpen_Register(this->engine);
00195 SQAIEventStationFirstVehicle_Register(this->engine);
00196 SQAIEventSubsidyAwarded_Register(this->engine);
00197 SQAIEventSubsidyExpired_Register(this->engine);
00198 SQAIEventSubsidyOffer_Register(this->engine);
00199 SQAIEventSubsidyOfferExpired_Register(this->engine);
00200 SQAIEventVehicleCrashed_Register(this->engine);
00201 SQAIEventVehicleLost_Register(this->engine);
00202 SQAIEventVehicleUnprofitable_Register(this->engine);
00203 SQAIEventVehicleWaitingInDepot_Register(this->engine);
00204 SQAIExecMode_Register(this->engine);
00205 SQAIGameSettings_Register(this->engine);
00206 SQAIGroup_Register(this->engine);
00207 SQAIGroupList_Register(this->engine);
00208 SQAIIndustry_Register(this->engine);
00209 SQAIIndustryList_Register(this->engine);
00210 SQAIIndustryList_CargoAccepting_Register(this->engine);
00211 SQAIIndustryList_CargoProducing_Register(this->engine);
00212 SQAIIndustryType_Register(this->engine);
00213 SQAIIndustryTypeList_Register(this->engine);
00214 SQAIList_Register(this->engine);
00215 SQAILog_Register(this->engine);
00216 SQAIMap_Register(this->engine);
00217 SQAIMarine_Register(this->engine);
00218 SQAIOrder_Register(this->engine);
00219 SQAIRail_Register(this->engine);
00220 SQAIRailTypeList_Register(this->engine);
00221 SQAIRoad_Register(this->engine);
00222 SQAISign_Register(this->engine);
00223 SQAISignList_Register(this->engine);
00224 SQAIStation_Register(this->engine);
00225 SQAIStationList_Register(this->engine);
00226 SQAIStationList_Vehicle_Register(this->engine);
00227 SQAISubsidy_Register(this->engine);
00228 SQAISubsidyList_Register(this->engine);
00229 SQAITestMode_Register(this->engine);
00230 SQAITile_Register(this->engine);
00231 SQAITileList_Register(this->engine);
00232 SQAITileList_IndustryAccepting_Register(this->engine);
00233 SQAITileList_IndustryProducing_Register(this->engine);
00234 SQAITileList_StationType_Register(this->engine);
00235 SQAITown_Register(this->engine);
00236 SQAITownList_Register(this->engine);
00237 SQAITunnel_Register(this->engine);
00238 SQAIVehicle_Register(this->engine);
00239 SQAIVehicleList_Register(this->engine);
00240 SQAIVehicleList_DefaultGroup_Register(this->engine);
00241 SQAIVehicleList_Group_Register(this->engine);
00242 SQAIVehicleList_SharedOrders_Register(this->engine);
00243 SQAIVehicleList_Station_Register(this->engine);
00244 SQAIWaypoint_Register(this->engine);
00245 SQAIWaypointList_Register(this->engine);
00246 SQAIWaypointList_Vehicle_Register(this->engine);
00247
00248 this->engine->SetGlobalPointer(this->engine);
00249 }
00250
00251 void AIInstance::Continue()
00252 {
00253 assert(this->suspend < 0);
00254 this->suspend = -this->suspend - 1;
00255 }
00256
00257 void AIInstance::Died()
00258 {
00259 DEBUG(ai, 0, "The AI died unexpectedly.");
00260 this->is_dead = true;
00261
00262 if (this->instance != NULL) this->engine->ReleaseObject(this->instance);
00263 delete this->engine;
00264 this->instance = NULL;
00265 this->engine = NULL;
00266
00267 ShowAIDebugWindow(_current_company);
00268
00269 const AIInfo *info = AIConfig::GetConfig(_current_company)->GetInfo();
00270 if (info != NULL) {
00271 ShowErrorMessage(INVALID_STRING_ID, STR_AI_PLEASE_REPORT_CRASH, 0, 0);
00272
00273 if (info->GetURL() != NULL) {
00274 AILog::Info("Please report the error to the following URL:");
00275 AILog::Info(info->GetURL());
00276 }
00277 }
00278 }
00279
00280 void AIInstance::GameLoop()
00281 {
00282 if (this->IsDead()) return;
00283 if (this->engine->HasScriptCrashed()) {
00284
00285 this->Died();
00286 return;
00287 }
00288 this->controller->ticks++;
00289
00290 if (this->suspend < -1) this->suspend++;
00291 if (this->suspend < 0) return;
00292 if (--this->suspend > 0) return;
00293
00294
00295 if (this->callback != NULL) {
00296 if (this->is_save_data_on_stack) {
00297 sq_poptop(this->engine->GetVM());
00298 this->is_save_data_on_stack = false;
00299 }
00300 try {
00301 this->callback(this);
00302 } catch (AI_VMSuspend e) {
00303 this->suspend = e.GetSuspendTime();
00304 this->callback = e.GetSuspendCallback();
00305
00306 return;
00307 }
00308 }
00309
00310 this->suspend = 0;
00311 this->callback = NULL;
00312
00313 if (!this->is_started) {
00314 try {
00315 AIObject::SetAllowDoCommand(false);
00316
00317 if (this->engine->MethodExists(*this->instance, "constructor")) {
00318 if (!this->engine->CallMethod(*this->instance, "constructor", 100000) || this->engine->IsSuspended()) {
00319 if (this->engine->IsSuspended()) AILog::Error("This AI took too long to initialize. AI is not started.");
00320 this->Died();
00321 return;
00322 }
00323 }
00324 if (!this->CallLoad() || this->engine->IsSuspended()) {
00325 if (this->engine->IsSuspended()) AILog::Error("This AI took too long in the Load function. AI is not started.");
00326 this->Died();
00327 return;
00328 }
00329 AIObject::SetAllowDoCommand(true);
00330
00331 if (!this->engine->CallMethod(*this->instance, "Start", _settings_game.ai.ai_max_opcode_till_suspend) || !this->engine->IsSuspended()) this->Died();
00332 } catch (AI_VMSuspend e) {
00333 this->suspend = e.GetSuspendTime();
00334 this->callback = e.GetSuspendCallback();
00335 } catch (AI_FatalError e) {
00336 this->is_dead = true;
00337 this->engine->ThrowError(e.GetErrorMessage());
00338 this->engine->ResumeError();
00339 this->Died();
00340 }
00341
00342 this->is_started = true;
00343 return;
00344 }
00345 if (this->is_save_data_on_stack) {
00346 sq_poptop(this->engine->GetVM());
00347 this->is_save_data_on_stack = false;
00348 }
00349
00350
00351 try {
00352 if (!this->engine->Resume(_settings_game.ai.ai_max_opcode_till_suspend)) this->Died();
00353 } catch (AI_VMSuspend e) {
00354 this->suspend = e.GetSuspendTime();
00355 this->callback = e.GetSuspendCallback();
00356 } catch (AI_FatalError e) {
00357 this->is_dead = true;
00358 this->engine->ThrowError(e.GetErrorMessage());
00359 this->engine->ResumeError();
00360 this->Died();
00361 }
00362 }
00363
00364 void AIInstance::CollectGarbage()
00365 {
00366 if (this->is_started && !this->IsDead()) this->engine->CollectGarbage();
00367 }
00368
00369 void AIInstance::DoCommandReturn(AIInstance *instance)
00370 {
00371 instance->engine->InsertResult(AIObject::GetLastCommandRes());
00372 }
00373
00374 void AIInstance::DoCommandReturnVehicleID(AIInstance *instance)
00375 {
00376 instance->engine->InsertResult(AIObject::GetNewVehicleID());
00377 }
00378
00379 void AIInstance::DoCommandReturnSignID(AIInstance *instance)
00380 {
00381 instance->engine->InsertResult(AIObject::GetNewSignID());
00382 }
00383
00384 void AIInstance::DoCommandReturnGroupID(AIInstance *instance)
00385 {
00386 instance->engine->InsertResult(AIObject::GetNewGroupID());
00387 }
00388
00389 AIStorage *AIInstance::GetStorage()
00390 {
00391 assert(IsValidCompanyID(_current_company) && !IsHumanCompany(_current_company));
00392 return GetCompany(_current_company)->ai_instance->storage;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00417 enum SQSaveLoadType {
00418 SQSL_INT = 0x00,
00419 SQSL_STRING = 0x01,
00420 SQSL_ARRAY = 0x02,
00421 SQSL_TABLE = 0x03,
00422 SQSL_BOOL = 0x04,
00423 SQSL_NULL = 0x05,
00424 SQSL_ARRAY_TABLE_END = 0xFF,
00425 };
00426
00427 static byte _ai_sl_byte;
00428
00429 static const SaveLoad _ai_byte[] = {
00430 SLEG_VAR(_ai_sl_byte, SLE_UINT8),
00431 SLE_END()
00432 };
00433
00434 enum {
00435 AISAVE_MAX_DEPTH = 25,
00436 };
00437
00438 bool AIInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test)
00439 {
00440 if (max_depth == 0) {
00441 AILog::Error("Savedata can only be nested to 25 deep. No data saved.");
00442 return false;
00443 }
00444
00445 switch (sq_gettype(vm, index)) {
00446 case OT_INTEGER: {
00447 if (!test) {
00448 _ai_sl_byte = SQSL_INT;
00449 SlObject(NULL, _ai_byte);
00450 }
00451 SQInteger res;
00452 sq_getinteger(vm, index, &res);
00453 if (!test) {
00454 int value = (int)res;
00455 SlArray(&value, 1, SLE_INT32);
00456 }
00457 return true;
00458 }
00459
00460 case OT_STRING: {
00461 if (!test) {
00462 _ai_sl_byte = SQSL_STRING;
00463 SlObject(NULL, _ai_byte);
00464 }
00465 const SQChar *res;
00466 sq_getstring(vm, index, &res);
00467
00468
00469 const char *buf = FS2OTTD(res);
00470 size_t len = strlen(buf) + 1;
00471 if (len >= 255) {
00472 AILog::Error("Maximum string length is 254 chars. No data saved.");
00473 return false;
00474 }
00475 if (!test) {
00476 _ai_sl_byte = (byte)len;
00477 SlObject(NULL, _ai_byte);
00478 SlArray((void*)buf, len, SLE_CHAR);
00479 }
00480 return true;
00481 }
00482
00483 case OT_ARRAY: {
00484 if (!test) {
00485 _ai_sl_byte = SQSL_ARRAY;
00486 SlObject(NULL, _ai_byte);
00487 }
00488 sq_pushnull(vm);
00489 while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
00490
00491 bool res = SaveObject(vm, -1, max_depth - 1, test);
00492 sq_pop(vm, 2);
00493 if (!res) {
00494 sq_pop(vm, 1);
00495 return false;
00496 }
00497 }
00498 sq_pop(vm, 1);
00499 if (!test) {
00500 _ai_sl_byte = SQSL_ARRAY_TABLE_END;
00501 SlObject(NULL, _ai_byte);
00502 }
00503 return true;
00504 }
00505
00506 case OT_TABLE: {
00507 if (!test) {
00508 _ai_sl_byte = SQSL_TABLE;
00509 SlObject(NULL, _ai_byte);
00510 }
00511 sq_pushnull(vm);
00512 while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
00513
00514 bool res = SaveObject(vm, -2, max_depth - 1, test) && SaveObject(vm, -1, max_depth - 1, test);
00515 sq_pop(vm, 2);
00516 if (!res) {
00517 sq_pop(vm, 1);
00518 return false;
00519 }
00520 }
00521 sq_pop(vm, 1);
00522 if (!test) {
00523 _ai_sl_byte = SQSL_ARRAY_TABLE_END;
00524 SlObject(NULL, _ai_byte);
00525 }
00526 return true;
00527 }
00528
00529 case OT_BOOL: {
00530 if (!test) {
00531 _ai_sl_byte = SQSL_BOOL;
00532 SlObject(NULL, _ai_byte);
00533 }
00534 SQBool res;
00535 sq_getbool(vm, index, &res);
00536 if (!test) {
00537 _ai_sl_byte = res ? 1 : 0;
00538 SlObject(NULL, _ai_byte);
00539 }
00540 return true;
00541 }
00542
00543 case OT_NULL: {
00544 if (!test) {
00545 _ai_sl_byte = SQSL_NULL;
00546 SlObject(NULL, _ai_byte);
00547 }
00548 return true;
00549 }
00550
00551 default:
00552 AILog::Error("You tried to save an unsupported type. No data saved.");
00553 return false;
00554 }
00555 }
00556
00557 void AIInstance::SaveEmpty()
00558 {
00559 _ai_sl_byte = 0;
00560 SlObject(NULL, _ai_byte);
00561 }
00562
00563 void AIInstance::Save()
00564 {
00565
00566 if (this->engine == NULL || this->engine->HasScriptCrashed()) {
00567 SaveEmpty();
00568 return;
00569 }
00570
00571 HSQUIRRELVM vm = this->engine->GetVM();
00572 if (this->is_save_data_on_stack) {
00573 _ai_sl_byte = 1;
00574 SlObject(NULL, _ai_byte);
00575
00576 SaveObject(vm, -1, AISAVE_MAX_DEPTH, false);
00577 } else if (!this->is_started) {
00578 SaveEmpty();
00579 return;
00580 } else if (this->engine->MethodExists(*this->instance, "Save")) {
00581 HSQOBJECT savedata;
00582
00583 bool backup_allow = AIObject::GetAllowDoCommand();
00584 AIObject::SetAllowDoCommand(false);
00585 try {
00586 if (!this->engine->CallMethod(*this->instance, "Save", &savedata)) {
00587
00588
00589 SaveEmpty();
00590 this->engine->CrashOccurred();
00591 return;
00592 }
00593 } catch (AI_FatalError e) {
00594
00595
00596 this->is_dead = true;
00597 this->engine->ThrowError(e.GetErrorMessage());
00598 this->engine->ResumeError();
00599 SaveEmpty();
00600
00601
00602 this->is_dead = false;
00603 this->engine->CrashOccurred();
00604 return;
00605 }
00606 AIObject::SetAllowDoCommand(backup_allow);
00607
00608 if (!sq_istable(savedata)) {
00609 AILog::Error("Save function should return a table.");
00610 SaveEmpty();
00611 this->engine->CrashOccurred();
00612 return;
00613 }
00614 sq_pushobject(vm, savedata);
00615 if (SaveObject(vm, -1, AISAVE_MAX_DEPTH, true)) {
00616 _ai_sl_byte = 1;
00617 SlObject(NULL, _ai_byte);
00618 SaveObject(vm, -1, AISAVE_MAX_DEPTH, false);
00619 this->is_save_data_on_stack = true;
00620 } else {
00621 SaveEmpty();
00622 this->engine->CrashOccurred();
00623 }
00624 } else {
00625 AILog::Warning("Save function is not implemented");
00626 _ai_sl_byte = 0;
00627 SlObject(NULL, _ai_byte);
00628 }
00629
00630 }
00631
00632 bool AIInstance::LoadObjects(HSQUIRRELVM vm)
00633 {
00634 SlObject(NULL, _ai_byte);
00635 switch (_ai_sl_byte) {
00636 case SQSL_INT: {
00637 int value;
00638 SlArray(&value, 1, SLE_INT32);
00639 if (vm != NULL) sq_pushinteger(vm, (SQInteger)value);
00640 return true;
00641 }
00642
00643 case SQSL_STRING: {
00644 SlObject(NULL, _ai_byte);
00645 static char buf[256];
00646 SlArray(buf, _ai_sl_byte, SLE_CHAR);
00647 if (vm != NULL) sq_pushstring(vm, OTTD2FS(buf), -1);
00648 return true;
00649 }
00650
00651 case SQSL_ARRAY: {
00652 if (vm != NULL) sq_newarray(vm, 0);
00653 while (LoadObjects(vm)) {
00654 if (vm != NULL) sq_arrayappend(vm, -2);
00655
00656 }
00657 return true;
00658 }
00659
00660 case SQSL_TABLE: {
00661 if (vm != NULL) sq_newtable(vm);
00662 while (LoadObjects(vm)) {
00663 LoadObjects(vm);
00664 if (vm != NULL) sq_rawset(vm, -3);
00665
00666 }
00667 return true;
00668 }
00669
00670 case SQSL_BOOL: {
00671 SlObject(NULL, _ai_byte);
00672 if (vm != NULL) sq_pushinteger(vm, (SQBool)(_ai_sl_byte != 0));
00673 return true;
00674 }
00675
00676 case SQSL_NULL: {
00677 if (vm != NULL) sq_pushnull(vm);
00678 return true;
00679 }
00680
00681 case SQSL_ARRAY_TABLE_END: {
00682 return false;
00683 }
00684
00685 default: NOT_REACHED();
00686 }
00687 }
00688
00689 void AIInstance::LoadEmpty()
00690 {
00691 SlObject(NULL, _ai_byte);
00692
00693 if (_ai_sl_byte == 0) return;
00694
00695 LoadObjects(NULL);
00696 }
00697
00698 void AIInstance::Load(int version)
00699 {
00700 if (this->engine == NULL || version == -1) {
00701 LoadEmpty();
00702 return;
00703 }
00704 HSQUIRRELVM vm = this->engine->GetVM();
00705
00706 SlObject(NULL, _ai_byte);
00707
00708 if (_ai_sl_byte == 0) return;
00709
00710 sq_pushinteger(vm, version);
00711 LoadObjects(vm);
00712 this->is_save_data_on_stack = true;
00713 }
00714
00715 bool AIInstance::CallLoad()
00716 {
00717 HSQUIRRELVM vm = this->engine->GetVM();
00718
00719 if (!this->is_save_data_on_stack) return true;
00720
00721 this->is_save_data_on_stack = false;
00722
00723 if (!this->engine->MethodExists(*this->instance, "Load")) {
00724 AILog::Warning("Loading failed: there was data for the AI to load, but the AI does not have a Load() function.");
00725
00726
00727 sq_pop(vm, 2);
00728 return true;
00729 }
00730
00731
00732 sq_pushobject(vm, *this->instance);
00733
00734 sq_pushstring(vm, OTTD2FS("Load"), -1);
00735
00736 sq_get(vm, -2);
00737
00738 sq_pushobject(vm, *this->instance);
00739
00740 sq_push(vm, -5);
00741 sq_push(vm, -5);
00742
00743
00744
00745 if (SQ_FAILED(sq_call(vm, 3, SQFalse, SQFalse, 100000))) return false;
00746
00747
00748 sq_pop(vm, 4);
00749 return true;
00750 }