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