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