3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "util/numeric.h"
26 #include "util/serialize.h"
27 #include "util/string.h"
28 #include "common/c_converter.h"
29 #include "common/c_internal.h"
30 #include "constants.h"
33 #define CHECK_TYPE(index, name, type) { \
34 int t = lua_type(L, (index)); \
36 std::string traceback = script_get_backtrace(L); \
37 throw LuaError(std::string("Invalid ") + (name) + \
38 " (expected " + lua_typename(L, (type)) + \
39 " got " + lua_typename(L, t) + ").\n" + traceback); \
42 #define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER)
43 #define CHECK_FLOAT_RANGE(value, name) \
44 if (value < F1000_MIN || value > F1000_MAX) { \
45 std::ostringstream error_text; \
46 error_text << "Invalid float vector dimension range '" name "' " << \
47 "(expected " << F1000_MIN << " < " name " < " << F1000_MAX << \
48 " got " << value << ")." << std::endl; \
49 throw LuaError(error_text.str()); \
51 #define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE)
54 void push_float_string(lua_State *L, float value)
60 lua_pushstring(L, str.c_str());
63 void push_v3f(lua_State *L, v3f p)
66 lua_pushnumber(L, p.X);
67 lua_setfield(L, -2, "x");
68 lua_pushnumber(L, p.Y);
69 lua_setfield(L, -2, "y");
70 lua_pushnumber(L, p.Z);
71 lua_setfield(L, -2, "z");
74 void push_v2f(lua_State *L, v2f p)
77 lua_pushnumber(L, p.X);
78 lua_setfield(L, -2, "x");
79 lua_pushnumber(L, p.Y);
80 lua_setfield(L, -2, "y");
83 void push_v3_float_string(lua_State *L, v3f p)
86 push_float_string(L, p.X);
87 lua_setfield(L, -2, "x");
88 push_float_string(L, p.Y);
89 lua_setfield(L, -2, "y");
90 push_float_string(L, p.Z);
91 lua_setfield(L, -2, "z");
94 void push_v2_float_string(lua_State *L, v2f p)
97 push_float_string(L, p.X);
98 lua_setfield(L, -2, "x");
99 push_float_string(L, p.Y);
100 lua_setfield(L, -2, "y");
103 v2s16 read_v2s16(lua_State *L, int index)
106 CHECK_POS_TAB(index);
107 lua_getfield(L, index, "x");
108 p.X = lua_tonumber(L, -1);
110 lua_getfield(L, index, "y");
111 p.Y = lua_tonumber(L, -1);
116 v2s16 check_v2s16(lua_State *L, int index)
119 CHECK_POS_TAB(index);
120 lua_getfield(L, index, "x");
121 CHECK_POS_COORD("x");
122 p.X = lua_tonumber(L, -1);
124 lua_getfield(L, index, "y");
125 CHECK_POS_COORD("y");
126 p.Y = lua_tonumber(L, -1);
131 void push_v2s16(lua_State *L, v2s16 p)
134 lua_pushnumber(L, p.X);
135 lua_setfield(L, -2, "x");
136 lua_pushnumber(L, p.Y);
137 lua_setfield(L, -2, "y");
140 void push_v2s32(lua_State *L, v2s32 p)
143 lua_pushnumber(L, p.X);
144 lua_setfield(L, -2, "x");
145 lua_pushnumber(L, p.Y);
146 lua_setfield(L, -2, "y");
149 v2s32 read_v2s32(lua_State *L, int index)
152 CHECK_POS_TAB(index);
153 lua_getfield(L, index, "x");
154 p.X = lua_tonumber(L, -1);
156 lua_getfield(L, index, "y");
157 p.Y = lua_tonumber(L, -1);
162 v2f read_v2f(lua_State *L, int index)
165 CHECK_POS_TAB(index);
166 lua_getfield(L, index, "x");
167 p.X = lua_tonumber(L, -1);
169 lua_getfield(L, index, "y");
170 p.Y = lua_tonumber(L, -1);
175 v2f check_v2f(lua_State *L, int index)
178 CHECK_POS_TAB(index);
179 lua_getfield(L, index, "x");
180 CHECK_POS_COORD("x");
181 p.X = lua_tonumber(L, -1);
183 lua_getfield(L, index, "y");
184 CHECK_POS_COORD("y");
185 p.Y = lua_tonumber(L, -1);
190 v3f read_v3f(lua_State *L, int index)
193 CHECK_POS_TAB(index);
194 lua_getfield(L, index, "x");
195 pos.X = lua_tonumber(L, -1);
197 lua_getfield(L, index, "y");
198 pos.Y = lua_tonumber(L, -1);
200 lua_getfield(L, index, "z");
201 pos.Z = lua_tonumber(L, -1);
206 v3f check_v3f(lua_State *L, int index)
209 CHECK_POS_TAB(index);
210 lua_getfield(L, index, "x");
211 CHECK_POS_COORD("x");
212 pos.X = lua_tonumber(L, -1);
213 CHECK_FLOAT_RANGE(pos.X, "x")
215 lua_getfield(L, index, "y");
216 CHECK_POS_COORD("y");
217 pos.Y = lua_tonumber(L, -1);
218 CHECK_FLOAT_RANGE(pos.Y, "y")
220 lua_getfield(L, index, "z");
221 CHECK_POS_COORD("z");
222 pos.Z = lua_tonumber(L, -1);
223 CHECK_FLOAT_RANGE(pos.Z, "z")
228 v3d read_v3d(lua_State *L, int index)
231 CHECK_POS_TAB(index);
232 lua_getfield(L, index, "x");
233 pos.X = lua_tonumber(L, -1);
235 lua_getfield(L, index, "y");
236 pos.Y = lua_tonumber(L, -1);
238 lua_getfield(L, index, "z");
239 pos.Z = lua_tonumber(L, -1);
244 v3d check_v3d(lua_State *L, int index)
247 CHECK_POS_TAB(index);
248 lua_getfield(L, index, "x");
249 CHECK_POS_COORD("x");
250 pos.X = lua_tonumber(L, -1);
251 CHECK_FLOAT_RANGE(pos.X, "x")
253 lua_getfield(L, index, "y");
254 CHECK_POS_COORD("y");
255 pos.Y = lua_tonumber(L, -1);
256 CHECK_FLOAT_RANGE(pos.Y, "y")
258 lua_getfield(L, index, "z");
259 CHECK_POS_COORD("z");
260 pos.Z = lua_tonumber(L, -1);
261 CHECK_FLOAT_RANGE(pos.Z, "z")
266 void push_ARGB8(lua_State *L, video::SColor color)
269 lua_pushnumber(L, color.getAlpha());
270 lua_setfield(L, -2, "a");
271 lua_pushnumber(L, color.getRed());
272 lua_setfield(L, -2, "r");
273 lua_pushnumber(L, color.getGreen());
274 lua_setfield(L, -2, "g");
275 lua_pushnumber(L, color.getBlue());
276 lua_setfield(L, -2, "b");
279 void pushFloatPos(lua_State *L, v3f p)
285 v3f checkFloatPos(lua_State *L, int index)
287 return check_v3f(L, index) * BS;
290 void push_v3s16(lua_State *L, v3s16 p)
293 lua_pushnumber(L, p.X);
294 lua_setfield(L, -2, "x");
295 lua_pushnumber(L, p.Y);
296 lua_setfield(L, -2, "y");
297 lua_pushnumber(L, p.Z);
298 lua_setfield(L, -2, "z");
301 v3s16 read_v3s16(lua_State *L, int index)
303 // Correct rounding at <0
304 v3d pf = read_v3d(L, index);
305 return doubleToInt(pf, 1.0);
308 v3s16 check_v3s16(lua_State *L, int index)
310 // Correct rounding at <0
311 v3d pf = check_v3d(L, index);
312 return doubleToInt(pf, 1.0);
315 bool read_color(lua_State *L, int index, video::SColor *color)
317 if (lua_istable(L, index)) {
318 *color = read_ARGB8(L, index);
319 } else if (lua_isnumber(L, index)) {
320 color->set(lua_tonumber(L, index));
321 } else if (lua_isstring(L, index)) {
322 video::SColor parsed_color;
323 if (!parseColorString(lua_tostring(L, index), parsed_color, true))
326 *color = parsed_color;
334 video::SColor read_ARGB8(lua_State *L, int index)
336 video::SColor color(0);
337 CHECK_TYPE(index, "ARGB color", LUA_TTABLE);
338 lua_getfield(L, index, "a");
339 color.setAlpha(lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 0xFF);
341 lua_getfield(L, index, "r");
342 color.setRed(lua_tonumber(L, -1));
344 lua_getfield(L, index, "g");
345 color.setGreen(lua_tonumber(L, -1));
347 lua_getfield(L, index, "b");
348 color.setBlue(lua_tonumber(L, -1));
353 aabb3f read_aabb3f(lua_State *L, int index, f32 scale)
356 if(lua_istable(L, index)){
357 lua_rawgeti(L, index, 1);
358 box.MinEdge.X = lua_tonumber(L, -1) * scale;
360 lua_rawgeti(L, index, 2);
361 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
363 lua_rawgeti(L, index, 3);
364 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
366 lua_rawgeti(L, index, 4);
367 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
369 lua_rawgeti(L, index, 5);
370 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
372 lua_rawgeti(L, index, 6);
373 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
380 void push_aabb3f(lua_State *L, aabb3f box)
383 lua_pushnumber(L, box.MinEdge.X);
384 lua_rawseti(L, -2, 1);
385 lua_pushnumber(L, box.MinEdge.Y);
386 lua_rawseti(L, -2, 2);
387 lua_pushnumber(L, box.MinEdge.Z);
388 lua_rawseti(L, -2, 3);
389 lua_pushnumber(L, box.MaxEdge.X);
390 lua_rawseti(L, -2, 4);
391 lua_pushnumber(L, box.MaxEdge.Y);
392 lua_rawseti(L, -2, 5);
393 lua_pushnumber(L, box.MaxEdge.Z);
394 lua_rawseti(L, -2, 6);
397 std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale)
399 std::vector<aabb3f> boxes;
400 if(lua_istable(L, index)){
401 int n = lua_objlen(L, index);
402 // Check if it's a single box or a list of boxes
403 bool possibly_single_box = (n == 6);
404 for(int i = 1; i <= n && possibly_single_box; i++){
405 lua_rawgeti(L, index, i);
406 if(!lua_isnumber(L, -1))
407 possibly_single_box = false;
410 if(possibly_single_box){
412 boxes.push_back(read_aabb3f(L, index, scale));
414 // Read a list of boxes
415 for(int i = 1; i <= n; i++){
416 lua_rawgeti(L, index, i);
417 boxes.push_back(read_aabb3f(L, -1, scale));
425 size_t read_stringlist(lua_State *L, int index, std::vector<std::string> *result)
428 index = lua_gettop(L) + 1 + index;
430 size_t num_strings = 0;
432 if (lua_istable(L, index)) {
434 while (lua_next(L, index)) {
435 if (lua_isstring(L, -1)) {
436 result->push_back(lua_tostring(L, -1));
441 } else if (lua_isstring(L, index)) {
442 result->push_back(lua_tostring(L, index));
453 bool getstringfield(lua_State *L, int table,
454 const char *fieldname, std::string &result)
456 lua_getfield(L, table, fieldname);
458 if(lua_isstring(L, -1)){
460 const char *ptr = lua_tolstring(L, -1, &len);
462 result.assign(ptr, len);
470 bool getfloatfield(lua_State *L, int table,
471 const char *fieldname, float &result)
473 lua_getfield(L, table, fieldname);
475 if(lua_isnumber(L, -1)){
476 result = lua_tonumber(L, -1);
483 bool getboolfield(lua_State *L, int table,
484 const char *fieldname, bool &result)
486 lua_getfield(L, table, fieldname);
488 if(lua_isboolean(L, -1)){
489 result = lua_toboolean(L, -1);
496 size_t getstringlistfield(lua_State *L, int table, const char *fieldname,
497 std::vector<std::string> *result)
499 lua_getfield(L, table, fieldname);
501 size_t num_strings_read = read_stringlist(L, -1, result);
504 return num_strings_read;
507 std::string checkstringfield(lua_State *L, int table,
508 const char *fieldname)
510 lua_getfield(L, table, fieldname);
511 CHECK_TYPE(-1, std::string("field \"") + fieldname + '"', LUA_TSTRING);
513 const char *s = lua_tolstring(L, -1, &len);
515 return std::string(s, len);
518 std::string getstringfield_default(lua_State *L, int table,
519 const char *fieldname, const std::string &default_)
521 std::string result = default_;
522 getstringfield(L, table, fieldname, result);
526 int getintfield_default(lua_State *L, int table,
527 const char *fieldname, int default_)
529 int result = default_;
530 getintfield(L, table, fieldname, result);
534 float getfloatfield_default(lua_State *L, int table,
535 const char *fieldname, float default_)
537 float result = default_;
538 getfloatfield(L, table, fieldname, result);
542 bool getboolfield_default(lua_State *L, int table,
543 const char *fieldname, bool default_)
545 bool result = default_;
546 getboolfield(L, table, fieldname, result);
550 v3s16 getv3s16field_default(lua_State *L, int table,
551 const char *fieldname, v3s16 default_)
553 getv3intfield(L, table, fieldname, default_);
557 void setstringfield(lua_State *L, int table,
558 const char *fieldname, const char *value)
560 lua_pushstring(L, value);
563 lua_setfield(L, table, fieldname);
566 void setintfield(lua_State *L, int table,
567 const char *fieldname, int value)
569 lua_pushinteger(L, value);
572 lua_setfield(L, table, fieldname);
575 void setfloatfield(lua_State *L, int table,
576 const char *fieldname, float value)
578 lua_pushnumber(L, value);
581 lua_setfield(L, table, fieldname);
584 void setboolfield(lua_State *L, int table,
585 const char *fieldname, bool value)
587 lua_pushboolean(L, value);
590 lua_setfield(L, table, fieldname);
595 //// Array table slices
598 size_t write_array_slice_float(
606 v3u16 pmin, pmax(data_size);
608 if (slice_offset.X > 0) {
610 pmin.X = slice_offset.X;
611 pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
614 if (slice_offset.Y > 0) {
616 pmin.Y = slice_offset.Y;
617 pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
620 if (slice_offset.Z > 0) {
622 pmin.Z = slice_offset.Z;
623 pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
626 const u32 ystride = data_size.X;
627 const u32 zstride = data_size.X * data_size.Y;
630 for (u32 z = pmin.Z; z != pmax.Z; z++)
631 for (u32 y = pmin.Y; y != pmax.Y; y++)
632 for (u32 x = pmin.X; x != pmax.X; x++) {
633 u32 i = z * zstride + y * ystride + x;
634 lua_pushnumber(L, data[i]);
635 lua_rawseti(L, table_index, elem_index);
639 return elem_index - 1;
643 size_t write_array_slice_u16(
651 v3u16 pmin, pmax(data_size);
653 if (slice_offset.X > 0) {
655 pmin.X = slice_offset.X;
656 pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
659 if (slice_offset.Y > 0) {
661 pmin.Y = slice_offset.Y;
662 pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
665 if (slice_offset.Z > 0) {
667 pmin.Z = slice_offset.Z;
668 pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
671 const u32 ystride = data_size.X;
672 const u32 zstride = data_size.X * data_size.Y;
675 for (u32 z = pmin.Z; z != pmax.Z; z++)
676 for (u32 y = pmin.Y; y != pmax.Y; y++)
677 for (u32 x = pmin.X; x != pmax.X; x++) {
678 u32 i = z * zstride + y * ystride + x;
679 lua_pushinteger(L, data[i]);
680 lua_rawseti(L, table_index, elem_index);
684 return elem_index - 1;