X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=src%2Fscript%2Fcommon%2Fc_content.cpp;h=78c46f0e086f5842bc4caa61fafc3ae83d644870;hb=82216e1476dff509ba0c83bfabf5e4ec6e1075b2;hp=8f08de1e5f838babd84b74bba6f93c59944d892d;hpb=08846cd05cd402cc7f8d025aaba96c5bb0aade2c;p=dragonfireclient.git diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 8f08de1e5..78c46f0e0 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -21,17 +21,19 @@ 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 "collision.h" #include "cpp_api/s_node.h" +#include "lua_api/l_clientobject.h" #include "lua_api/l_object.h" #include "lua_api/l_item.h" #include "common/c_internal.h" #include "server.h" #include "log.h" #include "tool.h" -#include "serverobject.h" #include "porting.h" -#include "mg_schematic.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 @@ -82,7 +84,7 @@ void read_item_definition(lua_State* L, int index, getboolfield(L, index, "liquids_pointable", def.liquids_pointable); warn_if_field_exists(L, index, "tool_digging_properties", - "Deprecated; use tool_capabilities"); + "Obsolete; use tool_capabilities"); lua_getfield(L, index, "tool_capabilities"); if(lua_istable(L, -1)){ @@ -102,7 +104,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); @@ -162,43 +165,55 @@ 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) { - push_tool_capabilities(L, ToolCapabilities( - i.tool_capabilities->full_punch_interval, - i.tool_capabilities->max_drop_level, - i.tool_capabilities->groupcaps, - i.tool_capabilities->damageGroups)); + if (i.tool_capabilities) { + push_tool_capabilities(L, *i.tool_capabilities); lua_setfield(L, -2, "tool_capabilities"); } push_groups(L, i.groups); lua_setfield(L, -2, "groups"); + lua_newtable(L); push_soundspec(L, i.sound_place); - lua_setfield(L, -2, "sound_place"); + lua_setfield(L, -2, "place"); push_soundspec(L, i.sound_place_failed); - lua_setfield(L, -2, "sound_place_failed"); + lua_setfield(L, -2, "place_failed"); + lua_setfield(L, -2, "sounds"); lua_pushstring(L, i.node_placement_prediction.c_str()); lua_setfield(L, -2, "node_placement_prediction"); } /******************************************************************************/ void read_object_properties(lua_State *L, int index, - ObjectProperties *prop, IItemDefManager *idef) + ServerActiveObject *sao, ObjectProperties *prop, IItemDefManager *idef) { 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 = (s16)rangelim(hp_max, 0, S16_MAX); + if (getintfield(L, -1, "hp_max", hp_max)) { + prop->hp_max = (u16)rangelim(hp_max, 0, U16_MAX); + + if (prop->hp_max < sao->getHP()) { + PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP); + sao->setHP(prop->hp_max, reason); + if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) + sao->getEnv()->getGameDef()->SendPlayerHPOrDie((PlayerSAO *)sao, reason); + } + } - getintfield(L, -1, "breath_max", prop->breath_max); + if (getintfield(L, -1, "breath_max", prop->breath_max)) { + if (sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + PlayerSAO *player = (PlayerSAO *)sao; + if (prop->breath_max < player->getBreath()) + player->setBreath(prop->breath_max); + } + } getboolfield(L, -1, "physical", prop->physical); getboolfield(L, -1, "collide_with_objects", prop->collideWithObjects); - getfloatfield(L, -1, "weight", prop->weight); - lua_getfield(L, -1, "collisionbox"); bool collisionbox_defined = lua_istable(L, -1); if (collisionbox_defined) @@ -218,8 +233,18 @@ void read_object_properties(lua_State *L, int index, getstringfield(L, -1, "mesh", prop->mesh); lua_getfield(L, -1, "visual_size"); - if(lua_istable(L, -1)) - prop->visual_size = read_v2f(L, -1); + if (lua_istable(L, -1)) { + // Backwards compatibility: Also accept { x = ?, y = ? } + v2f scale_xy = read_v2f(L, -1); + + f32 scale_z = scale_xy.X; + lua_getfield(L, -1, "z"); + if (lua_isnumber(L, -1)) + scale_z = lua_tonumber(L, -1); + lua_pop(L, 1); + + prop->visual_size = v3f(scale_xy.X, scale_xy.Y, scale_z); + } lua_pop(L, 1); lua_getfield(L, -1, "textures"); @@ -265,7 +290,7 @@ void read_object_properties(lua_State *L, int index, getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound); if (getfloatfield(L, -1, "stepheight", prop->stepheight)) prop->stepheight *= BS; - getboolfield(L, -1, "can_zoom", prop->can_zoom); + getfloatfield(L, -1, "eye_height", prop->eye_height); getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate); lua_getfield(L, -1, "automatic_face_movement_dir"); @@ -302,6 +327,12 @@ void read_object_properties(lua_State *L, int index, if (!lua_isnil(L, -1)) prop->wield_item = read_item(L, -1, idef).getItemString(); lua_pop(L, 1); + + 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); } /******************************************************************************/ @@ -316,8 +347,6 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) lua_setfield(L, -2, "physical"); lua_pushboolean(L, prop->collideWithObjects); lua_setfield(L, -2, "collide_with_objects"); - lua_pushnumber(L, prop->weight); - lua_setfield(L, -2, "weight"); push_aabb3f(L, prop->collisionbox); lua_setfield(L, -2, "collisionbox"); push_aabb3f(L, prop->selectionbox); @@ -328,22 +357,22 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) lua_setfield(L, -2, "visual"); lua_pushlstring(L, prop->mesh.c_str(), prop->mesh.size()); lua_setfield(L, -2, "mesh"); - push_v2f(L, prop->visual_size); + 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()); - lua_rawseti(L, -2, i); + lua_rawseti(L, -2, i++); } 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); - lua_rawseti(L, -2, i); + lua_rawseti(L, -2, i++); } lua_setfield(L, -2, "colors"); @@ -357,9 +386,8 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) lua_setfield(L, -2, "makes_footstep_sound"); lua_pushnumber(L, prop->stepheight / BS); lua_setfield(L, -2, "stepheight"); - lua_pushboolean(L, prop->can_zoom); - lua_setfield(L, -2, "can_zoom"); - + lua_pushnumber(L, prop->eye_height); + lua_setfield(L, -2, "eye_height"); lua_pushnumber(L, prop->automatic_rotate); lua_setfield(L, -2, "automatic_rotate"); if (prop->automatic_face_movement_dir) @@ -383,6 +411,14 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) lua_setfield(L, -2, "static_save"); lua_pushlstring(L, prop->wield_item.c_str(), prop->wield_item.size()); lua_setfield(L, -2, "wield_item"); + lua_pushnumber(L, prop->zoom_fov); + 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"); } /******************************************************************************/ @@ -431,6 +467,16 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype) L, index, "tileable_horizontal", default_tiling); tiledef.tileable_vertical = getboolfield_default( L, index, "tileable_vertical", default_tiling); + std::string align_style; + if (getstringfield(L, index, "align_style", align_style)) { + if (align_style == "user") + tiledef.align_style = ALIGN_STYLE_USER_DEFINED; + else if (align_style == "world") + tiledef.align_style = ALIGN_STYLE_WORLD; + else + tiledef.align_style = ALIGN_STYLE_NODE; + } + tiledef.scale = getintfield_default(L, index, "scale", 0); // color = ... lua_getfield(L, index, "color"); tiledef.has_color = read_color(L, -1, &tiledef.color); @@ -606,19 +652,19 @@ ContentFeatures read_content_features(lua_State *L, int index) warningstream << "Node " << f.name.c_str() << " has a palette, but not a suitable paramtype2." << std::endl; - // Warn about some deprecated fields + // Warn about some obsolete fields warn_if_field_exists(L, index, "wall_mounted", - "Deprecated; use paramtype2 = 'wallmounted'"); + "Obsolete; use paramtype2 = 'wallmounted'"); warn_if_field_exists(L, index, "light_propagates", - "Deprecated; determined from paramtype"); + "Obsolete; determined from paramtype"); warn_if_field_exists(L, index, "dug_item", - "Deprecated; use 'drop' field"); + "Obsolete; use 'drop' field"); warn_if_field_exists(L, index, "extra_dug_item", - "Deprecated; use 'drop' field"); + "Obsolete; use 'drop' field"); warn_if_field_exists(L, index, "extra_dug_item_rarity", - "Deprecated; use 'drop' field"); + "Obsolete; use 'drop' field"); warn_if_field_exists(L, index, "metadata_name", - "Deprecated; use on_add and metadata callbacks"); + "Obsolete; use on_add and metadata callbacks"); // True for all ground-like things like stone and mud, false for eg. trees getboolfield(L, index, "is_ground_content", f.is_ground_content); @@ -654,6 +700,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, @@ -808,11 +856,11 @@ 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()); - lua_rawseti(L, -2, i); + lua_rawseti(L, -2, i++); } lua_setfield(L, -2, "connects_to"); @@ -820,6 +868,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); @@ -866,11 +916,11 @@ void push_content_features(lua_State *L, const ContentFeatures &c) lua_setfield(L, -2, "collision_box"); lua_newtable(L); push_soundspec(L, c.sound_footstep); - lua_setfield(L, -2, "sound_footstep"); + lua_setfield(L, -2, "footstep"); push_soundspec(L, c.sound_dig); - lua_setfield(L, -2, "sound_dig"); + lua_setfield(L, -2, "dig"); push_soundspec(L, c.sound_dug); - lua_setfield(L, -2, "sound_dug"); + lua_setfield(L, -2, "dug"); lua_setfield(L, -2, "sounds"); lua_pushboolean(L, c.legacy_facedir_simple); lua_setfield(L, -2, "legacy_facedir_simple"); @@ -931,11 +981,11 @@ void push_nodebox(lua_State *L, const NodeBox &box) void push_box(lua_State *L, const std::vector &box) { - lua_newtable(L); + lua_createtable(L, box.size(), 0); u8 i = 1; for (const aabb3f &it : box) { push_aabb3f(L, it); - lua_rawseti(L, -2, i); + lua_rawseti(L, -2, i++); } } @@ -986,6 +1036,7 @@ void read_server_sound_params(lua_State *L, int index, params.max_hear_distance = BS*getfloatfield_default(L, index, "max_hear_distance", params.max_hear_distance/BS); getboolfield(L, index, "loop", params.loop); + getstringfield(L, index, "exclude_player", params.exclude_player); } } @@ -994,20 +1045,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); @@ -1022,9 +1075,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)); \ @@ -1034,32 +1091,40 @@ 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"); - } return nodebox; } /******************************************************************************/ -MapNode readnode(lua_State *L, int index, INodeDefManager *ndef) +MapNode readnode(lua_State *L, int index, const NodeDefManager *ndef) { lua_getfield(L, index, "name"); if (!lua_isstring(L, -1)) throw LuaError("Node name is not set or is not a string!"); - const char *name = lua_tostring(L, -1); + std::string name = lua_tostring(L, -1); lua_pop(L, 1); u8 param1 = 0; @@ -1074,18 +1139,22 @@ MapNode readnode(lua_State *L, int index, INodeDefManager *ndef) param2 = lua_tonumber(L, -1); lua_pop(L, 1); - return {ndef, name, param1, param2}; + content_t id = CONTENT_IGNORE; + if (!ndef->getId(name, id)) + throw LuaError("\"" + name + "\" is not a registered node!"); + + return {id, param1, param2}; } /******************************************************************************/ -void pushnode(lua_State *L, const MapNode &n, INodeDefManager *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"); } @@ -1118,7 +1187,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; } @@ -1200,7 +1269,8 @@ void push_tool_capabilities(lua_State *L, { lua_newtable(L); setfloatfield(L, -1, "full_punch_interval", toolcap.full_punch_interval); - setintfield(L, -1, "max_drop_level", toolcap.max_drop_level); + setintfield(L, -1, "max_drop_level", toolcap.max_drop_level); + setintfield(L, -1, "punch_attack_uses", toolcap.punch_attack_uses); // Create groupcaps table lua_newtable(L); // For each groupcap @@ -1237,6 +1307,20 @@ void push_tool_capabilities(lua_State *L, lua_setfield(L, -2, "damage_groups"); } +/******************************************************************************/ +void push_inventory(lua_State *L, Inventory *inventory) +{ + std::vector lists = inventory->getLists(); + std::vector::iterator iter = lists.begin(); + lua_createtable(L, 0, lists.size()); + for (; iter != lists.end(); iter++) { + const char* name = (*iter)->getName().c_str(); + lua_pushstring(L, name); + push_inventory_list(L, inventory, name); + lua_rawset(L, -3); + } +} + /******************************************************************************/ void push_inventory_list(lua_State *L, Inventory *inv, const char *name) { @@ -1322,6 +1406,7 @@ ToolCapabilities read_tool_capabilities( ToolCapabilities toolcap; getfloatfield(L, table, "full_punch_interval", toolcap.full_punch_interval); getintfield(L, table, "max_drop_level", toolcap.max_drop_level); + getintfield(L, table, "punch_attack_uses", toolcap.punch_attack_uses); lua_getfield(L, table, "groupcaps"); if(lua_istable(L, -1)){ int table_groupcaps = lua_gettop(L); @@ -1391,7 +1476,7 @@ ToolCapabilities read_tool_capabilities( /******************************************************************************/ void push_dig_params(lua_State *L,const DigParams ¶ms) { - 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); @@ -1400,7 +1485,7 @@ void push_dig_params(lua_State *L,const DigParams ¶ms) /******************************************************************************/ void push_hit_params(lua_State *L,const HitParams ¶ms) { - lua_newtable(L); + lua_createtable(L, 0, 3); setintfield(L, -1, "hp", params.hp); setintfield(L, -1, "wear", params.wear); } @@ -1472,17 +1557,22 @@ 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) + if (index < 0) index -= 1; - while(lua_next(L, index) != 0){ + while (lua_next(L, index) != 0) { // key at index -2 and value at index -1 std::string name = luaL_checkstring(L, -2); int rating = luaL_checkinteger(L, -1); - result[name] = rating; + // zero rating indicates not in the group + if (rating != 0) + result[name] = rating; // removes value, keeps key for next iteration lua_pop(L, 1); } @@ -1491,9 +1581,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()); } } @@ -1538,7 +1628,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 @@ -1576,13 +1666,13 @@ bool read_noiseparams(lua_State *L, int index, NoiseParams *np) void push_noiseparams(lua_State *L, NoiseParams *np) { lua_newtable(L); - lua_pushnumber(L, np->offset); + push_float_string(L, np->offset); lua_setfield(L, -2, "offset"); - lua_pushnumber(L, np->scale); + push_float_string(L, np->scale); lua_setfield(L, -2, "scale"); - lua_pushnumber(L, np->persist); + push_float_string(L, np->persist); lua_setfield(L, -2, "persistence"); - lua_pushnumber(L, np->lacunarity); + push_float_string(L, np->lacunarity); lua_setfield(L, -2, "lacunarity"); lua_pushnumber(L, np->seed); lua_setfield(L, -2, "seed"); @@ -1593,7 +1683,7 @@ void push_noiseparams(lua_State *L, NoiseParams *np) np->flags); lua_setfield(L, -2, "flags"); - push_v3f(L, np->spread); + push_v3_float_string(L, np->spread); lua_setfield(L, -2, "spread"); } @@ -1622,10 +1712,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()); @@ -1640,7 +1730,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); @@ -1648,10 +1738,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 @@ -1733,7 +1823,8 @@ void read_json_value(lua_State *L, Json::Value &root, int index, u8 recursion) lua_pop(L, 1); // Pop value } -void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm) +void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm, + bool hitpoint) { lua_newtable(L); if (pointed.type == POINTEDTHING_NODE) { @@ -1746,18 +1837,27 @@ void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm) } else if (pointed.type == POINTEDTHING_OBJECT) { lua_pushstring(L, "object"); lua_setfield(L, -2, "type"); - if (csm) { - lua_pushinteger(L, pointed.object_id); - lua_setfield(L, -2, "id"); +#ifndef SERVER + ClientObjectRef::create(L, pointed.object_id); +#endif } else { push_objectRef(L, pointed.object_id); - lua_setfield(L, -2, "ref"); } + + lua_setfield(L, -2, "ref"); } else { lua_pushstring(L, "nothing"); lua_setfield(L, -2, "type"); } + if (hitpoint && (pointed.type != POINTEDTHING_NOTHING)) { + push_v3f(L, pointed.intersection_point / BS); // convert to node coords + lua_setfield(L, -2, "intersection_point"); + push_v3s16(L, pointed.intersection_normal); + lua_setfield(L, -2, "intersection_normal"); + lua_pushinteger(L, pointed.box_id + 1); // change to Lua array index + lua_setfield(L, -2, "box_id"); + } } void push_objectRef(lua_State *L, const u16 id) @@ -1766,8 +1866,256 @@ 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 } + +void read_hud_element(lua_State *L, HudElement *elem) +{ + elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type", + es_HudElementType, HUD_ELEM_TEXT); + + lua_getfield(L, 2, "position"); + elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "scale"); + elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "size"); + elem->size = lua_istable(L, -1) ? read_v2s32(L, -1) : v2s32(); + lua_pop(L, 1); + + elem->name = getstringfield_default(L, 2, "name", ""); + elem->text = getstringfield_default(L, 2, "text", ""); + elem->number = getintfield_default(L, 2, "number", 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) + elem->dir = getintfield_default(L, 2, "dir", 0); + + lua_getfield(L, 2, "alignment"); + elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "offset"); + elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "world_pos"); + elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f(); + lua_pop(L, 1); + + /* check for known deprecated element usage */ + if ((elem->type == HUD_ELEM_STATBAR) && (elem->size == v2s32())) + log_deprecated(L,"Deprecated usage of statbar without size!"); +} + +void push_hud_element(lua_State *L, HudElement *elem) +{ + lua_newtable(L); + + lua_pushstring(L, es_HudElementType[(u8)elem->type].str); + lua_setfield(L, -2, "type"); + + push_v2f(L, elem->pos); + lua_setfield(L, -2, "position"); + + lua_pushstring(L, elem->name.c_str()); + lua_setfield(L, -2, "name"); + + push_v2f(L, elem->scale); + lua_setfield(L, -2, "scale"); + + lua_pushstring(L, elem->text.c_str()); + lua_setfield(L, -2, "text"); + + lua_pushnumber(L, elem->number); + lua_setfield(L, -2, "number"); + + lua_pushnumber(L, elem->item); + lua_setfield(L, -2, "item"); + + lua_pushnumber(L, elem->dir); + lua_setfield(L, -2, "direction"); + + push_v2f(L, elem->offset); + lua_setfield(L, -2, "offset"); + + push_v2f(L, elem->align); + lua_setfield(L, -2, "alignment"); + + push_v2s32(L, elem->size); + lua_setfield(L, -2, "size"); + + // Deprecated, only for compatibility's sake + lua_pushnumber(L, elem->dir); + lua_setfield(L, -2, "dir"); + + push_v3f(L, elem->world_pos); + lua_setfield(L, -2, "world_pos"); + + 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) +{ + HudElementStat stat = HUD_STAT_NUMBER; + if (lua_isstring(L, 3)) { + int statint; + std::string statstr = lua_tostring(L, 3); + stat = string_to_enum(es_HudElementStat, statint, statstr) ? + (HudElementStat)statint : stat; + } + + switch (stat) { + case HUD_STAT_POS: + elem->pos = read_v2f(L, 4); + *value = &elem->pos; + break; + case HUD_STAT_NAME: + elem->name = luaL_checkstring(L, 4); + *value = &elem->name; + break; + case HUD_STAT_SCALE: + elem->scale = read_v2f(L, 4); + *value = &elem->scale; + break; + case HUD_STAT_TEXT: + elem->text = luaL_checkstring(L, 4); + *value = &elem->text; + break; + case HUD_STAT_NUMBER: + elem->number = luaL_checknumber(L, 4); + *value = &elem->number; + break; + case HUD_STAT_ITEM: + elem->item = luaL_checknumber(L, 4); + *value = &elem->item; + break; + case HUD_STAT_DIR: + elem->dir = luaL_checknumber(L, 4); + *value = &elem->dir; + break; + case HUD_STAT_ALIGN: + elem->align = read_v2f(L, 4); + *value = &elem->align; + break; + case HUD_STAT_OFFSET: + elem->offset = read_v2f(L, 4); + *value = &elem->offset; + break; + case HUD_STAT_WORLD_POS: + elem->world_pos = read_v3f(L, 4); + *value = &elem->world_pos; + break; + case HUD_STAT_SIZE: + elem->size = read_v2s32(L, 4); + *value = &elem->size; + break; + case HUD_STAT_Z_INDEX: + 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"); + /**/ +} + +void push_physics_override(lua_State *L, float speed, float jump, float gravity, bool sneak, bool sneak_glitch, bool new_move) +{ + lua_createtable(L, 0, 6); + + lua_pushnumber(L, speed); + lua_setfield(L, -2, "speed"); + + lua_pushnumber(L, jump); + lua_setfield(L, -2, "jump"); + + lua_pushnumber(L, gravity); + lua_setfield(L, -2, "gravity"); + + lua_pushboolean(L, sneak); + lua_setfield(L, -2, "sneak"); + + lua_pushboolean(L, sneak_glitch); + lua_setfield(L, -2, "sneak_glitch"); + + lua_pushboolean(L, new_move); + lua_setfield(L, -2, "new_move"); +}