Update to 13.0-RC1

This commit is contained in:
Pavel Stupnikov
2023-01-03 15:58:14 +04:00
parent be23283677
commit 59c991fa52
326 changed files with 12923 additions and 8705 deletions

View File

@@ -177,6 +177,7 @@ add_files(
script_industrytypelist.hpp
script_info_docs.hpp
script_infrastructure.hpp
script_league.hpp
script_list.hpp
script_log.hpp
script_map.hpp
@@ -247,6 +248,7 @@ add_files(
script_industrytype.cpp
script_industrytypelist.cpp
script_infrastructure.cpp
script_league.cpp
script_list.cpp
script_log.cpp
script_map.cpp

View File

@@ -21,6 +21,7 @@
* \li GSCargo::GetWeight
* \li GSIndustryType::ResolveNewGRFID
* \li GSObjectType::ResolveNewGRFID
* \li GSLeagueTable
*
* Other changes:
* \li GSRoad::HasRoadType now correctly checks RoadType against RoadType

View File

@@ -85,5 +85,5 @@
/* static */ int64 ScriptCargo::GetWeight(CargoID cargo_type, uint32 amount)
{
if (!IsValidCargo(cargo_type)) return -1;
return ::CargoSpec::Get(cargo_type)->weight * static_cast<int64>(amount) / 16;
return ::CargoSpec::Get(cargo_type)->WeightOfNUnits(amount);
}

View File

@@ -0,0 +1,122 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file script_league.cpp Implementation of ScriptLeagueTable. */
#include "../../stdafx.h"
#include "script_league.hpp"
#include "../script_instance.hpp"
#include "script_error.hpp"
#include "../../league_base.h"
#include "../../league_cmd.h"
#include "../../safeguards.h"
/* static */ bool ScriptLeagueTable::IsValidLeagueTable(LeagueTableID table_id)
{
return ::LeagueTable::IsValidID(table_id);
}
/* static */ ScriptLeagueTable::LeagueTableID ScriptLeagueTable::New(Text *title, Text *header, Text *footer)
{
CCountedPtr<Text> title_counter(title);
CCountedPtr<Text> header_counter(header);
CCountedPtr<Text> footer_counter(footer);
EnforcePrecondition(LEAGUE_TABLE_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(LEAGUE_TABLE_INVALID, title != nullptr);
const char *encoded_title = title->GetEncodedText();
EnforcePreconditionEncodedText(LEAGUE_TABLE_INVALID, encoded_title);
auto encoded_header = (header != nullptr ? std::string{ header->GetEncodedText() } : std::string{});
auto encoded_footer = (footer != nullptr ? std::string{ footer->GetEncodedText() } : std::string{});
if (!ScriptObject::Command<CMD_CREATE_LEAGUE_TABLE>::Do(&ScriptInstance::DoCommandReturnLeagueTableID, encoded_title, encoded_header, encoded_footer)) return LEAGUE_TABLE_INVALID;
/* In case of test-mode, we return LeagueTableID 0 */
return (ScriptLeagueTable::LeagueTableID)0;
}
/* static */ bool ScriptLeagueTable::IsValidLeagueTableElement(LeagueTableElementID element_id)
{
return ::LeagueTableElement::IsValidID(element_id);
}
/* static */ ScriptLeagueTable::LeagueTableElementID ScriptLeagueTable::NewElement(ScriptLeagueTable::LeagueTableID table, int64 rating, ScriptCompany::CompanyID company, Text *text, Text *score, LinkType link_type, uint32 link_target)
{
CCountedPtr<Text> text_counter(text);
CCountedPtr<Text> score_counter(score);
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, IsValidLeagueTable(table));
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
CompanyID c = (::CompanyID)company;
if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, text != nullptr);
const char *encoded_text_ptr = text->GetEncodedText();
EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_text_ptr);
std::string encoded_text = encoded_text_ptr; // save into string so GetEncodedText can reuse the internal buffer
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, score != nullptr);
const char *encoded_score = score->GetEncodedText();
EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_score);
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, IsValidLink(Link((::LinkType)link_type, link_target)));
if (!ScriptObject::Command<CMD_CREATE_LEAGUE_TABLE_ELEMENT>::Do(&ScriptInstance::DoCommandReturnLeagueTableElementID, table, rating, c, encoded_text, encoded_score, (::LinkType)link_type, (::LinkTargetID)link_target)) return LEAGUE_TABLE_ELEMENT_INVALID;
/* In case of test-mode, we return LeagueTableElementID 0 */
return (ScriptLeagueTable::LeagueTableElementID)0;
}
/* static */ bool ScriptLeagueTable::UpdateElementData(LeagueTableElementID element, ScriptCompany::CompanyID company, Text *text, LinkType link_type, LinkTargetID link_target)
{
CCountedPtr<Text> text_counter(text);
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(false, IsValidLeagueTableElement(element));
EnforcePrecondition(false, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
CompanyID c = (::CompanyID)company;
if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
EnforcePrecondition(false, text != nullptr);
const char *encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_text);
EnforcePrecondition(false, IsValidLink(Link((::LinkType)link_type, link_target)));
return ScriptObject::Command<CMD_UPDATE_LEAGUE_TABLE_ELEMENT_DATA>::Do(element, c, encoded_text, (::LinkType)link_type, (::LinkTargetID)link_target);
}
/* static */ bool ScriptLeagueTable::UpdateElementScore(LeagueTableElementID element, int64 rating, Text *score)
{
CCountedPtr<Text> score_counter(score);
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(false, IsValidLeagueTableElement(element));
EnforcePrecondition(false, score != nullptr);
const char *encoded_score = score->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_score);
return ScriptObject::Command<CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE>::Do(element, rating, encoded_score);
}
/* static */ bool ScriptLeagueTable::RemoveElement(LeagueTableElementID element)
{
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(false, IsValidLeagueTableElement(element));
return ScriptObject::Command<CMD_REMOVE_LEAGUE_TABLE_ELEMENT>::Do(element);
}

