aboutsummaryrefslogtreecommitdiff
path: root/src/script/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/common')
-rw-r--r--src/script/common/c_content.cpp203
-rw-r--r--src/script/common/c_content.h4
-rw-r--r--src/script/common/c_converter.cpp106
-rw-r--r--src/script/common/c_converter.h6
-rw-r--r--src/script/common/c_internal.cpp9
-rw-r--r--src/script/common/c_internal.h10
6 files changed, 238 insertions, 100 deletions
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index accbb1a87..3dfd7ce61 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_types.h"
#include "nodedef.h"
#include "object_properties.h"
-#include "content_sao.h"
+#include "collision.h"
#include "cpp_api/s_node.h"
#include "lua_api/l_object.h"
#include "lua_api/l_item.h"
@@ -29,10 +29,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "server.h"
#include "log.h"
#include "tool.h"
-#include "serverobject.h"
#include "porting.h"
#include "mapgen/mg_schematic.h"
#include "noise.h"
+#include "server/player_sao.h"
#include "util/pointedthing.h"
#include "debug.h" // For FATAL_ERROR
#include <json/json.h>
@@ -103,7 +103,8 @@ void read_item_definition(lua_State* L, int index,
lua_pop(L, 1);
lua_getfield(L, index, "sounds");
- if(lua_istable(L, -1)){
+ if (!lua_isnil(L, -1)) {
+ luaL_checktype(L, -1, LUA_TTABLE);
lua_getfield(L, -1, "place");
read_soundspec(L, -1, def.sound_place);
lua_pop(L, 1);
@@ -163,7 +164,7 @@ void push_item_definition_full(lua_State *L, const ItemDefinition &i)
lua_setfield(L, -2, "usable");
lua_pushboolean(L, i.liquids_pointable);
lua_setfield(L, -2, "liquids_pointable");
- if (i.type == ITEM_TOOL) {
+ if (i.tool_capabilities) {
push_tool_capabilities(L, *i.tool_capabilities);
lua_setfield(L, -2, "tool_capabilities");
}
@@ -183,9 +184,11 @@ void read_object_properties(lua_State *L, int index,
{
if(index < 0)
index = lua_gettop(L) + 1 + index;
- if(!lua_istable(L, index))
+ if (lua_isnil(L, index))
return;
+ luaL_checktype(L, -1, LUA_TTABLE);
+
int hp_max = 0;
if (getintfield(L, -1, "hp_max", hp_max)) {
prop->hp_max = (u16)rangelim(hp_max, 0, U16_MAX);
@@ -324,6 +327,9 @@ void read_object_properties(lua_State *L, int index,
getfloatfield(L, -1, "zoom_fov", prop->zoom_fov);
getboolfield(L, -1, "use_texture_alpha", prop->use_texture_alpha);
+ getboolfield(L, -1, "shaded", prop->shaded);
+
+ getstringfield(L, -1, "damage_texture_modifier", prop->damage_texture_modifier);
}
/******************************************************************************/
@@ -351,7 +357,7 @@ void push_object_properties(lua_State *L, ObjectProperties *prop)
push_v3f(L, prop->visual_size);
lua_setfield(L, -2, "visual_size");
- lua_newtable(L);
+ lua_createtable(L, prop->textures.size(), 0);
u16 i = 1;
for (const std::string &texture : prop->textures) {
lua_pushlstring(L, texture.c_str(), texture.size());
@@ -359,7 +365,7 @@ void push_object_properties(lua_State *L, ObjectProperties *prop)
}
lua_setfield(L, -2, "textures");
- lua_newtable(L);
+ lua_createtable(L, prop->colors.size(), 0);
i = 1;
for (const video::SColor &color : prop->colors) {
push_ARGB8(L, color);
@@ -406,6 +412,10 @@ void push_object_properties(lua_State *L, ObjectProperties *prop)
lua_setfield(L, -2, "zoom_fov");
lua_pushboolean(L, prop->use_texture_alpha);
lua_setfield(L, -2, "use_texture_alpha");
+ lua_pushboolean(L, prop->shaded);
+ lua_setfield(L, -2, "shaded");
+ lua_pushlstring(L, prop->damage_texture_modifier.c_str(), prop->damage_texture_modifier.size());
+ lua_setfield(L, -2, "damage_texture_modifier");
}
/******************************************************************************/
@@ -687,6 +697,8 @@ ContentFeatures read_content_features(lua_State *L, int index)
f.liquid_range = getintfield_default(L, index,
"liquid_range", f.liquid_range);
f.leveled = getintfield_default(L, index, "leveled", f.leveled);
+ f.leveled_max = getintfield_default(L, index,
+ "leveled_max", f.leveled_max);
getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
f.drowning = getintfield_default(L, index,
@@ -841,7 +853,7 @@ void push_content_features(lua_State *L, const ContentFeatures &c)
lua_pushnumber(L, c.connect_sides);
lua_setfield(L, -2, "connect_sides");
- lua_newtable(L);
+ lua_createtable(L, c.connects_to.size(), 0);
u16 i = 1;
for (const std::string &it : c.connects_to) {
lua_pushlstring(L, it.c_str(), it.size());
@@ -853,6 +865,8 @@ void push_content_features(lua_State *L, const ContentFeatures &c)
lua_setfield(L, -2, "post_effect_color");
lua_pushnumber(L, c.leveled);
lua_setfield(L, -2, "leveled");
+ lua_pushnumber(L, c.leveled_max);
+ lua_setfield(L, -2, "leveled_max");
lua_pushboolean(L, c.sunlight_propagates);
lua_setfield(L, -2, "sunlight_propagates");
lua_pushnumber(L, c.light_source);
@@ -964,7 +978,7 @@ void push_nodebox(lua_State *L, const NodeBox &box)
void push_box(lua_State *L, const std::vector<aabb3f> &box)
{
- lua_newtable(L);
+ lua_createtable(L, box.size(), 0);
u8 i = 1;
for (const aabb3f &it : box) {
push_aabb3f(L, it);
@@ -1028,20 +1042,22 @@ void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec)
{
if(index < 0)
index = lua_gettop(L) + 1 + index;
- if(lua_isnil(L, index)){
- } else if(lua_istable(L, index)){
+ if (lua_isnil(L, index))
+ return;
+
+ if (lua_istable(L, index)) {
getstringfield(L, index, "name", spec.name);
getfloatfield(L, index, "gain", spec.gain);
getfloatfield(L, index, "fade", spec.fade);
getfloatfield(L, index, "pitch", spec.pitch);
- } else if(lua_isstring(L, index)){
+ } else if (lua_isstring(L, index)) {
spec.name = lua_tostring(L, index);
}
}
void push_soundspec(lua_State *L, const SimpleSoundSpec &spec)
{
- lua_newtable(L);
+ lua_createtable(L, 0, 3);
lua_pushstring(L, spec.name.c_str());
lua_setfield(L, -2, "name");
lua_pushnumber(L, spec.gain);
@@ -1056,9 +1072,13 @@ void push_soundspec(lua_State *L, const SimpleSoundSpec &spec)
NodeBox read_nodebox(lua_State *L, int index)
{
NodeBox nodebox;
- if(lua_istable(L, -1)){
- nodebox.type = (NodeBoxType)getenumfield(L, index, "type",
- ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR);
+ if (lua_isnil(L, -1))
+ return nodebox;
+
+ luaL_checktype(L, -1, LUA_TTABLE);
+
+ nodebox.type = (NodeBoxType)getenumfield(L, index, "type",
+ ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR);
#define NODEBOXREAD(n, s){ \
lua_getfield(L, index, (s)); \
@@ -1068,30 +1088,30 @@ NodeBox read_nodebox(lua_State *L, int index)
}
#define NODEBOXREADVEC(n, s) \
- lua_getfield(L, index, (s)); \
- if (lua_istable(L, -1)) \
- (n) = read_aabb3f_vector(L, -1, BS); \
- lua_pop(L, 1);
+ lua_getfield(L, index, (s)); \
+ if (lua_istable(L, -1)) \
+ (n) = read_aabb3f_vector(L, -1, BS); \
+ lua_pop(L, 1);
+
+ NODEBOXREADVEC(nodebox.fixed, "fixed");
+ NODEBOXREAD(nodebox.wall_top, "wall_top");
+ NODEBOXREAD(nodebox.wall_bottom, "wall_bottom");
+ NODEBOXREAD(nodebox.wall_side, "wall_side");
+ NODEBOXREADVEC(nodebox.connect_top, "connect_top");
+ NODEBOXREADVEC(nodebox.connect_bottom, "connect_bottom");
+ NODEBOXREADVEC(nodebox.connect_front, "connect_front");
+ NODEBOXREADVEC(nodebox.connect_left, "connect_left");
+ NODEBOXREADVEC(nodebox.connect_back, "connect_back");
+ NODEBOXREADVEC(nodebox.connect_right, "connect_right");
+ NODEBOXREADVEC(nodebox.disconnected_top, "disconnected_top");
+ NODEBOXREADVEC(nodebox.disconnected_bottom, "disconnected_bottom");
+ NODEBOXREADVEC(nodebox.disconnected_front, "disconnected_front");
+ NODEBOXREADVEC(nodebox.disconnected_left, "disconnected_left");
+ NODEBOXREADVEC(nodebox.disconnected_back, "disconnected_back");
+ NODEBOXREADVEC(nodebox.disconnected_right, "disconnected_right");
+ NODEBOXREADVEC(nodebox.disconnected, "disconnected");
+ NODEBOXREADVEC(nodebox.disconnected_sides, "disconnected_sides");
- NODEBOXREADVEC(nodebox.fixed, "fixed");
- NODEBOXREAD(nodebox.wall_top, "wall_top");
- NODEBOXREAD(nodebox.wall_bottom, "wall_bottom");
- NODEBOXREAD(nodebox.wall_side, "wall_side");
- NODEBOXREADVEC(nodebox.connect_top, "connect_top");
- NODEBOXREADVEC(nodebox.connect_bottom, "connect_bottom");
- NODEBOXREADVEC(nodebox.connect_front, "connect_front");
- NODEBOXREADVEC(nodebox.connect_left, "connect_left");
- NODEBOXREADVEC(nodebox.connect_back, "connect_back");
- NODEBOXREADVEC(nodebox.connect_right, "connect_right");
- NODEBOXREADVEC(nodebox.disconnected_top, "disconnected_top");
- NODEBOXREADVEC(nodebox.disconnected_bottom, "disconnected_bottom");
- NODEBOXREADVEC(nodebox.disconnected_front, "disconnected_front");
- NODEBOXREADVEC(nodebox.disconnected_left, "disconnected_left");
- NODEBOXREADVEC(nodebox.disconnected_back, "disconnected_back");
- NODEBOXREADVEC(nodebox.disconnected_right, "disconnected_right");
- NODEBOXREADVEC(nodebox.disconnected, "disconnected");
- NODEBOXREADVEC(nodebox.disconnected_sides, "disconnected_sides");
- }
return nodebox;
}
@@ -1126,12 +1146,12 @@ MapNode readnode(lua_State *L, int index, const NodeDefManager *ndef)
/******************************************************************************/
void pushnode(lua_State *L, const MapNode &n, const NodeDefManager *ndef)
{
- lua_newtable(L);
+ lua_createtable(L, 0, 3);
lua_pushstring(L, ndef->get(n).name.c_str());
lua_setfield(L, -2, "name");
- lua_pushnumber(L, n.getParam1());
+ lua_pushinteger(L, n.getParam1());
lua_setfield(L, -2, "param1");
- lua_pushnumber(L, n.getParam2());
+ lua_pushinteger(L, n.getParam2());
lua_setfield(L, -2, "param2");
}
@@ -1164,7 +1184,7 @@ bool string_to_enum(const EnumString *spec, int &result,
{
const EnumString *esp = spec;
while(esp->str){
- if(str == std::string(esp->str)){
+ if (!strcmp(str.c_str(), esp->str)) {
result = esp->num;
return true;
}
@@ -1439,7 +1459,7 @@ ToolCapabilities read_tool_capabilities(
/******************************************************************************/
void push_dig_params(lua_State *L,const DigParams &params)
{
- lua_newtable(L);
+ lua_createtable(L, 0, 3);
setboolfield(L, -1, "diggable", params.diggable);
setfloatfield(L, -1, "time", params.time);
setintfield(L, -1, "wear", params.wear);
@@ -1448,7 +1468,7 @@ void push_dig_params(lua_State *L,const DigParams &params)
/******************************************************************************/
void push_hit_params(lua_State *L,const HitParams &params)
{
- lua_newtable(L);
+ lua_createtable(L, 0, 3);
setintfield(L, -1, "hp", params.hp);
setintfield(L, -1, "wear", params.wear);
}
@@ -1520,8 +1540,11 @@ void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask
/******************************************************************************/
void read_groups(lua_State *L, int index, ItemGroupList &result)
{
- if (!lua_istable(L,index))
+ if (lua_isnil(L, index))
return;
+
+ luaL_checktype(L, index, LUA_TTABLE);
+
result.clear();
lua_pushnil(L);
if (index < 0)
@@ -1541,9 +1564,9 @@ void read_groups(lua_State *L, int index, ItemGroupList &result)
/******************************************************************************/
void push_groups(lua_State *L, const ItemGroupList &groups)
{
- lua_newtable(L);
+ lua_createtable(L, 0, groups.size());
for (const auto &group : groups) {
- lua_pushnumber(L, group.second);
+ lua_pushinteger(L, group.second);
lua_setfield(L, -2, group.first.c_str());
}
}
@@ -1588,7 +1611,7 @@ void luaentity_get(lua_State *L, u16 id)
lua_getglobal(L, "core");
lua_getfield(L, -1, "luaentities");
luaL_checktype(L, -1, LUA_TTABLE);
- lua_pushnumber(L, id);
+ lua_pushinteger(L, id);
lua_gettable(L, -2);
lua_remove(L, -2); // Remove luaentities
lua_remove(L, -2); // Remove core
@@ -1672,10 +1695,10 @@ static bool push_json_value_helper(lua_State *L, const Json::Value &value,
lua_pushvalue(L, nullindex);
break;
case Json::intValue:
- lua_pushinteger(L, value.asInt());
+ lua_pushinteger(L, value.asLargestInt());
break;
case Json::uintValue:
- lua_pushinteger(L, value.asUInt());
+ lua_pushinteger(L, value.asLargestUInt());
break;
case Json::realValue:
lua_pushnumber(L, value.asDouble());
@@ -1690,7 +1713,7 @@ static bool push_json_value_helper(lua_State *L, const Json::Value &value,
lua_pushboolean(L, value.asInt());
break;
case Json::arrayValue:
- lua_newtable(L);
+ lua_createtable(L, value.size(), 0);
for (Json::Value::const_iterator it = value.begin();
it != value.end(); ++it) {
push_json_value_helper(L, *it, nullindex);
@@ -1698,10 +1721,10 @@ static bool push_json_value_helper(lua_State *L, const Json::Value &value,
}
break;
case Json::objectValue:
- lua_newtable(L);
+ lua_createtable(L, 0, value.size());
for (Json::Value::const_iterator it = value.begin();
it != value.end(); ++it) {
-#ifndef JSONCPP_STRING
+#if !defined(JSONCPP_STRING) && (JSONCPP_VERSION_MAJOR < 1 || JSONCPP_VERSION_MINOR < 9)
const char *str = it.memberName();
lua_pushstring(L, str ? str : "");
#else
@@ -1825,7 +1848,7 @@ void push_objectRef(lua_State *L, const u16 id)
lua_getglobal(L, "core");
lua_getfield(L, -1, "object_refs");
luaL_checktype(L, -1, LUA_TTABLE);
- lua_pushnumber(L, id);
+ lua_pushinteger(L, id);
lua_gettable(L, -2);
lua_remove(L, -2); // object_refs
lua_remove(L, -2); // core
@@ -1851,10 +1874,15 @@ void read_hud_element(lua_State *L, HudElement *elem)
elem->name = getstringfield_default(L, 2, "name", "");
elem->text = getstringfield_default(L, 2, "text", "");
elem->number = getintfield_default(L, 2, "number", 0);
- elem->item = getintfield_default(L, 2, "item", 0);
+ if (elem->type == HUD_ELEM_WAYPOINT)
+ // waypoints reuse the item field to store precision, item = precision + 1
+ elem->item = getintfield_default(L, 2, "precision", -1) + 1;
+ else
+ elem->item = getintfield_default(L, 2, "item", 0);
elem->dir = getintfield_default(L, 2, "direction", 0);
elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX,
getintfield_default(L, 2, "z_index", 0)));
+ elem->text2 = getstringfield_default(L, 2, "text2", "");
// Deprecated, only for compatibility's sake
if (elem->dir == 0)
@@ -1923,6 +1951,9 @@ void push_hud_element(lua_State *L, HudElement *elem)
lua_pushnumber(L, elem->z_index);
lua_setfield(L, -2, "z_index");
+
+ lua_pushstring(L, elem->text2.c_str());
+ lua_setfield(L, -2, "text2");
}
HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
@@ -1984,6 +2015,66 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX, luaL_checknumber(L, 4)));
*value = &elem->z_index;
break;
+ case HUD_STAT_TEXT2:
+ elem->text2 = luaL_checkstring(L, 4);
+ *value = &elem->text2;
+ break;
}
return stat;
}
+
+/******************************************************************************/
+
+// Indices must match values in `enum CollisionType` exactly!!
+static const char *collision_type_str[] = {
+ "node",
+ "object",
+};
+
+// Indices must match values in `enum CollisionAxis` exactly!!
+static const char *collision_axis_str[] = {
+ "x",
+ "y",
+ "z",
+};
+
+void push_collision_move_result(lua_State *L, const collisionMoveResult &res)
+{
+ lua_createtable(L, 0, 4);
+
+ setboolfield(L, -1, "touching_ground", res.touching_ground);
+ setboolfield(L, -1, "collides", res.collides);
+ setboolfield(L, -1, "standing_on_object", res.standing_on_object);
+
+ /* collisions */
+ lua_createtable(L, res.collisions.size(), 0);
+ int i = 1;
+ for (const auto &c : res.collisions) {
+ lua_createtable(L, 0, 5);
+
+ lua_pushstring(L, collision_type_str[c.type]);
+ lua_setfield(L, -2, "type");
+
+ assert(c.axis != COLLISION_AXIS_NONE);
+ lua_pushstring(L, collision_axis_str[c.axis]);
+ lua_setfield(L, -2, "axis");
+
+ if (c.type == COLLISION_NODE) {
+ push_v3s16(L, c.node_p);
+ lua_setfield(L, -2, "node_pos");
+ } else if (c.type == COLLISION_OBJECT) {
+ push_objectRef(L, c.object->getId());
+ lua_setfield(L, -2, "object");
+ }
+
+ push_v3f(L, c.old_speed / BS);
+ lua_setfield(L, -2, "old_velocity");
+
+ push_v3f(L, c.new_speed / BS);
+ lua_setfield(L, -2, "new_velocity");
+
+ lua_rawseti(L, -2, i++);
+ }
+ lua_setfield(L, -2, "collisions");
+ /**/
+}
diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h
index 9e755682f..8f32e58eb 100644
--- a/src/script/common/c_content.h
+++ b/src/script/common/c_content.h
@@ -63,7 +63,9 @@ struct EnumString;
struct NoiseParams;
class Schematic;
class ServerActiveObject;
+struct collisionMoveResult;
+extern struct EnumString es_TileAnimationType[];
ContentFeatures read_content_features (lua_State *L, int index);
void push_content_features (lua_State *L,
@@ -196,4 +198,4 @@ void push_hud_element (lua_State *L, HudElement *elem);
HudElementStat read_hud_change (lua_State *L, HudElement *elem, void **value);
-extern struct EnumString es_TileAnimationType[];
+void push_collision_move_result(lua_State *L, const collisionMoveResult &res);
diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp
index 3c2f75641..eb6ab5331 100644
--- a/src/script/common/c_converter.cpp
+++ b/src/script/common/c_converter.cpp
@@ -28,15 +28,15 @@ extern "C" {
#include "common/c_converter.h"
#include "common/c_internal.h"
#include "constants.h"
+#include <set>
#define CHECK_TYPE(index, name, type) { \
int t = lua_type(L, (index)); \
if (t != (type)) { \
- std::string traceback = script_get_backtrace(L); \
throw LuaError(std::string("Invalid ") + (name) + \
" (expected " + lua_typename(L, (type)) + \
- " got " + lua_typename(L, t) + ").\n" + traceback); \
+ " got " + lua_typename(L, t) + ")."); \
} \
}
#define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER)
@@ -62,7 +62,7 @@ void push_float_string(lua_State *L, float value)
void push_v3f(lua_State *L, v3f p)
{
- lua_newtable(L);
+ lua_createtable(L, 0, 3);
lua_pushnumber(L, p.X);
lua_setfield(L, -2, "x");
lua_pushnumber(L, p.Y);
@@ -73,7 +73,7 @@ void push_v3f(lua_State *L, v3f p)
void push_v2f(lua_State *L, v2f p)
{
- lua_newtable(L);
+ lua_createtable(L, 0, 2);
lua_pushnumber(L, p.X);
lua_setfield(L, -2, "x");
lua_pushnumber(L, p.Y);
@@ -82,7 +82,7 @@ void push_v2f(lua_State *L, v2f p)
void push_v3_float_string(lua_State *L, v3f p)
{
- lua_newtable(L);
+ lua_createtable(L, 0, 3);
push_float_string(L, p.X);
lua_setfield(L, -2, "x");
push_float_string(L, p.Y);
@@ -93,7 +93,7 @@ void push_v3_float_string(lua_State *L, v3f p)
void push_v2_float_string(lua_State *L, v2f p)
{
- lua_newtable(L);
+ lua_createtable(L, 0, 2);
push_float_string(L, p.X);
lua_setfield(L, -2, "x");
push_float_string(L, p.Y);
@@ -115,19 +115,19 @@ v2s16 read_v2s16(lua_State *L, int index)
void push_v2s16(lua_State *L, v2s16 p)
{
- lua_newtable(L);
- lua_pushnumber(L, p.X);
+ lua_createtable(L, 0, 2);
+ lua_pushinteger(L, p.X);
lua_setfield(L, -2, "x");
- lua_pushnumber(L, p.Y);
+ lua_pushinteger(L, p.Y);
lua_setfield(L, -2, "y");
}
void push_v2s32(lua_State *L, v2s32 p)
{
- lua_newtable(L);
- lua_pushnumber(L, p.X);
+ lua_createtable(L, 0, 2);
+ lua_pushinteger(L, p.X);
lua_setfield(L, -2, "x");
- lua_pushnumber(L, p.Y);
+ lua_pushinteger(L, p.Y);
lua_setfield(L, -2, "y");
}
@@ -250,14 +250,14 @@ v3d check_v3d(lua_State *L, int index)
void push_ARGB8(lua_State *L, video::SColor color)
{
- lua_newtable(L);
- lua_pushnumber(L, color.getAlpha());
+ lua_createtable(L, 0, 4);
+ lua_pushinteger(L, color.getAlpha());
lua_setfield(L, -2, "a");
- lua_pushnumber(L, color.getRed());
+ lua_pushinteger(L, color.getRed());
lua_setfield(L, -2, "r");
- lua_pushnumber(L, color.getGreen());
+ lua_pushinteger(L, color.getGreen());
lua_setfield(L, -2, "g");
- lua_pushnumber(L, color.getBlue());
+ lua_pushinteger(L, color.getBlue());
lua_setfield(L, -2, "b");
}
@@ -274,12 +274,12 @@ v3f checkFloatPos(lua_State *L, int index)
void push_v3s16(lua_State *L, v3s16 p)
{
- lua_newtable(L);
- lua_pushnumber(L, p.X);
+ lua_createtable(L, 0, 3);
+ lua_pushinteger(L, p.X);
lua_setfield(L, -2, "x");
- lua_pushnumber(L, p.Y);
+ lua_pushinteger(L, p.Y);
lua_setfield(L, -2, "y");
- lua_pushnumber(L, p.Z);
+ lua_pushinteger(L, p.Z);
lua_setfield(L, -2, "z");
}
@@ -386,7 +386,7 @@ aabb3f read_aabb3f(lua_State *L, int index, f32 scale)
void push_aabb3f(lua_State *L, aabb3f box)
{
- lua_newtable(L);
+ lua_createtable(L, 6, 0);
lua_pushnumber(L, box.MinEdge.X);
lua_rawseti(L, -2, 1);
lua_pushnumber(L, box.MinEdge.Y);
@@ -457,12 +457,55 @@ size_t read_stringlist(lua_State *L, int index, std::vector<std::string> *result
Table field getters
*/
+#if defined(__MINGW32__) && !defined(__MINGW64__)
+/* MinGW 32-bit somehow crashes in the std::set destructor when this
+ * variable is thread-local, so just don't do that. */
+static std::set<u64> warned_msgs;
+#endif
+
+bool check_field_or_nil(lua_State *L, int index, int type, const char *fieldname)
+{
+#if !defined(__MINGW32__) || defined(__MINGW64__)
+ thread_local std::set<u64> warned_msgs;
+#endif
+
+ int t = lua_type(L, index);
+ if (t == LUA_TNIL)
+ return false;
+
+ if (t == type)
+ return true;
+
+ // Check coercion types
+ if (type == LUA_TNUMBER) {
+ if (lua_isnumber(L, index))
+ return true;
+ } else if (type == LUA_TSTRING) {
+ if (lua_isstring(L, index))
+ return true;
+ }
+
+ // Types mismatch. Log unique line.
+ std::string backtrace = std::string("Invalid field ") + fieldname +
+ " (expected " + lua_typename(L, type) +
+ " got " + lua_typename(L, t) + ").\n" + script_get_backtrace(L);
+
+ u64 hash = murmur_hash_64_ua(backtrace.data(), backtrace.length(), 0xBADBABE);
+ if (warned_msgs.find(hash) == warned_msgs.end()) {
+ errorstream << backtrace << std::endl;
+ warned_msgs.insert(hash);
+ }
+
+ return false;
+}
+
bool getstringfield(lua_State *L, int table,
const char *fieldname, std::string &result)
{
lua_getfield(L, table, fieldname);
bool got = false;
- if(lua_isstring(L, -1)){
+
+ if (check_field_or_nil(L, -1, LUA_TSTRING, fieldname)) {
size_t len = 0;
const char *ptr = lua_tolstring(L, -1, &len);
if (ptr) {
@@ -479,7 +522,8 @@ bool getfloatfield(lua_State *L, int table,
{
lua_getfield(L, table, fieldname);
bool got = false;
- if(lua_isnumber(L, -1)){
+
+ if (check_field_or_nil(L, -1, LUA_TNUMBER, fieldname)) {
result = lua_tonumber(L, -1);
got = true;
}
@@ -492,7 +536,8 @@ bool getboolfield(lua_State *L, int table,
{
lua_getfield(L, table, fieldname);
bool got = false;
- if(lua_isboolean(L, -1)){
+
+ if (check_field_or_nil(L, -1, LUA_TBOOLEAN, fieldname)){
result = lua_toboolean(L, -1);
got = true;
}
@@ -511,17 +556,6 @@ size_t getstringlistfield(lua_State *L, int table, const char *fieldname,
return num_strings_read;
}
-std::string checkstringfield(lua_State *L, int table,
- const char *fieldname)
-{
- lua_getfield(L, table, fieldname);
- CHECK_TYPE(-1, std::string("field \"") + fieldname + '"', LUA_TSTRING);
- size_t len;
- const char *s = lua_tolstring(L, -1, &len);
- lua_pop(L, 1);
- return std::string(s, len);
-}
-
std::string getstringfield_default(lua_State *L, int table,
const char *fieldname, const std::string &default_)
{
diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h
index 9620bf75a..a4a7079fd 100644
--- a/src/script/common/c_converter.h
+++ b/src/script/common/c_converter.h
@@ -45,13 +45,15 @@ float getfloatfield_default(lua_State *L, int table,
int getintfield_default(lua_State *L, int table,
const char *fieldname, int default_);
+bool check_field_or_nil(lua_State *L, int index, int type, const char *fieldname);
+
template<typename T>
bool getintfield(lua_State *L, int table,
const char *fieldname, T &result)
{
lua_getfield(L, table, fieldname);
bool got = false;
- if (lua_isnumber(L, -1)){
+ if (check_field_or_nil(L, -1, LUA_TNUMBER, fieldname)){
result = lua_tointeger(L, -1);
got = true;
}
@@ -87,8 +89,6 @@ bool getboolfield(lua_State *L, int table,
const char *fieldname, bool &result);
bool getfloatfield(lua_State *L, int table,
const char *fieldname, float &result);
-std::string checkstringfield(lua_State *L, int table,
- const char *fieldname);
void setstringfield(lua_State *L, int table,
const char *fieldname, const std::string &value);
diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp
index b19af9f82..6df1f8b7b 100644
--- a/src/script/common/c_internal.cpp
+++ b/src/script/common/c_internal.cpp
@@ -157,9 +157,9 @@ static void script_log(lua_State *L, const std::string &message,
void log_deprecated(lua_State *L, const std::string &message, int stack_depth)
{
- static bool configured = false;
- static bool do_log = false;
- static bool do_error = false;
+ static thread_local bool configured = false;
+ static thread_local bool do_log = false;
+ static thread_local bool do_error = false;
// Only read settings on first call
if (!configured) {
@@ -167,9 +167,10 @@ void log_deprecated(lua_State *L, const std::string &message, int stack_depth)
if (value == "log") {
do_log = true;
} else if (value == "error") {
- do_log = true;
+ do_log = true;
do_error = true;
}
+ configured = true;
}
if (do_log)
diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h
index d8cf3fe76..442546332 100644
--- a/src/script/common/c_internal.h
+++ b/src/script/common/c_internal.h
@@ -31,6 +31,7 @@ extern "C" {
#include <lauxlib.h>
}
+#include "config.h"
#include "common/c_types.h"
@@ -54,6 +55,15 @@ extern "C" {
#define CUSTOM_RIDX_CURRENT_MOD_NAME (CUSTOM_RIDX_BASE + 2)
#define CUSTOM_RIDX_BACKTRACE (CUSTOM_RIDX_BASE + 3)
+// Determine if CUSTOM_RIDX_SCRIPTAPI will hold a light or full userdata
+#if defined(__aarch64__) && USE_LUAJIT
+/* LuaJIT has a 47-bit limit for lightuserdata on this platform and we cannot
+ * assume that the ScriptApi class was allocated at a fitting address. */
+#define INDIRECT_SCRIPTAPI_RIDX 1
+#else
+#define INDIRECT_SCRIPTAPI_RIDX 0
+#endif
+
// Pushes the error handler onto the stack and returns its index
#define PUSH_ERROR_HANDLER(L) \
(lua_rawgeti((L), LUA_REGISTRYINDEX, CUSTOM_RIDX_BACKTRACE), lua_gettop((L)))