1
0
Fork 0

Add: [Script] GetExtraLastError and GetExtraLastErrorString

Allow scripts to get the extra error message of their last command.

Allow DoCommand and a few others to set extra error messages upon returning result.

Add regression tests.
pull/12269/head
SamuXarick 2024-03-10 23:09:44 +00:00
parent 95f8fc983b
commit ebe5c114dd
12 changed files with 85 additions and 4 deletions

View File

@ -1828,6 +1828,17 @@ function Regression::Vehicle()
print(" GetLastErrorString(): " + AIError.GetLastErrorString()); print(" GetLastErrorString(): " + AIError.GetLastErrorString());
print(" SendVehicleToDepot(): " + AIVehicle.SendVehicleToDepot(13)); print(" SendVehicleToDepot(): " + AIVehicle.SendVehicleToDepot(13));
print(" GetLastErrorString(): " + AIError.GetLastErrorString()); print(" GetLastErrorString(): " + AIError.GetLastErrorString());
print(" BuildVehicle(): " + AIVehicle.BuildVehicle(33417, 116));
print(" AppendOrder(): " + AIOrder.AppendOrder(20, 33421, AIOrder.OF_NONE));
print(" GetLastError(): " + AIError.GetLastError());
print(" GetLastErrorString(): " + AIError.GetLastErrorString());
print(" GetExtraLastError(): " + AIError.GetExtraLastError());
print(" GetExtraLastErrorString(): " + AIError.GetExtraLastErrorString());
print(" SellVehicle(): " + AIVehicle.SellVehicle(20));
print(" GetLastError(): " + AIError.GetLastError());
print(" GetLastErrorString(): " + AIError.GetLastErrorString());
print(" GetExtraLastError(): " + AIError.GetExtraLastError());
print(" GetExtraLastErrorString(): " + AIError.GetExtraLastErrorString());
local list = AIVehicleList(); local list = AIVehicleList();
local in_depot = AIVehicleList(AIVehicle.IsInDepot); local in_depot = AIVehicleList(AIVehicle.IsInDepot);

View File

@ -9546,6 +9546,17 @@ ERROR: IsEnd() is invalid as Begin() is never called
GetLastErrorString(): ERR_VEHICLE_NOT_IN_DEPOT GetLastErrorString(): ERR_VEHICLE_NOT_IN_DEPOT
SendVehicleToDepot(): false SendVehicleToDepot(): false
GetLastErrorString(): ERR_UNKNOWN GetLastErrorString(): ERR_UNKNOWN
BuildVehicle(): 20
AppendOrder(): false
GetLastError(): 1
GetLastErrorString(): ERR_UNKNOWN
GetExtraLastError(): 1
GetExtraLastErrorString(): ERR_UNKNOWN
SellVehicle(): true
GetLastError(): 0
GetLastErrorString(): ERR_NONE
GetExtraLastError(): 0
GetExtraLastErrorString(): ERR_NONE
--VehicleList-- --VehicleList--
Count(): 5 Count(): 5
@ -9588,7 +9599,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
13 => 5490 13 => 5490
12 => 5489 12 => 5489
CurrentSpeed ListDump: CurrentSpeed ListDump:
12 => 27 12 => 31
17 => 0 17 => 0
16 => 0 16 => 0
14 => 0 14 => 0
@ -9763,9 +9774,9 @@ ERROR: IsEnd() is invalid as Begin() is never called
--Valuate() with excessive CPU usage-- --Valuate() with excessive CPU usage--
Your script made an error: excessive CPU usage in valuator function Your script made an error: excessive CPU usage in valuator function
*FUNCTION [unknown()] regression/main.nut line [2065] *FUNCTION [unknown()] regression/main.nut line [2076]
*FUNCTION [Valuate()] NATIVE line [-1] *FUNCTION [Valuate()] NATIVE line [-1]
*FUNCTION [Start()] regression/main.nut line [2066] *FUNCTION [Start()] regression/main.nut line [2077]
[id] 0 [id] 0
[this] TABLE [this] TABLE
@ -9774,7 +9785,7 @@ Your script made an error: excessive CPU usage in valuator function
[this] INSTANCE [this] INSTANCE
Your script made an error: excessive CPU usage in valuator function Your script made an error: excessive CPU usage in valuator function
*FUNCTION [Start()] regression/main.nut line [2066] *FUNCTION [Start()] regression/main.nut line [2077]
[Infinite] CLOSURE [Infinite] CLOSURE
[list] INSTANCE [list] INSTANCE

View File

@ -21,6 +21,8 @@
* \li AIEventVehicleCrashed::GetVictims * \li AIEventVehicleCrashed::GetVictims
* \li AIEventCompanyRenamed * \li AIEventCompanyRenamed
* \li AIEventPresidentRenamed * \li AIEventPresidentRenamed
* \li AIError::GetExtraLastError
* \li AIError::GetExtraLastErrorString
* *
* \b 14.0 * \b 14.0
* *

View File