View File

@@ -0,0 +1,134 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file script_league.hpp Everything to manipulate league tables. */
#ifndef SCRIPT_LEAGUE_HPP
#define SCRIPT_LEAGUE_HPP
#include "script_company.hpp"
#include "script_text.hpp"
#include "../../league_type.h"
/**
* Class that handles league table related functions.
*
* To create a league table:
* 1. Create the league table
* 2. Create league table elements that will be shown in the table in the order of their rating (higher=better).
*
* @api game
*/
class ScriptLeagueTable : public ScriptObject {
public:
/**
* The league table IDs.
*/
enum LeagueTableID {
LEAGUE_TABLE_INVALID = ::INVALID_LEAGUE_TABLE, ///< An invalid league table id.
};
/**
* The league table element IDs.
*/
enum LeagueTableElementID {
LEAGUE_TABLE_ELEMENT_INVALID = ::INVALID_LEAGUE_TABLE_ELEMENT, ///< An invalid league table element id.
};
/**
* The type of a link.
*/
enum LinkType : byte {
LINK_NONE = ::LT_NONE, ///< No link
LINK_TILE = ::LT_TILE, ///< Link a tile
LINK_INDUSTRY = ::LT_INDUSTRY, ///< Link an industry
LINK_TOWN = ::LT_TOWN, ///< Link a town
LINK_COMPANY = ::LT_COMPANY, ///< Link a company
LINK_STORY_PAGE = ::LT_STORY_PAGE, ///< Link a story page
};
/**
* Check whether this is a valid league table ID.
* @param table_id The LeagueTableID to check.
* @return true iff this league table is valid.
*/
static bool IsValidLeagueTable(LeagueTableID table_id);
/**
* Check whether this is a valid league table element ID.
* @param element_id The LeagueTableElementID to check.
* @return true iff this league table element is valid.
*/
static bool IsValidLeagueTableElement(LeagueTableElementID element_id);
/**
* Create a new league table.
* @param title League table title (can be either a raw string, or ScriptText object).
* @return The new LeagueTableID, or LEAGUE_TABLE_INVALID if it failed.
* @pre No ScriptCompanyMode may be in scope.
* @pre title != nullptr && len(title) != 0.
*/
static LeagueTableID New(Text *title, Text *header, Text *footer);
/**
* Create a new league table element.
* @param table Id of the league table this element belongs to.
* @param rating Value that elements are ordered by.
* @param company Company to show the color blob for or INVALID_COMPANY.
* @param text Text of the element (can be either a raw string, or ScriptText object).
* @param score String representation of the score associated with the element (can be either a raw string, or ScriptText object).
* @param link_type Type of the referenced object.
* @param link_target Id of the referenced object.
* @return The new LeagueTableElementID, or LEAGUE_TABLE_ELEMENT_INVALID if it failed.
* @pre No ScriptCompanyMode may be in scope.
* @pre IsValidLeagueTable(table).
* @pre text != nullptr && len(text) != 0.
* @pre score != nullptr && len(score) != 0.
* @pre IsValidLink(Link(link_type, link_target)).
*/
static LeagueTableElementID NewElement(LeagueTableID table, int64 rating, ScriptCompany::CompanyID company, Text *text, Text *score, LinkType link_type, LinkTargetID link_target);
/**
* Update the attributes of a league table element.
* @param element Id of the element to update
* @param company Company to show the color blob for or INVALID_COMPANY.
* @param text Text of the element (can be either a raw string, or ScriptText object).
* @param link_type Type of the referenced object.
* @param link_target Id of the referenced object.
* @return True if the action succeeded.
* @pre No ScriptCompanyMode may be in scope.
* @pre IsValidLeagueTableElement(element).
* @pre text != nullptr && len(text) != 0.
* @pre IsValidLink(Link(link_type, link_target)).
*/
static bool UpdateElementData(LeagueTableElementID element, ScriptCompany::CompanyID company, Text *text, LinkType link_type, LinkTargetID link_target);
/**
* Create a new league table element.
* @param element Id of the element to update
* @param rating Value that elements are ordered by.
* @param score String representation of the score associated with the element (can be either a raw string, or ScriptText object).
* @return True if the action succeeded.
* @pre No ScriptCompanyMode may be in scope.
* @pre IsValidLeagueTableElement(element).
* @pre score != nullptr && len(score) != 0.
*/
static bool UpdateElementScore(LeagueTableElementID element, int64 rating, Text *score);
/**
* Remove a league table element.
* @param element Id of the element to update
* @return True if the action succeeded.
* @pre No ScriptCompanyMode may be in scope.
* @pre IsValidLeagueTableElement(element).
*/
static bool RemoveElement(LeagueTableElementID element);
};
#endif /* SCRIPT_LEAGUE_HPP */

