summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/cluautil.h
blob: 60f8f73e1450dfbead044f4e9833190e5e26edd2 (plain) (blame)
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
/*
 * File:      cluautil.h
 * Summary:   Utility functions and macros for Lua bindings.
 */

#ifndef CLUAUTIL_H
#define CLUAUTIL_H

extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}

/*
 * Function definitions.
 */

#define LUAFN(name) static int name(lua_State *ls)
#define LUAWRAP(name, wrapexpr) \
    static int name(lua_State *ls) \
    {   \
        wrapexpr; \
        return (0); \
    }
#define PLUARET(type, val) \
        lua_push##type(ls, val); \
        return (1);
#define LUARET1(name, type, val) \
    static int name(lua_State *ls) \
    { \
        lua_push##type(ls, val); \
        return (1); \
    }
#define LUARET2(name, type, val1, val2)  \
    static int name(lua_State *ls) \
    { \
        lua_push##type(ls, val1); \
        lua_push##type(ls, val2); \
        return (2); \
    }

#define ASSERT_DLUA \
    do {                                                            \
        if (CLua::get_vm(ls).managed_vm)                            \
            luaL_error(ls, "Operation forbidden in end-user script");   \
    } while (false)


// FIXME: remove one of these.
void luaopen_setmeta(lua_State *ls,
                     const char *global,
                     const luaL_reg *lua_lib,
                     const char *meta);

void clua_register_metatable(lua_State *ls, const char *tn,
                             const luaL_reg *lr,
                             int (*gcfn)(lua_State *ls) = NULL);

int clua_stringtable(lua_State *ls, const std::vector<std::string> &s);

/*
 * User-data templates.
 * TODO: Consolidate these.
 */

template <class T>
inline static T *util_get_userdata(lua_State *ls, int ndx)
{
    return (lua_islightuserdata(ls, ndx))?
            static_cast<T *>( lua_touserdata(ls, ndx) )
          : NULL;
}

template <class T>
inline static T *clua_get_userdata(lua_State *ls, const char *mt, int ndx = 1)
{
    return static_cast<T*>( luaL_checkudata( ls, ndx, mt ) );
}

template <class T>
static int lua_object_gc(lua_State *ls)
{
    T **pptr = static_cast<T**>( lua_touserdata(ls, 1) );
    if (pptr)
        delete *pptr;
    return (0);
}

template <class T> T *clua_new_userdata(
        lua_State *ls, const char *mt)
{
    void *udata = lua_newuserdata( ls, sizeof(T) );
    luaL_getmetatable(ls, mt);
    lua_setmetatable(ls, -2);
    return static_cast<T*>( udata );
}

template <typename T>
inline void dlua_push_userdata(lua_State *ls, T udata, const char *meta)
{
    T *de = clua_new_userdata<T>(ls, meta);
    *de = udata;
}

template <class T>
static int dlua_push_object_type(lua_State *ls, const char *meta, const T &data)
{
    T **ptr = clua_new_userdata<T*>(ls, meta);
    if (ptr)
        *ptr = new T(data);
    else
        lua_pushnil(ls);
    return (1);
}

/*
 * Passing objects from and to Lua.
 */
struct activity_interrupt_data;
int push_activity_interrupt(lua_State *ls, activity_interrupt_data *t);

class map_def;
void clua_push_map(lua_State *ls, map_def *map);

void clua_push_coord(lua_State *ls, const coord_def &c);

class dgn_event;
void clua_push_dgn_event(lua_State *ls, const dgn_event *devent);

// XXX: These are currently defined outside cluautil.cc.
class monsters;
void push_monster(lua_State *ls, monsters* mons);
void lua_push_items(lua_State *ls, int link);
dungeon_feature_type check_lua_feature(lua_State *ls, int idx);
item_def *clua_check_item(lua_State *ls, int n);
unsigned int get_tile_idx(lua_State *ls, int arg);
level_id dlua_level_id(lua_State *ls, int ndx);


#define GETCOORD(c, p1, p2, boundfn)                      \
    coord_def c;                                          \
    c.x = luaL_checkint(ls, p1);                          \
    c.y = luaL_checkint(ls, p2);                          \
    if (!boundfn(c))                                        \
        luaL_error(                                             \
            ls,                                                 \
            make_stringf("Point (%d,%d) is out of bounds",      \
                         c.x, c.y).c_str());                    \
    else ;


#define COORDS(c, p1, p2)                                \
    GETCOORD(c, p1, p2, in_bounds)

#define COORDSHOW(c, p1, p2) \
    GETCOORD(c, p1, p2, in_show_bounds)

#define FEAT(f, pos) \
dungeon_feature_type f = check_lua_feature(ls, pos)

#define LUA_ITEM(name, n) \
    item_def *name = clua_check_item(ls, n);

#define LEVEL(lev, br, pos)                                             \
const char *level_name = luaL_checkstring(ls, pos);                 \
level_area_type lev = str_to_level_area_type(level_name);           \
if (lev == NUM_LEVEL_AREA_TYPES)                                    \
luaL_error(ls, "Expected level name");                          \
const char *branch_name = luaL_checkstring(ls, pos);                \
branch_type br = str_to_branch(branch_name);                        \
if (lev == LEVEL_DUNGEON && br == NUM_BRANCHES)                     \
luaL_error(ls, "Expected branch name");

#define MAP(ls, n, var) \
map_def *var = *(map_def **) luaL_checkudata(ls, n, MAP_METATABLE)
#define LINES(ls, n, var) \
map_lines &var = (*(map_def **) luaL_checkudata(ls, n, MAP_METATABLE))->map
#define DEVENT(ls, n, var) \
dgn_event *var = *(dgn_event **) luaL_checkudata(ls, n, DEVENT_METATABLE)
#define MAPMARKER(ls, n, var) \
map_marker *var = *(map_marker **) luaL_checkudata(ls, n, MAPMARK_METATABLE)


template <typename list, typename lpush>
static int clua_gentable(lua_State *ls, const list &strings, lpush push)
{
    lua_newtable(ls);
    for (int i = 0, size = strings.size(); i < size; ++i)
    {
        push(ls, strings[i]);
        lua_rawseti(ls, -2, i + 1);
    }
    return (1);
}

int clua_pushcxxstring(lua_State *ls, const std::string &s);
int clua_pushpoint(lua_State *ls, const coord_def &pos);

#endif