@ -21,6 +21,8 @@
* \li GSEventVehicleCrashed::GetVictims * \li GSEventVehicleCrashed::GetVictims
* \li GSEventCompanyRenamed * \li GSEventCompanyRenamed
* \li GSEventPresidentRenamed * \li GSEventPresidentRenamed
* \li GSError::GetExtraLastError
* \li GSError::GetExtraLastErrorString
* *
* \b 14.0 * \b 14.0
* *

View File

@ -23,11 +23,21 @@ ScriptError::ScriptErrorMapString ScriptError::error_map_string = ScriptError::S
return ScriptObject::GetLastError(); return ScriptObject::GetLastError();
} }
/* static */ ScriptErrorType ScriptError::GetExtraLastError()
{
return ScriptObject::GetExtraLastError();
}
/* static */ std::optional<std::string> ScriptError::GetLastErrorString() /* static */ std::optional<std::string> ScriptError::GetLastErrorString()
{ {
return (*error_map_string.find(ScriptError::GetLastError())).second; return (*error_map_string.find(ScriptError::GetLastError())).second;
} }
/* static */ std::optional<std::string> ScriptError::GetExtraLastErrorString()
{
return (*error_map_string.find(ScriptError::GetExtraLastError())).second;
}
/* static */ ScriptErrorType ScriptError::StringToError(StringID internal_string_id) /* static */ ScriptErrorType ScriptError::StringToError(StringID internal_string_id)
{ {
StringIndexInTab index = GetStringIndex(internal_string_id); StringIndexInTab index = GetStringIndex(internal_string_id);

View File

@ -21,6 +21,7 @@
#define EnforcePrecondition(returnval, condition) \ #define EnforcePrecondition(returnval, condition) \
if (!(condition)) { \ if (!(condition)) { \
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); \ ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); \
ScriptObject::SetExtraLastError(ScriptError::ERR_UNKNOWN); \
return returnval; \ return returnval; \
} }
@ -33,6 +34,7 @@
#define EnforcePreconditionCustomError(returnval, condition, error_code) \ #define EnforcePreconditionCustomError(returnval, condition, error_code) \
if (!(condition)) { \ if (!(condition)) { \
ScriptObject::SetLastError(error_code); \ ScriptObject::SetLastError(error_code); \
ScriptObject::SetExtraLastError(ScriptError::ERR_UNKNOWN); \
return returnval; \ return returnval; \
} }
@ -44,6 +46,7 @@
#define EnforcePreconditionEncodedText(returnval, string) \ #define EnforcePreconditionEncodedText(returnval, string) \
if (string.empty()) { \ if (string.empty()) { \
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); \ ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); \
ScriptObject::SetExtraLastError(ScriptError::ERR_UNKNOWN); \
return returnval; \ return returnval; \
} }
@ -60,6 +63,7 @@
#define EnforceCompanyModeValid_Void() \ #define EnforceCompanyModeValid_Void() \
if (!ScriptCompanyMode::IsValid()) { \ if (!ScriptCompanyMode::IsValid()) { \
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY); \ ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY); \
ScriptObject::SetExtraLastError(ScriptError::ERR_UNKNOWN); \
return; \ return; \
} }
@ -83,6 +87,7 @@
#define EnforceDeityOrCompanyModeValid_Void() \ #define EnforceDeityOrCompanyModeValid_Void() \
if (!(ScriptCompanyMode::IsDeity() || ScriptCompanyMode::IsValid())) { \ if (!(ScriptCompanyMode::IsDeity() || ScriptCompanyMode::IsValid())) { \
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY); \ ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY); \
ScriptObject::SetExtraLastError(ScriptError::ERR_UNKNOWN); \
return; \ return; \
} }
@ -190,12 +195,24 @@ public:
*/ */
static ScriptErrorType GetLastError(); static ScriptErrorType GetLastError();
/**
* Get the extra last error.
* @return An ErrorMessages enum value.
*/
static ScriptErrorType GetExtraLastError();
/** /**
* Get the last error in string format (for human readability). * Get the last error in string format (for human readability).
* @return An ErrorMessage enum item, as string. * @return An ErrorMessage enum item, as string.
*/ */
static std::optional<std::string> GetLastErrorString(); static std::optional<std::string> GetLastErrorString();
/**
* Get the extra last error in string format (for human readability).
* @return An ErrorMessage enum item, as string.
*/
static std::optional<std::string> GetExtraLastErrorString();
/** /**
* Get the error based on the OpenTTD StringID. * Get the error based on the OpenTTD StringID.
* @api -all * @api -all

View File

@ -150,11 +150,21 @@ ScriptObject::ActiveInstance::~ActiveInstance()
GetStorage()->last_error = last_error; GetStorage()->last_error = last_error;
} }
/* static */ void ScriptObject::SetExtraLastError(ScriptErrorType extra_last_error)
{
GetStorage()->extra_last_error = extra_last_error;
}
/* static */ ScriptErrorType ScriptObject::GetLastError() /* static */ ScriptErrorType ScriptObject::GetLastError()
{ {
return GetStorage()->last_error; return GetStorage()->last_error;
} }
/* static */ ScriptErrorType ScriptObject::GetExtraLastError()
{
return GetStorage()->extra_last_error;
}
/* static */ void ScriptObject::SetLastCost(Money last_cost) /* static */ void ScriptObject::SetLastCost(Money last_cost)
{ {
GetStorage()->last_cost = last_cost; GetStorage()->last_cost = last_cost;
@ -286,6 +296,7 @@ std::tuple<bool, bool, bool, bool> ScriptObject::DoCommandPrep()
if (!ScriptCompanyMode::IsDeity() && !ScriptCompanyMode::IsValid()) { if (!ScriptCompanyMode::IsDeity() && !ScriptCompanyMode::IsValid()) {
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY); ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY);
ScriptObject::SetExtraLastError(ScriptError::ERR_UNKNOWN);
return { true, estimate_only, asynchronous, networking }; return { true, estimate_only, asynchronous, networking };
} }
@ -300,11 +311,13 @@ bool ScriptObject::DoCommandProcessResult(const CommandCost &res, Script_Suspend
/* We failed; set the error and bail out */ /* We failed; set the error and bail out */
if (res.Failed()) { if (res.Failed()) {
SetLastError(ScriptError::StringToError(res.GetErrorMessage())); SetLastError(ScriptError::StringToError(res.GetErrorMessage()));
SetExtraLastError(ScriptError::StringToError(res.GetExtraErrorMessage()));
return false; return false;
} }
/* No error, then clear it. */ /* No error, then clear it. */
SetLastError(ScriptError::ERR_NONE); SetLastError(ScriptError::ERR_NONE);
SetExtraLastError(ScriptError::ERR_NONE);
/* Estimates, update the cost for the estimate and be done */ /* Estimates, update the cost for the estimate and be done */
if (estimate_only) { if (estimate_only) {

View File

@ -174,11 +174,21 @@ protected:
*/ */
static void SetLastError(ScriptErrorType last_error); static void SetLastError(ScriptErrorType last_error);
/**
* Set the DoCommand extra last error.
*/
static void SetExtraLastError(ScriptErrorType extra_last_error);
/** /**
* Get the DoCommand last error. * Get the DoCommand last error.
*/ */
static ScriptErrorType GetLastError(); static ScriptErrorType GetLastError();
/**
* Get the DoCommand extra last error.
*/
static ScriptErrorType GetExtraLastError();
/** /**
* Set the road type. * Set the road type.
*/ */

View File

@ -52,6 +52,7 @@ SQInteger ScriptPriorityQueue::Pop(HSQUIRRELVM vm)
{ {
if (this->IsEmpty()) { if (this->IsEmpty()) {
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED);
ScriptObject::SetExtraLastError(ScriptError::ERR_UNKNOWN);
sq_pushnull(vm); sq_pushnull(vm);
return 1; return 1;
} }
@ -70,6 +71,7 @@ SQInteger ScriptPriorityQueue::Peek(HSQUIRRELVM vm)
{ {
if (this->IsEmpty()) { if (this->IsEmpty()) {
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED);
ScriptObject::SetExtraLastError(ScriptError::ERR_UNKNOWN);
sq_pushnull(vm); sq_pushnull(vm);
return 1; return 1;
} }

View File

@ -305,6 +305,7 @@
uint32_t townnameparts; uint32_t townnameparts;
if (!GenerateTownName(ScriptObject::GetRandomizer(), &townnameparts)) { if (!GenerateTownName(ScriptObject::GetRandomizer(), &townnameparts)) {
ScriptObject::SetLastError(ScriptError::ERR_NAME_IS_NOT_UNIQUE); ScriptObject::SetLastError(ScriptError::ERR_NAME_IS_NOT_UNIQUE);
ScriptObject::SetExtraLastError(ScriptError::ERR_UNKNOWN);
return false; return false;
} }

View File

@ -759,6 +759,7 @@ bool ScriptInstance::DoCommandCallback(const CommandCost &result, const CommandD
if (result.Failed()) { if (result.Failed()) {
ScriptObject::SetLastError(ScriptError::StringToError(result.GetErrorMessage())); ScriptObject::SetLastError(ScriptError::StringToError(result.GetErrorMessage()));
ScriptObject::SetExtraLastError(ScriptError::StringToError(result.GetExtraErrorMessage()));
} else { } else {
ScriptObject::IncreaseDoCommandCosts(result.GetCost()); ScriptObject::IncreaseDoCommandCosts(result.GetCost());
ScriptObject::SetLastCost(result.GetCost()); ScriptObject::SetLastCost(result.GetCost());

View File

@ -51,6 +51,7 @@ private:
CommandCost costs; ///< The costs the script is tracking. CommandCost costs; ///< The costs the script is tracking.
Money last_cost; ///< The last cost of the command. Money last_cost; ///< The last cost of the command.
ScriptErrorType last_error{}; ///< The last error of the command. ScriptErrorType last_error{}; ///< The last error of the command.
ScriptErrorType extra_last_error{}; ///< The extra last error of the command.
bool last_command_res; ///< The last result of the command. bool last_command_res; ///< The last result of the command.
CommandDataBuffer last_data; ///< The last data passed to a command. CommandDataBuffer last_data; ///< The last data passed to a command.