1 /*****************************************************************************
2  * Copyright (c) 2014-2021 OpenRCT2 developers
3  *
4  * For a complete list of all authors, please refer to contributors.md
5  * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
6  *
7  * OpenRCT2 is licensed under the GNU General Public License version 3.
8  *****************************************************************************/
9 #pragma once
10 
11 #include "../localisation/StringIds.h"
12 #include "../management/Finance.h"
13 #include "../world/Location.hpp"
14 
15 #include <any>
16 #include <array>
17 #include <cstdint>
18 #include <limits>
19 #include <memory>
20 #include <string>
21 #include <type_traits>
22 #include <variant>
23 
24 namespace GameActions
25 {
26     /**
27      * Common error codes for game actions.
28      */
29     enum class Status : uint16_t
30     {
31         Ok,
32         InvalidParameters,
33         Disallowed,
34         GamePaused,
35         InsufficientFunds,
36         NotInEditorMode,
37 
38         NotOwned,
39         TooLow,
40         TooHigh,
41         NoClearance,
42         ItemAlreadyPlaced,
43 
44         NotClosed,
45         Broken,
46 
47         NoFreeElements,
48 
49         Unknown = std::numeric_limits<std::underlying_type_t<Status>>::max(),
50     };
51 
52 #ifdef __WARN_SUGGEST_FINAL_METHODS__
53 #    pragma GCC diagnostic push
54 #    pragma GCC diagnostic ignored "-Wsuggest-final-methods"
55 #    pragma GCC diagnostic ignored "-Wsuggest-final-types"
56 #endif
57 
58     /**
59      * Represents the result of a game action query or execution.
60      */
61     class Result final
62     {
63     public:
64         using Ptr = std::unique_ptr<GameActions::Result>;
65         using StringVariant = std::variant<std::string, rct_string_id>;
66 
67         GameActions::Status Error = GameActions::Status::Ok;
68         StringVariant ErrorTitle = STR_NONE;
69         StringVariant ErrorMessage = STR_NONE;
70         std::array<uint8_t, 32> ErrorMessageArgs{};
71         CoordsXYZ Position = { LOCATION_NULL, LOCATION_NULL, LOCATION_NULL };
72         money32 Cost = 0;
73         ExpenditureType Expenditure = ExpenditureType::Count;
74         std::any ResultData;
75 
76         Result() = default;
77         Result(GameActions::Status error, rct_string_id title, rct_string_id message, uint8_t* args = nullptr);
78 
79         std::string GetErrorTitle() const;
80         std::string GetErrorMessage() const;
81 
82         // It is recommended to use strong types since a type alias such as 'using MyType = uint32_t'
83         // is still just uint32_t, this guarantees the data is associated with the correct type.
SetData(const T && data)84         template<typename T> void SetData(const T&& data)
85         {
86             ResultData = std::forward<const T&&>(data);
87         }
88 
89         // This function will throw std::bad_any_cast if the type mismatches.
GetData()90         template<typename T> T GetData() const
91         {
92             return std::any_cast<T>(ResultData);
93         }
94     };
95 
96 #ifdef __WARN_SUGGEST_FINAL_METHODS__
97 #    pragma GCC diagnostic pop
98 #endif
99 
100 } // namespace GameActions
101