1 // 2 // 3 4 #ifndef FS2_OPEN_ADE_H 5 #define FS2_OPEN_ADE_H 6 7 #include "globalincs/pstypes.h" 8 #include "globalincs/version.h" 9 10 #include "object/object.h" 11 #include "scripting/ade_doc.h" 12 13 extern "C" { 14 #include <lauxlib.h> 15 #include <lualib.h> 16 } 17 18 #include <memory> 19 20 /** 21 * @defgroup ade_api ADE API functions 22 * 23 * @brief Functions and macros used in the ADE scripting API 24 * 25 * These functions enable the code to communicate with external scripts and expose an API for them to use 26 */ 27 28 29 namespace scripting { 30 31 // Forward definition 32 struct DocumentationElement; 33 34 using DocumentationErrorReporter = std::function<void(const SCP_string& errorMessage)>; 35 36 /** 37 * 38 * @param L 39 * @param stackdump 40 * 41 * @ingroup ade_api 42 */ 43 void ade_stackdump(lua_State* L, char* stackdump); 44 45 /** 46 * 47 * @param L 48 * @return 49 * 50 * @ingroup ade_api 51 */ 52 int ade_friendly_error(lua_State* L); 53 54 //*************************Lua types************************* 55 // Value fo ade_odata::size for when buf contains a pointer 56 const size_t ODATA_PTR_SIZE = (size_t) -1; 57 58 const int ADE_FUNCNAME_UPVALUE_INDEX = 1; 59 const int ADE_SETTING_UPVALUE_INDEX = 2; 60 const int ADE_DESTRUCTOR_OBJ_UPVALUE_INDEX = 3; // Upvalue which stores the reference to the ade_obj of a destructor 61 #define ADE_SETTING_VAR lua_toboolean(L,lua_upvalueindex(ADE_SETTING_UPVALUE_INDEX)) 62 63 template <typename T> 64 struct ade_odata_getter { 65 size_t idx; 66 T* value_ptr; 67 ade_odata_getterade_odata_getter68 ade_odata_getter(size_t idx_in, T* ptr_in) : idx(idx_in), value_ptr(ptr_in) {} 69 }; 70 71 template <typename T> 72 struct ade_odata_ptr_getter { 73 size_t idx; 74 T** value_ptr; 75 ade_odata_ptr_getterade_odata_ptr_getter76 ade_odata_ptr_getter(size_t idx_in, T** ptr_in) : idx(idx_in), value_ptr(ptr_in) {} 77 }; 78 79 template <typename T> 80 struct ade_odata_setter { 81 size_t idx; 82 T value; 83 ade_odata_setterade_odata_setter84 ade_odata_setter(size_t idx_in, T value_in) : idx(idx_in), value(std::move(value_in)) {} 85 }; 86 87 //WMC - 'Type' is the same as ade_set_args, 88 //plus some extra 89 //b - boolean 90 //d - double 91 //f - float 92 //i - integer 93 //s - string 94 //x - fix 95 //o - object 96 //EXTRA: 97 //l - library //WMC - no longer exists 98 //u - function 99 //v - virtual variable 100 // 101 //u - oh wait... 102 103 /** 104 * @ingroup ade_api 105 */ 106 class ade_table_entry { 107 public: 108 const char* Name = nullptr; 109 const char* ShortName = nullptr; 110 111 //Important stuff 112 size_t Idx = UINT_MAX; 113 size_t ParentIdx = UINT_MAX; 114 size_t DerivatorIdx = UINT_MAX; 115 //ade_id AdeID; 116 //ade_id DerivatorID; //Who do we derive from 117 118 //Type-specific 119 bool Instanced = false; //Is this a single instance? 120 char Type = '\0'; 121 122 //Functions/virtfuncs 123 lua_CFunction Function = nullptr; 124 125 // For Objects, the destructor of the object 126 void* Destructor_upvalue = nullptr; 127 lua_CFunction Destructor = nullptr; 128 129 size_t Size = 0; 130 131 //Metadata 132 ade_overload_list Arguments; 133 const char* Description = nullptr; 134 const char* ReturnType; 135 const char* ReturnDescription = nullptr; 136 gameversion::version DeprecationVersion; 137 const char* DeprecationMessage = nullptr; 138 139 //Subentries, of course 140 //WMC - I have HAD it with these motherfriendly vectors 141 //on this motherfriendly class. 142 size_t Num_subentries = 0; 143 size_t Subentries[256]; 144 145 private: 146 //*****Internal functions 147 //int IndexHandler(lua_State *L); 148 149 public: 150 //*****Constructors 151 ade_table_entry(); 152 153 //*****Operators 154 //ade_table_entry &operator = (const ade_table_entry &ate); 155 156 //*****Functions 157 size_t AddSubentry(ade_table_entry& n_ate); 158 int SetTable(lua_State* L, int p_amt_ldx, int p_mtb_ldx); 159 std::unique_ptr<DocumentationElement> ToDocumentationElement( 160 const scripting::DocumentationErrorReporter& errorReporter); 161 162 //*****Get 163 const char* GetName() const; 164 165 SCP_string GetFullPath() const; 166 }; 167 168 /** 169 * @ingroup ade_api 170 */ 171 class ade_manager { 172 SCP_vector<ade_table_entry> _table_entries; 173 174 SCP_vector<SCP_string> _type_names; 175 176 ade_manager(); 177 public: 178 static ade_manager* getInstance(); 179 180 // Disallow copying 181 ade_manager(const ade_manager&) = delete; 182 ade_manager& operator=(const ade_manager&) = delete; 183 184 // Disallow moving 185 ade_manager(ade_manager&&) = delete; 186 ade_manager& operator=(ade_manager&&) = delete; 187 188 size_t addTableEntry(const ade_table_entry& entry); 189 190 ade_table_entry& getEntry(size_t idx); 191 const ade_table_entry& getEntry(size_t idx) const; 192 getNumEntries()193 size_t getNumEntries() const { return _table_entries.size(); } 194 195 const SCP_vector<SCP_string>& getTypeNames() const; 196 }; 197 198 /** 199 * @ingroup ade_api 200 */ 201 void ade_stackdump(lua_State *L, char *stackdump); 202 203 /** 204 * @ingroup ade_api 205 */ 206 int ade_friendly_error(lua_State* L); 207 208 /** 209 * @ingroup ade_api 210 */ 211 const char* ade_get_type_string(lua_State* L, int argnum); 212 213 /** 214 * @ingroup ade_api 215 */ 216 bool ade_is_internal_type(const char* typeName); 217 218 /** 219 * @brief Converts an object index to something that can be used with ade_set_args. 220 * 221 * This respects the actual type of the object so all appropriate functions are available in Lua. 222 * 223 * @warning This is only used internally and should not be used by API code. Use ade_set_object_with_breed instead. 224 * 225 * @param obj_idx The object index 226 * @return The ade odata 227 */ 228 ade_odata_setter<object_h> ade_object_to_odata(int obj_idx); 229 230 /** 231 * @brief Sets an object parameter with the right type 232 * 233 * This should be used everywhere where an object value is returned to make sure that the scripter has access to 234 * all API functions. 235 * 236 * @param L The lua state 237 * @param obj_idx The object number 238 * @return The return value of ade_set_args 239 * 240 * @author WMC 241 * @ingroup ade_api 242 */ 243 int ade_set_object_with_breed(lua_State* L, int obj_idx); 244 245 /** 246 * @brief Loads and executes a default lua script 247 * 248 * This uses the specified file name and either retrieves it from the default files or uses it as a file name if the mod 249 * option is enabled. 250 * 251 * @param L The lua state 252 * @param name The name of the script file 253 * 254 * @ingroup ade_api 255 */ 256 void load_default_script(lua_State* L, const char* name); 257 258 //Struct for converting one string for another. whee! 259 struct string_conv { 260 const char *src; 261 const char *dest; 262 }; 263 264 const string_conv* ade_get_operator(const char *funcname); 265 266 namespace internal { 267 268 ade_table_entry& getTableEntry(size_t idx); 269 } 270 } // namespace scripting 271 272 #endif // FS2_OPEN_ADE_H 273