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