View File

@@ -103,7 +103,7 @@ ScriptObject::ActiveInstance::~ActiveInstance()
/* static */ void ScriptObject::SetDoCommandCosts(Money value)
{
GetStorage()->costs = CommandCost(value);
GetStorage()->costs = CommandCost(INVALID_EXPENSES, value); // Expense type is never read.
}
/* static */ void ScriptObject::IncreaseDoCommandCosts(Money value)

View File

@@ -333,6 +333,9 @@ bool ScriptObject::ScriptDoCommandHelper<Tcmd, Tret(*)(DoCommandFlag, Targs...)>
tile = std::get<0>(args);
}
/* Do not even think about executing out-of-bounds tile-commands. */
if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (GetCommandFlags<Tcmd>() & CMD_ALL_TILES) == 0))) return false;
/* Only set ClientID parameters when the command does not come from the network. */
if constexpr ((::GetCommandFlags<Tcmd>() & CMD_CLIENT_ID) != 0) ScriptObjectInternal::SetClientIds(args, std::index_sequence_for<Targs...>{});

View File

@@ -155,7 +155,7 @@ ScriptTileList_StationType::ScriptTileList_StationType(StationID station_id, Scr
if ((station_type & ScriptStation::STATION_AIRPORT) != 0) station_type_value |= (1 << ::STATION_AIRPORT) | (1 << ::STATION_OILRIG);
if ((station_type & ScriptStation::STATION_DOCK) != 0) station_type_value |= (1 << ::STATION_DOCK) | (1 << ::STATION_OILRIG);
TileArea ta(::TileXY(rect->left, rect->top), rect->right - rect->left + 1, rect->bottom - rect->top + 1);
TileArea ta(::TileXY(rect->left, rect->top), rect->Width(), rect->Height());
for (TileIndex cur_tile : ta) {
if (!::IsTileType(cur_tile, MP_STATION)) continue;
if (::GetStationIndex(cur_tile) != station_id) continue;

View File

@@ -258,7 +258,7 @@
if (ScriptObject::GetCompany() == OWNER_DEITY) return false;
if (!IsValidTown(town_id)) return false;
return HasBit(::GetMaskOfTownActions(nullptr, ScriptObject::GetCompany(), ::Town::Get(town_id)), town_action);
return HasBit(::GetMaskOfTownActions(ScriptObject::GetCompany(), ::Town::Get(town_id)), town_action);
}
/* static */ bool ScriptTown::PerformTownAction(TownID town_id, TownAction town_action)

View File

@@ -26,6 +26,7 @@ void ScriptConfig::Change(const char *name, int version, bool force_exact_match,
if (this->config_list != nullptr) delete this->config_list;
this->config_list = (info == nullptr) ? nullptr : new ScriptConfigItemList();
if (this->config_list != nullptr) this->PushExtraConfigList();
this->to_load_data.reset();
this->ClearConfigList();
@@ -49,6 +50,7 @@ ScriptConfig::ScriptConfig(const ScriptConfig *config)
this->version = config->version;
this->config_list = nullptr;
this->is_random = config->is_random;
this->to_load_data.reset();
for (const auto &item : config->settings) {
this->settings[stredup(item.first)] = item.second;
@@ -63,6 +65,7 @@ ScriptConfig::~ScriptConfig()
free(this->name);
this->ResetSettings();
if (this->config_list != nullptr) delete this->config_list;
this->to_load_data.reset();
}
ScriptInfo *ScriptConfig::GetInfo() const
@@ -238,3 +241,14 @@ const char *ScriptConfig::GetTextfile(TextfileType type, CompanyID slot) const
return ::GetTextfile(type, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR, this->GetInfo()->GetMainScript());
}
void ScriptConfig::SetToLoadData(ScriptInstance::ScriptData *data)
{
this->to_load_data.reset(data);
}
ScriptInstance::ScriptData *ScriptConfig::GetToLoadData()
{
return this->to_load_data.get();
}

View File

@@ -16,6 +16,7 @@
#include "../core/string_compare_type.hpp"
#include "../company_type.h"
#include "../textfile_gui.h"
#include "script_instance.hpp"
/** Bitmask of flags for Script settings. */
enum ScriptConfigFlags {
@@ -63,7 +64,8 @@ public:
version(-1),
info(nullptr),
config_list(nullptr),
is_random(false)
is_random(false),
to_load_data(nullptr)
{}
/**
@@ -185,13 +187,17 @@ public:
*/
const char *GetTextfile(TextfileType type, CompanyID slot) const;
void SetToLoadData(ScriptInstance::ScriptData *data);
ScriptInstance::ScriptData *GetToLoadData();
protected:
const char *name; ///< Name of the Script
int version; ///< Version of the Script
class ScriptInfo *info; ///< ScriptInfo object for related to this Script version
SettingValueList settings; ///< List with all setting=>value pairs that are configure for this Script
ScriptConfigItemList *config_list; ///< List with all settings defined by this Script
bool is_random; ///< True if the AI in this slot was randomly chosen.
const char *name; ///< Name of the Script
int version; ///< Version of the Script
class ScriptInfo *info; ///< ScriptInfo object for related to this Script version
SettingValueList settings; ///< List with all setting=>value pairs that are configure for this Script
ScriptConfigItemList *config_list; ///< List with all settings defined by this Script
bool is_random; ///< True if the AI in this slot was randomly chosen.
std::unique_ptr<ScriptInstance::ScriptData> to_load_data; ///< Data to load after the Script start.
/**
* In case you have mandatory non-Script-definable config entries in your

View File

@@ -26,6 +26,7 @@
#include "../company_base.h"
#include "../company_func.h"
#include "../fileio_func.h"
#include "../league_type.h"
#include "../misc/endian_buffer.hpp"
#include "../safeguards.h"
@@ -298,6 +299,17 @@ void ScriptInstance::CollectGarbage()
instance->engine->InsertResult(EndianBufferReader::ToValue<StoryPageElementID>(ScriptObject::GetLastCommandResData()));
}
/* static */ void ScriptInstance::DoCommandReturnLeagueTableElementID(ScriptInstance *instance)
{
instance->engine->InsertResult(EndianBufferReader::ToValue<LeagueTableElementID>(ScriptObject::GetLastCommandResData()));
}
/* static */ void ScriptInstance::DoCommandReturnLeagueTableID(ScriptInstance *instance)
{
instance->engine->InsertResult(EndianBufferReader::ToValue<LeagueTableID>(ScriptObject::GetLastCommandResData()));
}
ScriptStorage *ScriptInstance::GetStorage()
{
return this->storage;
@@ -331,17 +343,6 @@ void *ScriptInstance::GetLogPointer()
* - 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 _script_sl_byte; ///< Used as source/target by the script saveload code to store/load a single byte.
/** SaveLoad array that saves/loads exactly one byte. */
@@ -560,14 +561,14 @@ bool ScriptInstance::IsPaused()
return this->is_paused;
}
/* static */ bool ScriptInstance::LoadObjects(HSQUIRRELVM vm)
/* static */ bool ScriptInstance::LoadObjects(ScriptData *data)
{
SlObject(nullptr, _script_byte);
switch (_script_sl_byte) {
case SQSL_INT: {
int64 value;
SlCopy(&value, 1, IsSavegameVersionBefore(SLV_SCRIPT_INT64) ? SLE_FILE_I32 | SLE_VAR_I64 : SLE_INT64);
if (vm != nullptr) sq_pushinteger(vm, (SQInteger)value);
if (data != nullptr) data->push_back((SQInteger)value);
return true;
}
@@ -576,37 +577,79 @@ bool ScriptInstance::IsPaused()
static char buf[std::numeric_limits<decltype(_script_sl_byte)>::max()];
SlCopy(buf, _script_sl_byte, SLE_CHAR);
StrMakeValidInPlace(buf, buf + _script_sl_byte);
if (vm != nullptr) sq_pushstring(vm, buf, -1);
if (data != nullptr) data->push_back(std::string(buf));
return true;
}
case SQSL_ARRAY:
case SQSL_TABLE: {
if (data != nullptr) data->push_back((SQSaveLoadType)_script_sl_byte);
while (LoadObjects(data));
return true;
}
case SQSL_BOOL: {
SlObject(nullptr, _script_byte);
if (data != nullptr) data->push_back((SQBool)(_script_sl_byte != 0));
return true;
}
case SQSL_NULL: {
if (data != nullptr) data->push_back((SQSaveLoadType)_script_sl_byte);
return true;
}
case SQSL_ARRAY_TABLE_END: {
if (data != nullptr) data->push_back((SQSaveLoadType)_script_sl_byte);
return false;
}
default: SlErrorCorrupt("Invalid script data type");
}
}
/* static */ bool ScriptInstance::LoadObjects(HSQUIRRELVM vm, ScriptData *data)
{
ScriptDataVariant value = data->front();
data->pop_front();
if (std::holds_alternative<SQInteger>(value)) {
sq_pushinteger(vm, std::get<SQInteger>(value));
return true;
}
if (std::holds_alternative<std::string>(value)) {
sq_pushstring(vm, std::get<std::string>(value).c_str(), -1);
return true;
}
if (std::holds_alternative<SQBool>(value)) {
sq_pushbool(vm, std::get<SQBool>(value));
return true;
}
switch (std::get<SQSaveLoadType>(value)) {
case SQSL_ARRAY: {
if (vm != nullptr) sq_newarray(vm, 0);
while (LoadObjects(vm)) {
if (vm != nullptr) sq_arrayappend(vm, -2);
sq_newarray(vm, 0);
while (LoadObjects(vm, data)) {
sq_arrayappend(vm, -2);
/* The value is popped from the stack by squirrel. */
}
return true;
}
case SQSL_TABLE: {
if (vm != nullptr) sq_newtable(vm);
while (LoadObjects(vm)) {
LoadObjects(vm);
if (vm != nullptr) sq_rawset(vm, -3);
sq_newtable(vm);
while (LoadObjects(vm, data)) {
LoadObjects(vm, data);
sq_rawset(vm, -3);
/* The key (-2) and value (-1) are popped from the stack by squirrel. */
}
return true;
}
case SQSL_BOOL: {
SlObject(nullptr, _script_byte);
if (vm != nullptr) sq_pushbool(vm, (SQBool)(_script_sl_byte != 0));
return true;
}
case SQSL_NULL: {
if (vm != nullptr) sq_pushnull(vm);
sq_pushnull(vm);
return true;
}
@@ -627,22 +670,35 @@ bool ScriptInstance::IsPaused()
LoadObjects(nullptr);
}
void ScriptInstance::Load(int version)
/* static */ ScriptInstance::ScriptData *ScriptInstance::Load(int version)
{
ScriptObject::ActiveInstance active(this);
if (this->engine == nullptr || version == -1) {
if (version == -1) {
LoadEmpty();
return;
return nullptr;
}
HSQUIRRELVM vm = this->engine->GetVM();
SlObject(nullptr, _script_byte);
/* Check if there was anything saved at all. */
if (_script_sl_byte == 0) return;
if (_script_sl_byte == 0) return nullptr;
sq_pushinteger(vm, version);
LoadObjects(vm);
ScriptData *data = new ScriptData();
data->push_back((SQInteger)version);
LoadObjects(data);
return data;
}
void ScriptInstance::LoadOnStack(ScriptData *data)
{
ScriptObject::ActiveInstance active(this);
if (data == nullptr) return;
HSQUIRRELVM vm = this->engine->GetVM();
ScriptDataVariant version = data->front();
data->pop_front();
sq_pushinteger(vm, std::get<SQInteger>(version));
LoadObjects(vm, data);
this->is_save_data_on_stack = true;
}

View File

@@ -10,6 +10,8 @@
#ifndef SCRIPT_INSTANCE_HPP
#define SCRIPT_INSTANCE_HPP
#include <variant>
#include <list>
#include <squirrel.h>
#include "script_suspend.hpp"
@@ -21,10 +23,25 @@ static const uint SQUIRREL_MAX_DEPTH = 25; ///< The maximum recursive depth for
/** Runtime information about a script like a pointer to the squirrel vm and the current state. */
class ScriptInstance {
private:
/** 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.
};
public:
friend class ScriptObject;
friend class ScriptController;
typedef std::variant<SQInteger, std::string, SQBool, SQSaveLoadType> ScriptDataVariant;
typedef std::list<ScriptDataVariant> ScriptData;
/**
* Create a new script.
*/
@@ -115,6 +132,16 @@ public:
*/
static void DoCommandReturnStoryPageElementID(ScriptInstance *instance);
/**
* Return a LeagueTableID reply for a DoCommand.
*/
static void DoCommandReturnLeagueTableID(ScriptInstance *instance);
/**
* Return a LeagueTableElementID reply for a DoCommand.
*/
static void DoCommandReturnLeagueTableElementID(ScriptInstance *instance);
/**
* Get the controller attached to the instance.
*/
@@ -136,11 +163,18 @@ public:
static void SaveEmpty();
/**
* Load data from a savegame and store it on the stack.
* Load data from a savegame.
* @param version The version of the script when saving, or -1 if this was
* not the original script saving the game.
* @return a pointer to loaded data.
*/
void Load(int version);
static ScriptData *Load(int version);
/**
* Store loaded data on the stack.
* @param data The loaded data to store on the stack.
*/
void LoadOnStack(ScriptData *data);
/**
* Load and discard data from a savegame.
@@ -279,7 +313,9 @@ private:
* Load all objects from a savegame.
* @return True if the loading was successful.
*/
static bool LoadObjects(HSQUIRRELVM vm);
static bool LoadObjects(ScriptData *data);
static bool LoadObjects(HSQUIRRELVM vm, ScriptData *data);
};
#endif /* SCRIPT_INSTANCE_HPP */