diff --git a/src/script/api/ai_changelog.hpp b/src/script/api/ai_changelog.hpp index 1aecd1a3d9..dbb4324bfe 100644 --- a/src/script/api/ai_changelog.hpp +++ b/src/script/api/ai_changelog.hpp @@ -25,6 +25,7 @@ * Other changes: * \li AIBridge::GetBridgeID renamed to AIBridge::GetBridgeType * \li AIWaypoint::GetWaypointID now returns the StationID of any type of waypoint + * \li AIList instances can now be saved * * \b 14.0 * diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp index 6b3a90623f..752c61f502 100644 --- a/src/script/api/game_changelog.hpp +++ b/src/script/api/game_changelog.hpp @@ -25,6 +25,7 @@ * Other changes: * \li GSBridge::GetBridgeID renamed to GSBridge::GetBridgeType * \li GSWaypoint::GetWaypointID now returns the StationID of any type of waypoint + * \li GSList instances can now be saved * * \b 14.0 * diff --git a/src/script/api/script_controller.hpp b/src/script/api/script_controller.hpp index 85ccbad3f4..b1d38d6a6d 100644 --- a/src/script/api/script_controller.hpp +++ b/src/script/api/script_controller.hpp @@ -77,9 +77,8 @@ public: * - booleans, and * - nulls. * - * In particular, instances of classes can't be saved including - * ScriptList. Such a list should be converted to an array or table on - * save and converted back on load. + * In particular, instances of classes can't be saved with the exception of + * ScriptList. * * The function is called as soon as the user saves the game, * independently of other activities of the script. The script is not diff --git a/src/script/api/script_list.cpp b/src/script/api/script_list.cpp index 4abef9de33..70deef82a0 100644 --- a/src/script/api/script_list.cpp +++ b/src/script/api/script_list.cpp @@ -403,6 +403,56 @@ public: +bool ScriptList::SaveObject(HSQUIRRELVM vm) +{ + sq_pushstring(vm, "List"); + sq_newarray(vm, 0); + sq_pushinteger(vm, this->sorter_type); + sq_arrayappend(vm, -2); + sq_pushbool(vm, this->sort_ascending ? SQTrue : SQFalse); + sq_arrayappend(vm, -2); + sq_newtable(vm); + for (ScriptListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + sq_pushinteger(vm, iter->first); + sq_pushinteger(vm, iter->second); + sq_rawset(vm, -3); + } + sq_arrayappend(vm, -2); + return true; +} + +bool ScriptList::LoadObject(HSQUIRRELVM vm) +{ + if (sq_gettype(vm, -1) != OT_ARRAY) return false; + sq_pushnull(vm); + if (SQ_FAILED(sq_next(vm, -2))) return false; + if (sq_gettype(vm, -1) != OT_INTEGER) return false; + SQInteger type; + sq_getinteger(vm, -1, &type); + sq_pop(vm, 2); + if (SQ_FAILED(sq_next(vm, -2))) return false; + if (sq_gettype(vm, -1) != OT_BOOL) return false; + SQBool order; + sq_getbool(vm, -1, &order); + sq_pop(vm, 2); + if (SQ_FAILED(sq_next(vm, -2))) return false; + if (sq_gettype(vm, -1) != OT_TABLE) return false; + sq_pushnull(vm); + while (SQ_SUCCEEDED(sq_next(vm, -2))) { + if (sq_gettype(vm, -2) != OT_INTEGER && sq_gettype(vm, -1) != OT_INTEGER) return false; + SQInteger key, value; + sq_getinteger(vm, -2, &key); + sq_getinteger(vm, -1, &value); + this->AddItem(key, value); + sq_pop(vm, 2); + } + sq_pop(vm, 3); + if (SQ_SUCCEEDED(sq_next(vm, -2))) return false; + sq_pop(vm, 1); + this->Sort(static_cast(type), order == SQTrue); + return true; +} + ScriptList::ScriptList() { /* Default sorter */ diff --git a/src/script/api/script_list.hpp b/src/script/api/script_list.hpp index 164dd15ba6..a2f16eb272 100644 --- a/src/script/api/script_list.hpp +++ b/src/script/api/script_list.hpp @@ -149,6 +149,9 @@ protected: ScriptList::FillList(vm, list, [](const T *) { return true; }); } + virtual bool SaveObject(HSQUIRRELVM vm) override; + virtual bool LoadObject(HSQUIRRELVM vm) override; + public: typedef std::set ScriptItemList; ///< The list of items inside the bucket typedef std::map ScriptListBucket; ///< The bucket list per value diff --git a/src/script/api/script_tilelist.cpp b/src/script/api/script_tilelist.cpp index 5b80269e17..83596d22bc 100644 --- a/src/script/api/script_tilelist.cpp +++ b/src/script/api/script_tilelist.cpp @@ -15,6 +15,14 @@ #include "../../safeguards.h" +bool ScriptTileList::SaveObject(HSQUIRRELVM vm) +{ + sq_pushstring(vm, "TileList"); + if (!ScriptList::SaveObject(vm)) return false; + sq_remove(vm, -2); + return true; +} + void ScriptTileList::AddRectangle(TileIndex t1, TileIndex t2) { if (!::IsValidTile(t1)) return; diff --git a/src/script/api/script_tilelist.hpp b/src/script/api/script_tilelist.hpp index 2a693f492d..a6308ec182 100644 --- a/src/script/api/script_tilelist.hpp +++ b/src/script/api/script_tilelist.hpp @@ -20,6 +20,8 @@ * @ingroup ScriptList */ class ScriptTileList : public ScriptList { +protected: + virtual bool SaveObject(HSQUIRRELVM) override; public: /** * Adds the rectangle between tile_from and tile_to to the to-be-evaluated tiles.