From 9c6032bb36e2de8d2e065efdf509def3323cfa47 Mon Sep 17 00:00:00 2001 From: Stephan Spengler Date: Thu, 12 Jan 2023 22:14:52 +0100 Subject: [PATCH] Fix: GameActionResult does not comply to API specification --- distribution/changelog.txt | 1 + distribution/openrct2.d.ts | 16 +++++--- src/openrct2/scripting/ScriptEngine.cpp | 11 ++++-- src/openrct2/scripting/ScriptEngine.h | 2 +- .../scripting/bindings/game/ScContext.hpp | 39 ++++--------------- 5 files changed, 27 insertions(+), 42 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 7b2bd53aa6..bace31c8c7 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -16,6 +16,7 @@ - Fix: [#18911] Mini Golf station does not draw correctly from all angles. - Fix: [#18971] New Game does not prompt for save before quitting. - Fix: [#19026] Park loan is clamped to a 32-bit integer. +- Fix: [#19114] [Plugin] GameActionResult does not comply to API specification. 0.4.3 (2022-12-14) ------------------------------------------------------------------------ diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index 5cee798c92..17dd3c13cd 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -323,7 +323,7 @@ declare global { queryAction(action: "peepspawnplace", args: PeepSpawnPlaceArgs, callback?: (result: GameActionResult) => void): void; queryAction(action: "playerkick", args: PlayerKickArgs, callback?: (result: GameActionResult) => void): void; queryAction(action: "playersetgroup", args: PlayerSetGroupArgs, callback?: (result: GameActionResult) => void): void; - queryAction(action: "ridecreate", args: RideCreateArgs, callback?: (result: GameActionResult) => void): void; + queryAction(action: "ridecreate", args: RideCreateArgs, callback?: (result: RideCreateActionResult) => void): void; queryAction(action: "ridedemolish", args: RideDemolishArgs, callback?: (result: GameActionResult) => void): void; queryAction(action: "rideentranceexitplace", args: RideEntranceExitPlaceArgs, callback?: (result: GameActionResult) => void): void; queryAction(action: "rideentranceexitremove", args: RideEntranceExitRemoveArgs, callback?: (result: GameActionResult) => void): void; @@ -342,7 +342,7 @@ declare global { queryAction(action: "smallsceneryremove", args: SmallSceneryRemoveArgs, callback?: (result: GameActionResult) => void): void; queryAction(action: "smallscenerysetcolour", args: SmallScenerySetColourArgs, callback?: (result: GameActionResult) => void): void; queryAction(action: "stafffire", args: StaffFireArgs, callback?: (result: GameActionResult) => void): void; - queryAction(action: "staffhire", args: StaffHireArgs, callback?: (result: GameActionResult) => void): void; + queryAction(action: "staffhire", args: StaffHireArgs, callback?: (result: StaffHireNewActionResult) => void): void; queryAction(action: "staffsetcolour", args: StaffSetColourArgs, callback?: (result: GameActionResult) => void): void; queryAction(action: "staffsetcostume", args: StaffSetCostumeArgs, callback?: (result: GameActionResult) => void): void; queryAction(action: "staffsetname", args: StaffSetNameArgs, callback?: (result: GameActionResult) => void): void; @@ -414,7 +414,7 @@ declare global { executeAction(action: "peepspawnplace", args: PeepSpawnPlaceArgs, callback?: (result: GameActionResult) => void): void; executeAction(action: "playerkick", args: PlayerKickArgs, callback?: (result: GameActionResult) => void): void; executeAction(action: "playersetgroup", args: PlayerSetGroupArgs, callback?: (result: GameActionResult) => void): void; - executeAction(action: "ridecreate", args: RideCreateArgs, callback?: (result: GameActionResult) => void): void; + executeAction(action: "ridecreate", args: RideCreateArgs, callback?: (result: RideCreateActionResult) => void): void; executeAction(action: "ridedemolish", args: RideDemolishArgs, callback?: (result: GameActionResult) => void): void; executeAction(action: "rideentranceexitplace", args: RideEntranceExitPlaceArgs, callback?: (result: GameActionResult) => void): void; executeAction(action: "rideentranceexitremove", args: RideEntranceExitRemoveArgs, callback?: (result: GameActionResult) => void): void; @@ -433,7 +433,7 @@ declare global { executeAction(action: "smallsceneryremove", args: SmallSceneryRemoveArgs, callback?: (result: GameActionResult) => void): void; executeAction(action: "smallscenerysetcolour", args: SmallScenerySetColourArgs, callback?: (result: GameActionResult) => void): void; executeAction(action: "stafffire", args: StaffFireArgs, callback?: (result: GameActionResult) => void): void; - executeAction(action: "staffhire", args: StaffHireArgs, callback?: (result: GameActionResult) => void): void; + executeAction(action: "staffhire", args: StaffHireArgs, callback?: (result: StaffHireNewActionResult) => void): void; executeAction(action: "staffsetcolour", args: StaffSetColourArgs, callback?: (result: GameActionResult) => void): void; executeAction(action: "staffsetcostume", args: StaffSetCostumeArgs, callback?: (result: GameActionResult) => void): void; executeAction(action: "staffsetname", args: StaffSetNameArgs, callback?: (result: GameActionResult) => void): void; @@ -1296,8 +1296,12 @@ declare global { expenditureType?: ExpenditureType; } - interface RideCreateGameActionResult extends GameActionResult { - readonly ride: number; + interface RideCreateActionResult extends GameActionResult { + readonly ride?: number; + } + + interface StaffHireNewActionResult extends GameActionResult { + readonly peep?: number; } interface NetworkEventArgs { diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index 99e97a8df1..591b96a852 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -1131,11 +1131,13 @@ DukValue ScriptEngine::GameActionResultToDuk(const GameAction& action, const Gam DukStackFrame frame(_context); DukObject obj(_context); - auto player = action.GetPlayer(); - if (player != -1) + obj.Set("error", static_cast(result.Error)); + if (result.Error != GameActions::Status::Ok) { - obj.Set("player", action.GetPlayer()); + obj.Set("errorTitle", result.GetErrorTitle()); + obj.Set("errorMessage", result.GetErrorMessage()); } + if (result.Cost != MONEY32_UNDEFINED) { obj.Set("cost", result.Cost); @@ -1144,12 +1146,12 @@ DukValue ScriptEngine::GameActionResultToDuk(const GameAction& action, const Gam { obj.Set("position", ToDuk(_context, result.Position)); } - if (result.Expenditure != ExpenditureType::Count) { obj.Set("expenditureType", ExpenditureTypeToString(result.Expenditure)); } + // RideCreateAction only if (action.GetType() == GameCommand::CreateRide) { if (result.Error == GameActions::Status::Ok) @@ -1158,6 +1160,7 @@ DukValue ScriptEngine::GameActionResultToDuk(const GameAction& action, const Gam obj.Set("ride", rideIndex.ToUnderlying()); } } + // StaffHireNewAction only else if (action.GetType() == GameCommand::HireNewStaffMember) { if (result.Error == GameActions::Status::Ok) diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h index c298960dba..21d31d2b17 100644 --- a/src/openrct2/scripting/ScriptEngine.h +++ b/src/openrct2/scripting/ScriptEngine.h @@ -242,6 +242,7 @@ namespace OpenRCT2::Scripting const std::shared_ptr& plugin, std::string_view action, const DukValue& query, const DukValue& execute); void RunGameActionHooks(const GameAction& action, GameActions::Result& result, bool isExecute); [[nodiscard]] std::unique_ptr CreateGameAction(const std::string& actionid, const DukValue& args); + [[nodiscard]] DukValue GameActionResultToDuk(const GameAction& action, const GameActions::Result& result); void SaveSharedStorage(); @@ -275,7 +276,6 @@ namespace OpenRCT2::Scripting void ProcessREPL(); void RemoveCustomGameActions(const std::shared_ptr& plugin); [[nodiscard]] GameActions::Result DukToGameActionResult(const DukValue& d); - [[nodiscard]] DukValue GameActionResultToDuk(const GameAction& action, const GameActions::Result& result); static std::string_view ExpenditureTypeToString(ExpenditureType expenditureType); static ExpenditureType StringToExpenditureType(std::string_view expenditureType); diff --git a/src/openrct2/scripting/bindings/game/ScContext.hpp b/src/openrct2/scripting/bindings/game/ScContext.hpp index cae1383f99..8582bb0763 100644 --- a/src/openrct2/scripting/bindings/game/ScContext.hpp +++ b/src/openrct2/scripting/bindings/game/ScContext.hpp @@ -339,15 +339,15 @@ namespace OpenRCT2::Scripting if (isExecute) { action->SetCallback( - [this, plugin, callback](const GameAction*, const GameActions::Result* res) -> void { - HandleGameActionResult(plugin, *res, callback); + [this, plugin, callback](const GameAction* act, const GameActions::Result* res) -> void { + HandleGameActionResult(plugin, *act, *res, callback); }); GameActions::Execute(action.get()); } else { auto res = GameActions::Query(action.get()); - HandleGameActionResult(plugin, res, callback); + HandleGameActionResult(plugin, *action, res, callback); } } else @@ -362,38 +362,15 @@ namespace OpenRCT2::Scripting } void HandleGameActionResult( - const std::shared_ptr& plugin, const GameActions::Result& res, const DukValue& callback) + const std::shared_ptr& plugin, const GameAction& action, const GameActions::Result& res, + const DukValue& callback) { - // Construct result object - auto& scriptEngine = GetContext()->GetScriptEngine(); - auto ctx = scriptEngine.GetContext(); - auto objIdx = duk_push_object(ctx); - duk_push_int(ctx, static_cast(res.Error)); - duk_put_prop_string(ctx, objIdx, "error"); - - if (res.Error != GameActions::Status::Ok) - { - auto title = res.GetErrorTitle(); - duk_push_string(ctx, title.c_str()); - duk_put_prop_string(ctx, objIdx, "errorTitle"); - - auto message = res.GetErrorMessage(); - duk_push_string(ctx, message.c_str()); - duk_put_prop_string(ctx, objIdx, "errorMessage"); - } - - duk_push_int(ctx, static_cast(res.Cost)); - duk_put_prop_string(ctx, objIdx, "cost"); - - duk_push_int(ctx, static_cast(res.Expenditure)); - duk_put_prop_string(ctx, objIdx, "expenditureType"); - - auto args = DukValue::take_from_stack(ctx); - if (callback.is_function()) { + auto& scriptEngine = GetContext()->GetScriptEngine(); + auto dukResult = scriptEngine.GameActionResultToDuk(action, res); // Call the plugin callback and pass the result object - scriptEngine.ExecutePluginCall(plugin, callback, { args }, false); + scriptEngine.ExecutePluginCall(plugin, callback, { dukResult }, false); } }