summaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-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
-rw-r--r--src/script/cpp_api/s_base.cpp15
-rw-r--r--src/script/cpp_api/s_base.h4
-rw-r--r--src/script/cpp_api/s_entity.cpp12
-rw-r--r--src/script/cpp_api/s_entity.h4
-rw-r--r--src/script/cpp_api/s_env.cpp2
-rw-r--r--src/script/cpp_api/s_node.cpp2
-rw-r--r--src/script/cpp_api/s_node.h2
-rw-r--r--src/script/cpp_api/s_player.cpp19
-rw-r--r--src/script/cpp_api/s_player.h5
-rw-r--r--src/script/cpp_api/s_security.cpp7
-rw-r--r--src/script/cpp_api/s_server.cpp14
-rw-r--r--src/script/cpp_api/s_server.h3
-rw-r--r--src/script/lua_api/l_base.cpp14
-rw-r--r--src/script/lua_api/l_base.h7
-rw-r--r--src/script/lua_api/l_camera.cpp59
-rw-r--r--src/script/lua_api/l_client.cpp46
-rw-r--r--src/script/lua_api/l_client.h6
-rw-r--r--src/script/lua_api/l_env.cpp140
-rw-r--r--src/script/lua_api/l_env.h3
-rw-r--r--src/script/lua_api/l_http.cpp51
-rw-r--r--src/script/lua_api/l_http.h7
-rw-r--r--src/script/lua_api/l_internal.h29
-rw-r--r--src/script/lua_api/l_inventory.cpp27
-rw-r--r--src/script/lua_api/l_item.cpp40
-rw-r--r--src/script/lua_api/l_item.h3
-rw-r--r--src/script/lua_api/l_localplayer.cpp74
-rw-r--r--src/script/lua_api/l_localplayer.h21
-rw-r--r--src/script/lua_api/l_mainmenu.cpp109
-rw-r--r--src/script/lua_api/l_mainmenu.h3
-rw-r--r--src/script/lua_api/l_mapgen.cpp82
-rw-r--r--src/script/lua_api/l_mapgen.h2
-rw-r--r--src/script/lua_api/l_metadata.cpp8
-rw-r--r--src/script/lua_api/l_nodemeta.cpp2
-rw-r--r--src/script/lua_api/l_nodetimer.cpp44
-rw-r--r--src/script/lua_api/l_nodetimer.h10
-rw-r--r--src/script/lua_api/l_noise.cpp14
-rw-r--r--src/script/lua_api/l_object.cpp78
-rw-r--r--src/script/lua_api/l_particles.cpp200
-rw-r--r--src/script/lua_api/l_particles_local.cpp159
-rw-r--r--src/script/lua_api/l_particles_local.h2
-rw-r--r--src/script/lua_api/l_server.cpp127
-rw-r--r--src/script/lua_api/l_server.h3
-rw-r--r--src/script/lua_api/l_util.cpp10
-rw-r--r--src/script/lua_api/l_util.h2
-rw-r--r--src/script/lua_api/l_vmanip.cpp6
-rw-r--r--src/script/scripting_client.cpp8
-rw-r--r--src/script/scripting_client.h3
-rw-r--r--src/script/scripting_mainmenu.cpp3
-rw-r--r--src/script/scripting_server.cpp4
55 files changed, 1136 insertions, 697 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)))
diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp
index ecb1ba39b..f965975a3 100644
--- a/src/script/cpp_api/s_base.cpp
+++ b/src/script/cpp_api/s_base.cpp
@@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_security.h"
#include "lua_api/l_object.h"
#include "common/c_converter.h"
-#include "serverobject.h"
+#include "server/player_sao.h"
#include "filesys.h"
#include "content/mods.h"
#include "porting.h"
@@ -43,7 +43,6 @@ extern "C" {
#include <cstdio>
#include <cstdarg>
#include "script/common/c_content.h"
-#include "content_sao.h"
#include <sstream>
@@ -90,7 +89,11 @@ ScriptApiBase::ScriptApiBase(ScriptingType type):
luaL_openlibs(m_luastack);
// Make the ScriptApiBase* accessible to ModApiBase
+#if INDIRECT_SCRIPTAPI_RIDX
+ *(void **)(lua_newuserdata(m_luastack, sizeof(void *))) = this;
+#else
lua_pushlightuserdata(m_luastack, this);
+#endif
lua_rawseti(m_luastack, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
// Add and save an error handler
@@ -184,7 +187,9 @@ void ScriptApiBase::loadScript(const std::string &script_path)
}
ok = ok && !lua_pcall(L, 0, 0, error_handler);
if (!ok) {
- std::string error_msg = readParam<std::string>(L, -1);
+ const char *error_msg = lua_tostring(L, -1);
+ if (!error_msg)
+ error_msg = "(error object is not a string)";
lua_pop(L, 2); // Pop error message and error handler
throw ModError("Failed to load and run script from " +
script_path + ":\n" + error_msg);
@@ -216,7 +221,9 @@ void ScriptApiBase::loadModFromMemory(const std::string &mod_name)
if (ok)
ok = !lua_pcall(L, 0, 0, error_handler);
if (!ok) {
- std::string error_msg = luaL_checkstring(L, -1);
+ const char *error_msg = lua_tostring(L, -1);
+ if (!error_msg)
+ error_msg = "(error object is not a string)";
lua_pop(L, 2); // Pop error message and error handler
throw ModError("Failed to load and run mod \"" +
mod_name + "\":\n" + error_msg);
diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h
index 697e5f556..86f7f7bac 100644
--- a/src/script/cpp_api/s_base.h
+++ b/src/script/cpp_api/s_base.h
@@ -136,8 +136,10 @@ protected:
Environment* getEnv() { return m_environment; }
void setEnv(Environment* env) { m_environment = env; }
+#ifndef SERVER
GUIEngine* getGuiEngine() { return m_guiengine; }
void setGuiEngine(GUIEngine* guiengine) { m_guiengine = guiengine; }
+#endif
void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj);
@@ -158,6 +160,8 @@ private:
IGameDef *m_gamedef = nullptr;
Environment *m_environment = nullptr;
+#ifndef SERVER
GUIEngine *m_guiengine = nullptr;
+#endif
ScriptingType m_type;
};
diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp
index 26c7e8cd4..ea9320051 100644
--- a/src/script/cpp_api/s_entity.cpp
+++ b/src/script/cpp_api/s_entity.cpp
@@ -178,12 +178,11 @@ void ScriptApiEntity::luaentity_GetProperties(u16 id,
lua_pop(L, 1);
}
-void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
+void ScriptApiEntity::luaentity_Step(u16 id, float dtime,
+ const collisionMoveResult *moveresult)
{
SCRIPTAPI_PRECHECKHEADER
- //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
-
int error_handler = PUSH_ERROR_HANDLER(L);
// Get core.luaentities[id]
@@ -199,9 +198,14 @@ void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self
lua_pushnumber(L, dtime); // dtime
+ /* moveresult */
+ if (moveresult)
+ push_collision_move_result(L, *moveresult);
+ else
+ lua_pushnil(L);
setOriginFromTable(object);
- PCALL_RES(lua_pcall(L, 2, 0, error_handler));
+ PCALL_RES(lua_pcall(L, 3, 0, error_handler));
lua_pop(L, 2); // Pop object and error handler
}
diff --git a/src/script/cpp_api/s_entity.h b/src/script/cpp_api/s_entity.h
index cc08c46e8..b5f7a6586 100644
--- a/src/script/cpp_api/s_entity.h
+++ b/src/script/cpp_api/s_entity.h
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
struct ObjectProperties;
struct ToolCapabilities;
+struct collisionMoveResult;
class ScriptApiEntity
: virtual public ScriptApiBase
@@ -36,7 +37,8 @@ public:
std::string luaentity_GetStaticdata(u16 id);
void luaentity_GetProperties(u16 id,
ServerActiveObject *self, ObjectProperties *prop);
- void luaentity_Step(u16 id, float dtime);
+ void luaentity_Step(u16 id, float dtime,
+ const collisionMoveResult *moveresult);
bool luaentity_Punch(u16 id,
ServerActiveObject *puncher, float time_from_last_punch,
const ToolCapabilities *toolcap, v3f dir, s16 damage);
diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp
index ab3b5fe46..8da5debaa 100644
--- a/src/script/cpp_api/s_env.cpp
+++ b/src/script/cpp_api/s_env.cpp
@@ -86,7 +86,7 @@ void ScriptApiEnv::player_event(ServerActiveObject *player, const std::string &t
void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env)
{
SCRIPTAPI_PRECHECKHEADER
- verbosestream << "scriptapi_add_environment" << std::endl;
+ verbosestream << "ScriptApiEnv: Environment initialized" << std::endl;
setEnv(env);
/*
diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp
index d93a4c3ad..e0f9bcd78 100644
--- a/src/script/cpp_api/s_node.cpp
+++ b/src/script/cpp_api/s_node.cpp
@@ -94,7 +94,7 @@ struct EnumString ScriptApiNode::es_NodeBoxType[] =
};
bool ScriptApiNode::node_on_punch(v3s16 p, MapNode node,
- ServerActiveObject *puncher, PointedThing pointed)
+ ServerActiveObject *puncher, const PointedThing &pointed)
{
SCRIPTAPI_PRECHECKHEADER
diff --git a/src/script/cpp_api/s_node.h b/src/script/cpp_api/s_node.h
index e7c0c01d1..81b44f0f0 100644
--- a/src/script/cpp_api/s_node.h
+++ b/src/script/cpp_api/s_node.h
@@ -36,7 +36,7 @@ public:
virtual ~ScriptApiNode() = default;
bool node_on_punch(v3s16 p, MapNode node,
- ServerActiveObject *puncher, PointedThing pointed);
+ ServerActiveObject *puncher, const PointedThing &pointed);
bool node_on_dig(v3s16 p, MapNode node,
ServerActiveObject *digger);
void node_on_construct(v3s16 p, MapNode node);
diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp
index df67ea00c..712120c61 100644
--- a/src/script/cpp_api/s_player.cpp
+++ b/src/script/cpp_api/s_player.cpp
@@ -147,7 +147,7 @@ bool ScriptApiPlayer::can_bypass_userlimit(const std::string &name, const std::s
return lua_toboolean(L, -1);
}
-void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player)
+void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player, s64 last_login)
{
SCRIPTAPI_PRECHECKHEADER
@@ -156,7 +156,11 @@ void ScriptApiPlayer::on_joinplayer(ServerActiveObject *player)
lua_getfield(L, -1, "registered_on_joinplayers");
// Call callbacks
objectrefGetOrCreate(L, player);
- runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+ if (last_login != -1)
+ lua_pushinteger(L, last_login);
+ else
+ lua_pushnil(L);
+ runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
}
void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player,
@@ -216,16 +220,19 @@ void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player,
runCallbacks(3, RUN_CALLBACKS_MODE_OR_SC);
}
-void ScriptApiPlayer::on_auth_failure(const std::string &name, const std::string &ip)
+void ScriptApiPlayer::on_authplayer(const std::string &name, const std::string &ip, bool is_success)
{
SCRIPTAPI_PRECHECKHEADER
- // Get core.registered_on_auth_failure
+ // Get core.registered_on_authplayers
lua_getglobal(L, "core");
- lua_getfield(L, -1, "registered_on_auth_fail");
+ lua_getfield(L, -1, "registered_on_authplayers");
+
+ // Call callbacks
lua_pushstring(L, name.c_str());
lua_pushstring(L, ip.c_str());
- runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
+ lua_pushboolean(L, is_success);
+ runCallbacks(3, RUN_CALLBACKS_MODE_FIRST);
}
void ScriptApiPlayer::pushMoveArguments(
diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h
index cf24ddc73..a337f975b 100644
--- a/src/script/cpp_api/s_player.h
+++ b/src/script/cpp_api/s_player.h
@@ -28,6 +28,7 @@ struct InventoryLocation;
struct ItemStack;
struct ToolCapabilities;
struct PlayerHPChangeReason;
+class ServerActiveObject;
class ScriptApiPlayer : virtual public ScriptApiBase
{
@@ -40,7 +41,7 @@ public:
bool on_prejoinplayer(const std::string &name, const std::string &ip,
std::string *reason);
bool can_bypass_userlimit(const std::string &name, const std::string &ip);
- void on_joinplayer(ServerActiveObject *player);
+ void on_joinplayer(ServerActiveObject *player, s64 last_login);
void on_leaveplayer(ServerActiveObject *player, bool timeout);
void on_cheat(ServerActiveObject *player, const std::string &cheat_type);
bool on_punchplayer(ServerActiveObject *player, ServerActiveObject *hitter,
@@ -50,7 +51,7 @@ public:
const PlayerHPChangeReason &reason);
void on_playerReceiveFields(ServerActiveObject *player,
const std::string &formname, const StringMap &fields);
- void on_auth_failure(const std::string &name, const std::string &ip);
+ void on_authplayer(const std::string &name, const std::string &ip, bool is_success);
// Player inventory callbacks
// Return number of accepted items to be moved
diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp
index b5abcfb5d..2afa3a191 100644
--- a/src/script/cpp_api/s_security.cpp
+++ b/src/script/cpp_api/s_security.cpp
@@ -499,7 +499,12 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
// Get server from registry
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
- ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1);
+ ScriptApiBase *script;
+#if INDIRECT_SCRIPTAPI_RIDX
+ script = (ScriptApiBase *) *(void**)(lua_touserdata(L, -1));
+#else
+ script = (ScriptApiBase *) lua_touserdata(L, -1);
+#endif
lua_pop(L, 1);
const IGameDef *gamedef = script->getGameDef();
if (!gamedef)
diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp
index 1ce2f9d45..96cb28b28 100644
--- a/src/script/cpp_api/s_server.cpp
+++ b/src/script/cpp_api/s_server.cpp
@@ -23,7 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
bool ScriptApiServer::getAuth(const std::string &playername,
std::string *dst_password,
- std::set<std::string> *dst_privs)
+ std::set<std::string> *dst_privs,
+ s64 *dst_last_login)
{
SCRIPTAPI_PRECHECKHEADER
@@ -43,8 +44,7 @@ bool ScriptApiServer::getAuth(const std::string &playername,
luaL_checktype(L, -1, LUA_TTABLE);
std::string password;
- bool found = getstringfield(L, -1, "password", password);
- if (!found)
+ if (!getstringfield(L, -1, "password", password))
throw LuaError("Authentication handler didn't return password");
if (dst_password)
*dst_password = password;
@@ -54,7 +54,13 @@ bool ScriptApiServer::getAuth(const std::string &playername,
throw LuaError("Authentication handler didn't return privilege table");
if (dst_privs)
readPrivileges(-1, *dst_privs);
- lua_pop(L, 1);
+ lua_pop(L, 1); // Remove key from privs table
+
+ s64 last_login;
+ if(!getintfield(L, -1, "last_login", last_login))
+ throw LuaError("Authentication handler didn't return last_login");
+ if (dst_last_login)
+ *dst_last_login = (s64)last_login;
return true;
}
diff --git a/src/script/cpp_api/s_server.h b/src/script/cpp_api/s_server.h
index a4cede84d..d8639cba7 100644
--- a/src/script/cpp_api/s_server.h
+++ b/src/script/cpp_api/s_server.h
@@ -43,7 +43,8 @@ public:
/* auth */
bool getAuth(const std::string &playername,
std::string *dst_password,
- std::set<std::string> *dst_privs);
+ std::set<std::string> *dst_privs,
+ s64 *dst_last_login = nullptr);
void createAuth(const std::string &playername,
const std::string &password);
bool setPassword(const std::string &playername,
diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp
index 8486fc7bc..2bee09436 100644
--- a/src/script/lua_api/l_base.cpp
+++ b/src/script/lua_api/l_base.cpp
@@ -30,7 +30,12 @@ ScriptApiBase *ModApiBase::getScriptApiBase(lua_State *L)
{
// Get server from registry
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
- ScriptApiBase *sapi_ptr = (ScriptApiBase*) lua_touserdata(L, -1);
+ ScriptApiBase *sapi_ptr;
+#if INDIRECT_SCRIPTAPI_RIDX
+ sapi_ptr = (ScriptApiBase*) *(void**)(lua_touserdata(L, -1));
+#else
+ sapi_ptr = (ScriptApiBase*) lua_touserdata(L, -1);
+#endif
lua_pop(L, 1);
return sapi_ptr;
}
@@ -40,6 +45,11 @@ Server *ModApiBase::getServer(lua_State *L)
return getScriptApiBase(L)->getServer();
}
+ServerInventoryManager *ModApiBase::getServerInventoryMgr(lua_State *L)
+{
+ return getScriptApiBase(L)->getServer()->getInventoryMgr();
+}
+
#ifndef SERVER
Client *ModApiBase::getClient(lua_State *L)
{
@@ -57,10 +67,12 @@ Environment *ModApiBase::getEnv(lua_State *L)
return getScriptApiBase(L)->getEnv();
}
+#ifndef SERVER
GUIEngine *ModApiBase::getGuiEngine(lua_State *L)
{
return getScriptApiBase(L)->getGuiEngine();
}
+#endif
std::string ModApiBase::getCurrentModPath(lua_State *L)
{
diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h
index b46b5b567..65fce8481 100644
--- a/src/script/lua_api/l_base.h
+++ b/src/script/lua_api/l_base.h
@@ -32,26 +32,29 @@ extern "C" {
#ifndef SERVER
class Client;
+class GUIEngine;
#endif
class ScriptApiBase;
class Server;
class Environment;
-class GUIEngine;
+class ServerInventoryManager;
class ModApiBase : protected LuaHelper {
public:
static ScriptApiBase* getScriptApiBase(lua_State *L);
static Server* getServer(lua_State *L);
+ static ServerInventoryManager *getServerInventoryMgr(lua_State *L);
#ifndef SERVER
static Client* getClient(lua_State *L);
+ static GUIEngine* getGuiEngine(lua_State *L);
#endif // !SERVER
static IGameDef* getGameDef(lua_State *L);
static Environment* getEnv(lua_State *L);
- static GUIEngine* getGuiEngine(lua_State *L);
+
// When we are not loading the mod, this function returns "."
static std::string getCurrentModPath(lua_State *L);
diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp
index 9c1470284..bfa60be67 100644
--- a/src/script/lua_api/l_camera.cpp
+++ b/src/script/lua_api/l_camera.cpp
@@ -51,6 +51,7 @@ void LuaCamera::create(lua_State *L, Camera *m)
lua_setfield(L, objectstable, "camera");
}
+// set_camera_mode(self, mode)
int LuaCamera::l_set_camera_mode(lua_State *L)
{
Camera *camera = getobject(L, 1);
@@ -67,17 +68,19 @@ int LuaCamera::l_set_camera_mode(lua_State *L)
return 0;
}
+// get_camera_mode(self)
int LuaCamera::l_get_camera_mode(lua_State *L)
{
Camera *camera = getobject(L, 1);
if (!camera)
return 0;
- lua_pushnumber(L, (int)camera->getCameraMode());
+ lua_pushinteger(L, (int)camera->getCameraMode());
return 1;
}
+// get_fov(self)
int LuaCamera::l_get_fov(lua_State *L)
{
Camera *camera = getobject(L, 1);
@@ -85,9 +88,9 @@ int LuaCamera::l_get_fov(lua_State *L)
return 0;
lua_newtable(L);
- lua_pushnumber(L, camera->getFovX() * core::DEGTORAD);
+ lua_pushnumber(L, camera->getFovX() * core::RADTODEG);
lua_setfield(L, -2, "x");
- lua_pushnumber(L, camera->getFovY() * core::DEGTORAD);
+ lua_pushnumber(L, camera->getFovY() * core::RADTODEG);
lua_setfield(L, -2, "y");
lua_pushnumber(L, camera->getCameraNode()->getFOV() * core::RADTODEG);
lua_setfield(L, -2, "actual");
@@ -96,16 +99,18 @@ int LuaCamera::l_get_fov(lua_State *L)
return 1;
}
+// get_pos(self)
int LuaCamera::l_get_pos(lua_State *L)
{
Camera *camera = getobject(L, 1);
if (!camera)
return 0;
- push_v3f(L, camera->getPosition());
+ push_v3f(L, camera->getPosition() / BS);
return 1;
}
+// get_offset(self)
int LuaCamera::l_get_offset(lua_State *L)
{
LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer();
@@ -115,38 +120,40 @@ int LuaCamera::l_get_offset(lua_State *L)
return 1;
}
+// get_look_dir(self)
int LuaCamera::l_get_look_dir(lua_State *L)
{
- LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer();
- sanity_check(player);
-
- float pitch = -1.0 * player->getPitch() * core::DEGTORAD;
- float yaw = (player->getYaw() + 90.) * core::DEGTORAD;
- v3f v(std::cos(pitch) * std::cos(yaw), std::sin(pitch),
- std::cos(pitch) * std::sin(yaw));
+ Camera *camera = getobject(L, 1);
+ if (!camera)
+ return 0;
- push_v3f(L, v);
+ push_v3f(L, camera->getDirection());
return 1;
}
+// get_look_horizontal(self)
+// FIXME: wouldn't localplayer be a better place for this?
int LuaCamera::l_get_look_horizontal(lua_State *L)
{
LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer();
sanity_check(player);
- lua_pushnumber(L, (player->getYaw() + 90.) * core::DEGTORAD);
+ lua_pushnumber(L, (player->getYaw() + 90.f) * core::DEGTORAD);
return 1;
}
+// get_look_vertical(self)
+// FIXME: wouldn't localplayer be a better place for this?
int LuaCamera::l_get_look_vertical(lua_State *L)
{
LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer();
sanity_check(player);
- lua_pushnumber(L, -1.0 * player->getPitch() * core::DEGTORAD);
+ lua_pushnumber(L, -1.0f * player->getPitch() * core::DEGTORAD);
return 1;
}
+// get_aspect_ratio(self)
int LuaCamera::l_get_aspect_ratio(lua_State *L)
{
Camera *camera = getobject(L, 1);
@@ -215,13 +222,19 @@ void LuaCamera::Register(lua_State *L)
lua_pop(L, 1);
}
+// clang-format off
const char LuaCamera::className[] = "Camera";
-const luaL_Reg LuaCamera::methods[] = {luamethod(LuaCamera, set_camera_mode),
- luamethod(LuaCamera, get_camera_mode), luamethod(LuaCamera, get_fov),
- luamethod(LuaCamera, get_pos), luamethod(LuaCamera, get_offset),
- luamethod(LuaCamera, get_look_dir),
- luamethod(LuaCamera, get_look_vertical),
- luamethod(LuaCamera, get_look_horizontal),
- luamethod(LuaCamera, get_aspect_ratio),
-
- {0, 0}};
+const luaL_Reg LuaCamera::methods[] = {
+ luamethod(LuaCamera, set_camera_mode),
+ luamethod(LuaCamera, get_camera_mode),
+ luamethod(LuaCamera, get_fov),
+ luamethod(LuaCamera, get_pos),
+ luamethod(LuaCamera, get_offset),
+ luamethod(LuaCamera, get_look_dir),
+ luamethod(LuaCamera, get_look_vertical),
+ luamethod(LuaCamera, get_look_horizontal),
+ luamethod(LuaCamera, get_aspect_ratio),
+
+ {0, 0}
+};
+// clang-format on
diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp
index fba182492..aaced7cd0 100644
--- a/src/script/lua_api/l_client.cpp
+++ b/src/script/lua_api/l_client.cpp
@@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_base.h"
#include "gettext.h"
#include "l_internal.h"
-#include "lua_api/l_item.h"
#include "lua_api/l_nodemeta.h"
#include "gui/mainmenumanager.h"
#include "map.h"
@@ -209,7 +208,7 @@ int ModApiClient::l_gettext(lua_State *L)
return 1;
}
-// get_node(pos)
+// get_node_or_nil(pos)
// pos = {x=num, y=num, z=num}
int ModApiClient::l_get_node_or_nil(lua_State *L)
{
@@ -228,6 +227,7 @@ int ModApiClient::l_get_node_or_nil(lua_State *L)
return 1;
}
+// get_langauge()
int ModApiClient::l_get_language(lua_State *L)
{
#ifdef _WIN32
@@ -244,34 +244,30 @@ int ModApiClient::l_get_language(lua_State *L)
return 2;
}
-int ModApiClient::l_get_wielded_item(lua_State *L)
-{
- Client *client = getClient(L);
- LocalPlayer *player = client->getEnv().getLocalPlayer();
- if (!player)
- return 0;
-
- ItemStack selected_item;
- player->getWieldedItem(&selected_item, nullptr);
- LuaItemStack::create(L, selected_item);
- return 1;
-}
-
// get_meta(pos)
int ModApiClient::l_get_meta(lua_State *L)
{
v3s16 p = read_v3s16(L, 1);
- NodeMetadata *meta = getClient(L)->getEnv().getMap().getNodeMetadata(p);
+
+ // check restrictions first
+ bool pos_ok;
+ getClient(L)->CSMGetNode(p, &pos_ok);
+ if (!pos_ok)
+ return 0;
+
+ NodeMetadata *meta = getEnv(L)->getMap().getNodeMetadata(p);
NodeMetaRef::createClient(L, meta);
return 1;
}
+// sound_play(spec, parameters)
int ModApiClient::l_sound_play(lua_State *L)
{
ISoundManager *sound = getClient(L)->getSoundManager();
SimpleSoundSpec spec;
read_soundspec(L, 1, spec);
+
float gain = 1.0f;
float pitch = 1.0f;
bool looped = false;
@@ -293,21 +289,32 @@ int ModApiClient::l_sound_play(lua_State *L)
}
}
- handle = sound->playSound(spec.name, looped, gain * spec.gain, 0.0f, pitch);
+ handle = sound->playSound(spec.name, looped, gain * spec.gain, spec.fade, pitch);
lua_pushinteger(L, handle);
return 1;
}
+// sound_stop(handle)
int ModApiClient::l_sound_stop(lua_State *L)
{
- u32 handle = luaL_checkinteger(L, 1);
+ s32 handle = luaL_checkinteger(L, 1);
getClient(L)->getSoundManager()->stopSound(handle);
return 0;
}
+// sound_fade(handle, step, gain)
+int ModApiClient::l_sound_fade(lua_State *L)
+{
+ s32 handle = luaL_checkinteger(L, 1);
+ float step = readParam<float>(L, 2);
+ float gain = readParam<float>(L, 3);
+ getClient(L)->getSoundManager()->fadeSound(handle, step, gain);
+ return 0;
+}
+
// get_server_info()
int ModApiClient::l_get_server_info(lua_State *L)
{
@@ -375,6 +382,7 @@ int ModApiClient::l_get_node_def(lua_State *L)
return 1;
}
+// get_privilege_list()
int ModApiClient::l_get_privilege_list(lua_State *L)
{
const Client *client = getClient(L);
@@ -421,11 +429,11 @@ void ModApiClient::Initialize(lua_State *L, int top)
API_FCT(send_respawn);
API_FCT(gettext);
API_FCT(get_node_or_nil);
- API_FCT(get_wielded_item);
API_FCT(disconnect);
API_FCT(get_meta);
API_FCT(sound_play);
API_FCT(sound_stop);
+ API_FCT(sound_fade);
API_FCT(get_server_info);
API_FCT(get_item_def);
API_FCT(get_node_def);
diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h
index 6d1f70b1d..5dc3efdad 100644
--- a/src/script/lua_api/l_client.h
+++ b/src/script/lua_api/l_client.h
@@ -69,6 +69,7 @@ private:
// get_node(pos)
static int l_get_node_or_nil(lua_State *L);
+ // get_language()
static int l_get_language(lua_State *L);
// get_wielded_item()
@@ -77,10 +78,15 @@ private:
// get_meta(pos)
static int l_get_meta(lua_State *L);
+ // sound_play(spec, parameters)
static int l_sound_play(lua_State *L);
+ // sound_stop(handle)
static int l_sound_stop(lua_State *L);
+ // sound_fade(handle, step, gain)
+ static int l_sound_fade(lua_State *L);
+
// get_server_info()
static int l_get_server_info(lua_State *L);
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index 3169fa4cf..89ec9dc7e 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <algorithm>
#include "lua_api/l_env.h"
#include "lua_api/l_internal.h"
#include "lua_api/l_nodemeta.h"
@@ -25,7 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_vmanip.h"
#include "common/c_converter.h"
#include "common/c_content.h"
-#include <algorithm>
#include "scripting_server.h"
#include "environment.h"
#include "mapblock.h"
@@ -33,12 +33,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodedef.h"
#include "daynightratio.h"
#include "util/pointedthing.h"
-#include "content_sao.h"
#include "mapgen/treegen.h"
#include "emerge.h"
#include "pathfinder.h"
#include "face_position_cache.h"
#include "remoteplayer.h"
+#include "server/luaentity_sao.h"
+#include "server/player_sao.h"
+#include "util/string.h"
+#include "translation.h"
#ifndef SERVER
#include "client/client.h"
#endif
@@ -72,7 +75,7 @@ void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
lua_remove(L, -2); // Remove core
// Get registered_abms[m_id]
- lua_pushnumber(L, m_id);
+ lua_pushinteger(L, m_id);
lua_gettable(L, -2);
if(lua_isnil(L, -1))
FATAL_ERROR("");
@@ -115,7 +118,7 @@ void LuaLBM::trigger(ServerEnvironment *env, v3s16 p, MapNode n)
lua_remove(L, -2); // Remove core
// Get registered_lbms[m_id]
- lua_pushnumber(L, m_id);
+ lua_pushinteger(L, m_id);
lua_gettable(L, -2);
FATAL_ERROR_IF(lua_isnil(L, -1), "Entry with given id not found in registered_lbms table");
lua_remove(L, -2); // Remove registered_lbms
@@ -139,8 +142,7 @@ void LuaLBM::trigger(ServerEnvironment *env, v3s16 p, MapNode n)
int LuaRaycast::l_next(lua_State *L)
{
- MAP_LOCK_REQUIRED;
- GET_ENV_PTR;
+ GET_PLAIN_ENV_PTR;
bool csm = false;
#ifndef SERVER
@@ -384,7 +386,7 @@ int ModApiEnvMod::l_get_node_or_nil(lua_State *L)
// timeofday: nil = current time, 0 = night, 0.5 = day
int ModApiEnvMod::l_get_node_light(lua_State *L)
{
- GET_ENV_PTR;
+ GET_PLAIN_ENV_PTR;
// Do it
v3s16 pos = read_v3s16(L, 1);
@@ -488,10 +490,7 @@ int ModApiEnvMod::l_punch_node(lua_State *L)
// pos = {x=num, y=num, z=num}
int ModApiEnvMod::l_get_node_max_level(lua_State *L)
{
- Environment *env = getEnv(L);
- if (!env) {
- return 0;
- }
+ GET_PLAIN_ENV_PTR;
v3s16 pos = read_v3s16(L, 1);
MapNode n = env->getMap().getNode(pos);
@@ -503,10 +502,7 @@ int ModApiEnvMod::l_get_node_max_level(lua_State *L)
// pos = {x=num, y=num, z=num}
int ModApiEnvMod::l_get_node_level(lua_State *L)
{
- Environment *env = getEnv(L);
- if (!env) {
- return 0;
- }
+ GET_PLAIN_ENV_PTR;
v3s16 pos = read_v3s16(L, 1);
MapNode n = env->getMap().getNode(pos);
@@ -533,13 +529,13 @@ int ModApiEnvMod::l_set_node_level(lua_State *L)
// add_node_level(pos, level)
// pos = {x=num, y=num, z=num}
-// level: 0..63
+// level: -127..127
int ModApiEnvMod::l_add_node_level(lua_State *L)
{
GET_ENV_PTR;
v3s16 pos = read_v3s16(L, 1);
- u8 level = 1;
+ s16 level = 1;
if(lua_isnumber(L, 2))
level = lua_tonumber(L, 2);
MapNode n = env->getMap().getNode(pos);
@@ -551,12 +547,12 @@ int ModApiEnvMod::l_add_node_level(lua_State *L)
// find_nodes_with_meta(pos1, pos2)
int ModApiEnvMod::l_find_nodes_with_meta(lua_State *L)
{
- GET_ENV_PTR;
+ GET_PLAIN_ENV_PTR;
std::vector<v3s16> positions = env->getMap().findNodesWithMetadata(
check_v3s16(L, 1), check_v3s16(L, 2));
- lua_newtable(L);
+ lua_createtable(L, positions.size(), 0);
for (size_t i = 0; i != positions.size(); i++) {
push_v3s16(L, positions[i]);
lua_rawseti(L, -2, i + 1);
@@ -583,7 +579,7 @@ int ModApiEnvMod::l_get_node_timer(lua_State *L)
// Do it
v3s16 p = read_v3s16(L, 1);
- NodeTimerRef::create(L, p, env);
+ NodeTimerRef::create(L, p, &env->getServerMap());
return 1;
}
@@ -593,19 +589,19 @@ int ModApiEnvMod::l_add_entity(lua_State *L)
{
GET_ENV_PTR;
- // pos
v3f pos = checkFloatPos(L, 1);
- // content
const char *name = luaL_checkstring(L, 2);
- // staticdata
const char *staticdata = luaL_optstring(L, 3, "");
- // Do it
+
ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, staticdata);
int objectid = env->addActiveObject(obj);
// If failed to add, return nothing (reads as nil)
if(objectid == 0)
return 0;
- // Return ObjectRef
+
+ // If already deleted (can happen in on_activate), return nil
+ if (obj->isGone())
+ return 0;
getScriptApiBase(L)->objectrefGetOrCreate(L, obj);
return 1;
}
@@ -687,22 +683,22 @@ int ModApiEnvMod::l_get_player_by_name(lua_State *L)
int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
{
GET_ENV_PTR;
+ ScriptApiBase *script = getScriptApiBase(L);
// Do it
v3f pos = checkFloatPos(L, 1);
float radius = readParam<float>(L, 2) * BS;
- std::vector<u16> ids;
- env->getObjectsInsideRadius(ids, pos, radius);
- ScriptApiBase *script = getScriptApiBase(L);
- lua_createtable(L, ids.size(), 0);
- std::vector<u16>::const_iterator iter = ids.begin();
- for(u32 i = 0; iter != ids.end(); ++iter) {
- ServerActiveObject *obj = env->getActiveObject(*iter);
- if (!obj->isGone()) {
- // Insert object reference into table
- script->objectrefGetOrCreate(L, obj);
- lua_rawseti(L, -2, ++i);
- }
+ std::vector<ServerActiveObject *> objs;
+
+ auto include_obj_cb = [](ServerActiveObject *obj){ return !obj->isGone(); };
+ env->getObjectsInsideRadius(objs, pos, radius, include_obj_cb);
+
+ int i = 0;
+ lua_createtable(L, objs.size(), 0);
+ for (const auto obj : objs) {
+ // Insert object reference into table
+ script->objectrefGetOrCreate(L, obj);
+ lua_rawseti(L, -2, ++i);
}
return 1;
}
@@ -728,10 +724,7 @@ int ModApiEnvMod::l_set_timeofday(lua_State *L)
// get_timeofday() -> 0...1
int ModApiEnvMod::l_get_timeofday(lua_State *L)
{
- Environment *env = getEnv(L);
- if (!env) {
- return 0;
- }
+ GET_PLAIN_ENV_PTR;
// Do it
int timeofday_mh = env->getTimeOfDay();
@@ -743,10 +736,7 @@ int ModApiEnvMod::l_get_timeofday(lua_State *L)
// get_day_count() -> int
int ModApiEnvMod::l_get_day_count(lua_State *L)
{
- Environment *env = getEnv(L);
- if (!env) {
- return 0;
- }
+ GET_PLAIN_ENV_PTR;
lua_pushnumber(L, env->getDayCount());
return 1;
@@ -767,12 +757,9 @@ int ModApiEnvMod::l_get_gametime(lua_State *L)
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
int ModApiEnvMod::l_find_node_near(lua_State *L)
{
- Environment *env = getEnv(L);
- if (!env) {
- return 0;
- }
+ GET_PLAIN_ENV_PTR;
- const NodeDefManager *ndef = getGameDef(L)->ndef();
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
v3s16 pos = read_v3s16(L, 1);
int radius = luaL_checkinteger(L, 2);
std::vector<content_t> filter;
@@ -793,8 +780,8 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
#ifndef SERVER
// Client API limitations
- if (getClient(L))
- radius = getClient(L)->CSMClampRadius(pos, radius);
+ if (Client *client = getClient(L))
+ radius = client->CSMClampRadius(pos, radius);
#endif
for (int d = start_radius; d <= radius; d++) {
@@ -815,20 +802,19 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
{
- GET_ENV_PTR;
+ GET_PLAIN_ENV_PTR;
v3s16 minp = read_v3s16(L, 1);
v3s16 maxp = read_v3s16(L, 2);
sortBoxVerticies(minp, maxp);
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
+
#ifndef SERVER
- const NodeDefManager *ndef = getClient(L) ? getClient(L)->ndef() : getServer(L)->ndef();
- if (getClient(L)) {
- minp = getClient(L)->CSMClampPos(minp);
- maxp = getClient(L)->CSMClampPos(maxp);
+ if (Client *client = getClient(L)) {
+ minp = client->CSMClampPos(minp);
+ maxp = client->CSMClampPos(maxp);
}
-#else
- const NodeDefManager *ndef = getServer(L)->ndef();
#endif
v3s16 cube = maxp - minp + 1;
@@ -892,20 +878,19 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
* TODO
*/
- GET_ENV_PTR;
+ GET_PLAIN_ENV_PTR;
v3s16 minp = read_v3s16(L, 1);
v3s16 maxp = read_v3s16(L, 2);
sortBoxVerticies(minp, maxp);
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
+
#ifndef SERVER
- const NodeDefManager *ndef = getClient(L) ? getClient(L)->ndef() : getServer(L)->ndef();
- if (getClient(L)) {
- minp = getClient(L)->CSMClampPos(minp);
- maxp = getClient(L)->CSMClampPos(maxp);
+ if (Client *client = getClient(L)) {
+ minp = client->CSMClampPos(minp);
+ maxp = client->CSMClampPos(maxp);
}
-#else
- const NodeDefManager *ndef = getServer(L)->ndef();
#endif
v3s16 cube = maxp - minp + 1;
@@ -1034,7 +1019,7 @@ int ModApiEnvMod::l_clear_objects(lua_State *L)
// line_of_sight(pos1, pos2) -> true/false, pos
int ModApiEnvMod::l_line_of_sight(lua_State *L)
{
- GET_ENV_PTR;
+ GET_PLAIN_ENV_PTR;
// read position 1 from lua
v3f pos1 = checkFloatPos(L, 1);
@@ -1210,11 +1195,11 @@ int ModApiEnvMod::l_find_path(lua_State *L)
algo = PA_DIJKSTRA;
}
- std::vector<v3s16> path = get_path(env, pos1, pos2,
+ std::vector<v3s16> path = get_path(&env->getServerMap(), env->getGameDef()->ndef(), pos1, pos2,
searchdistance, max_jump, max_drop, algo);
if (!path.empty()) {
- lua_newtable(L);
+ lua_createtable(L, path.size(), 0);
int top = lua_gettop(L);
unsigned int index = 1;
for (const v3s16 &i : path) {
@@ -1274,8 +1259,9 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
else
return 0;
+ ServerMap *map = &env->getServerMap();
treegen::error e;
- if ((e = treegen::spawn_ltree (env, p0, ndef, tree_def)) != treegen::SUCCESS) {
+ if ((e = treegen::spawn_ltree (map, p0, ndef, tree_def)) != treegen::SUCCESS) {
if (e == treegen::UNBALANCED_BRACKETS) {
luaL_error(L, "spawn_tree(): closing ']' has no matching opening bracket");
} else {
@@ -1318,6 +1304,19 @@ int ModApiEnvMod::l_forceload_free_block(lua_State *L)
return 0;
}
+// get_translated_string(lang_code, string)
+int ModApiEnvMod::l_get_translated_string(lua_State * L)
+{
+ GET_ENV_PTR;
+ std::string lang_code = luaL_checkstring(L, 1);
+ std::string string = luaL_checkstring(L, 2);
+ getServer(L)->loadTranslationLanguage(lang_code);
+ string = wide_to_utf8(translate_string(utf8_to_wide(string),
+ &(*g_server_translations)[lang_code]));
+ lua_pushstring(L, string.c_str());
+ return 1;
+}
+
void ModApiEnvMod::Initialize(lua_State *L, int top)
{
API_FCT(set_node);
@@ -1365,6 +1364,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
API_FCT(transforming_liquid_add);
API_FCT(forceload_block);
API_FCT(forceload_free_block);
+ API_FCT(get_translated_string);
}
void ModApiEnvMod::InitializeClient(lua_State *L, int top)
diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h
index ac2f8b588..9050b4306 100644
--- a/src/script/lua_api/l_env.h
+++ b/src/script/lua_api/l_env.h
@@ -187,6 +187,9 @@ private:
// stops forceloading a position
static int l_forceload_free_block(lua_State *L);
+ // Get a string translated server side
+ static int l_get_translated_string(lua_State * L);
+
public:
static void Initialize(lua_State *L, int top);
static void InitializeClient(lua_State *L, int top);
diff --git a/src/script/lua_api/l_http.cpp b/src/script/lua_api/l_http.cpp
index 2ff651cb5..ec43bf174 100644
--- a/src/script/lua_api/l_http.cpp
+++ b/src/script/lua_api/l_http.cpp
@@ -83,6 +83,24 @@ void ModApiHttp::push_http_fetch_result(lua_State *L, HTTPFetchResult &res, bool
setstringfield(L, -1, "data", res.data);
}
+// http_api.fetch_sync(HTTPRequest definition)
+int ModApiHttp::l_http_fetch_sync(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ HTTPFetchRequest req;
+ read_http_fetch_request(L, req);
+
+ infostream << "Mod performs HTTP request with URL " << req.url << std::endl;
+
+ HTTPFetchResult res;
+ httpfetch_sync(req, res);
+
+ push_http_fetch_result(L, res, true);
+
+ return 1;
+}
+
// http_api.fetch_async(HTTPRequest definition)
int ModApiHttp::l_http_fetch_async(lua_State *L)
{
@@ -180,11 +198,42 @@ int ModApiHttp::l_request_http_api(lua_State *L)
return 1;
}
+
+int ModApiHttp::l_get_http_api(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ lua_newtable(L);
+ HTTP_API(fetch_async);
+ HTTP_API(fetch_async_get);
+ HTTP_API(fetch_sync);
+
+ return 1;
+}
+
#endif
void ModApiHttp::Initialize(lua_State *L, int top)
{
#if USE_CURL
- API_FCT(request_http_api);
+
+ bool isMainmenu = false;
+#ifndef SERVER
+ isMainmenu = ModApiBase::getGuiEngine(L) != nullptr;
+#endif
+
+ if (isMainmenu) {
+ API_FCT(get_http_api);
+ } else {
+ API_FCT(request_http_api);
+ }
+
+#endif
+}
+
+void ModApiHttp::InitializeAsync(lua_State *L, int top)
+{
+#if USE_CURL
+ API_FCT(get_http_api);
#endif
}
diff --git a/src/script/lua_api/l_http.h b/src/script/lua_api/l_http.h
index 3d9cdad29..de6e51b37 100644
--- a/src/script/lua_api/l_http.h
+++ b/src/script/lua_api/l_http.h
@@ -32,6 +32,9 @@ private:
static void read_http_fetch_request(lua_State *L, HTTPFetchRequest &req);
static void push_http_fetch_result(lua_State *L, HTTPFetchResult &res, bool completed = true);
+ // http_fetch_sync({url=, timeout=, post_data=})
+ static int l_http_fetch_sync(lua_State *L);
+
// http_fetch_async({url=, timeout=, post_data=})
static int l_http_fetch_async(lua_State *L);
@@ -40,8 +43,12 @@ private:
// request_http_api()
static int l_request_http_api(lua_State *L);
+
+ // get_http_api()
+ static int l_get_http_api(lua_State *L);
#endif
public:
static void Initialize(lua_State *L, int top);
+ static void InitializeAsync(lua_State *L, int top);
};
diff --git a/src/script/lua_api/l_internal.h b/src/script/lua_api/l_internal.h
index bbedfe46e..a86eeaf79 100644
--- a/src/script/lua_api/l_internal.h
+++ b/src/script/lua_api/l_internal.h
@@ -32,14 +32,39 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define luamethod_aliased(class, name, alias) {#name, class::l_##name}, {#alias, class::l_##name}
#define API_FCT(name) registerFunction(L, #name, l_##name, top)
-#define MAP_LOCK_REQUIRED
-#define NO_MAP_LOCK_REQUIRED
+// For future use
+#define MAP_LOCK_REQUIRED ((void)0)
+#define NO_MAP_LOCK_REQUIRED ((void)0)
+/* In debug mode ensure no code tries to retrieve the server env when it isn't
+ * actually available (in CSM) */
+#if !defined(SERVER) && !defined(NDEBUG)
+#define DEBUG_ASSERT_NO_CLIENTAPI \
+ FATAL_ERROR_IF(getClient(L) != nullptr, "Tried " \
+ "to retrieve ServerEnvironment on client")
+#else
+#define DEBUG_ASSERT_NO_CLIENTAPI ((void)0)
+#endif
+
+// Retrieve ServerEnvironment pointer as `env` (no map lock)
#define GET_ENV_PTR_NO_MAP_LOCK \
+ DEBUG_ASSERT_NO_CLIENTAPI; \
ServerEnvironment *env = (ServerEnvironment *)getEnv(L); \
if (env == NULL) \
return 0
+// Retrieve ServerEnvironment pointer as `env`
#define GET_ENV_PTR \
MAP_LOCK_REQUIRED; \
GET_ENV_PTR_NO_MAP_LOCK
+
+// Retrieve Environment pointer as `env` (no map lock)
+#define GET_PLAIN_ENV_PTR_NO_MAP_LOCK \
+ Environment *env = (Environment *)getEnv(L); \
+ if (env == NULL) \
+ return 0
+
+// Retrieve Environment pointer as `env`
+#define GET_PLAIN_ENV_PTR \
+ MAP_LOCK_REQUIRED; \
+ GET_PLAIN_ENV_PTR_NO_MAP_LOCK
diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp
index 6e7afa4a4..e41b5cb41 100644
--- a/src/script/lua_api/l_inventory.cpp
+++ b/src/script/lua_api/l_inventory.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_converter.h"
#include "common/c_content.h"
#include "server.h"
+#include "server/serverinventorymgr.h"
#include "remoteplayer.h"
/*
@@ -38,7 +39,7 @@ InvRef* InvRef::checkobject(lua_State *L, int narg)
Inventory* InvRef::getinv(lua_State *L, InvRef *ref)
{
- return getServer(L)->getInventory(ref->m_loc);
+ return getServerInventoryMgr(L)->getInventory(ref->m_loc);
}
InventoryList* InvRef::getlist(lua_State *L, InvRef *ref,
@@ -54,7 +55,7 @@ InventoryList* InvRef::getlist(lua_State *L, InvRef *ref,
void InvRef::reportInventoryChange(lua_State *L, InvRef *ref)
{
// Inform other things that the inventory has changed
- getServer(L)->setInventoryModified(ref->m_loc);
+ getServerInventoryMgr(L)->setInventoryModified(ref->m_loc);
}
// Exported functions
@@ -487,7 +488,9 @@ int ModApiInventory::l_get_inventory(lua_State *L)
{
InventoryLocation loc;
- std::string type = checkstringfield(L, 1, "type");
+ lua_getfield(L, 1, "type");
+ std::string type = luaL_checkstring(L, -1);
+ lua_pop(L, 1);
if(type == "node"){
MAP_LOCK_REQUIRED;
@@ -495,7 +498,7 @@ int ModApiInventory::l_get_inventory(lua_State *L)
v3s16 pos = check_v3s16(L, -1);
loc.setNodeMeta(pos);
- if (getServer(L)->getInventory(loc) != NULL)
+ if (getServerInventoryMgr(L)->getInventory(loc) != NULL)
InvRef::create(L, loc);
else
lua_pushnil(L);
@@ -504,14 +507,16 @@ int ModApiInventory::l_get_inventory(lua_State *L)
NO_MAP_LOCK_REQUIRED;
if (type == "player") {
- std::string name = checkstringfield(L, 1, "name");
- loc.setPlayer(name);
+ lua_getfield(L, 1, "name");
+ loc.setPlayer(luaL_checkstring(L, -1));
+ lua_pop(L, 1);
} else if (type == "detached") {
- std::string name = checkstringfield(L, 1, "name");
- loc.setDetached(name);
+ lua_getfield(L, 1, "name");
+ loc.setDetached(luaL_checkstring(L, -1));
+ lua_pop(L, 1);
}
- if (getServer(L)->getInventory(loc) != NULL)
+ if (getServerInventoryMgr(L)->getInventory(loc) != NULL)
InvRef::create(L, loc);
else
lua_pushnil(L);
@@ -526,7 +531,7 @@ int ModApiInventory::l_create_detached_inventory_raw(lua_State *L)
NO_MAP_LOCK_REQUIRED;
const char *name = luaL_checkstring(L, 1);
std::string player = readParam<std::string>(L, 2, "");
- if (getServer(L)->createDetachedInventory(name, player) != NULL) {
+ if (getServerInventoryMgr(L)->createDetachedInventory(name, getServer(L)->idef(), player) != NULL) {
InventoryLocation loc;
loc.setDetached(name);
InvRef::create(L, loc);
@@ -541,7 +546,7 @@ int ModApiInventory::l_remove_detached_inventory_raw(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const std::string &name = luaL_checkstring(L, 1);
- lua_pushboolean(L, getServer(L)->removeDetachedInventory(name));
+ lua_pushboolean(L, getServerInventoryMgr(L)->removeDetachedInventory(name));
return 1;
}
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index 0c174feca..d67cab76f 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "itemdef.h"
#include "nodedef.h"
#include "server.h"
-#include "content_sao.h"
#include "inventory.h"
#include "log.h"
@@ -38,6 +37,15 @@ int LuaItemStack::gc_object(lua_State *L)
return 0;
}
+// __tostring metamethod
+int LuaItemStack::mt_tostring(lua_State *L)
+{
+ LuaItemStack *o = checkobject(L, 1);
+ std::string itemstring = o->m_stack.getItemString(false);
+ lua_pushfstring(L, "ItemStack(\"%s\")", itemstring.c_str());
+ return 1;
+}
+
// is_empty(self) -> true/false
int LuaItemStack::l_is_empty(lua_State *L)
{
@@ -434,12 +442,9 @@ int LuaItemStack::create(lua_State *L, const ItemStack &item)
return 1;
}
-LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg)
+LuaItemStack *LuaItemStack::checkobject(lua_State *L, int narg)
{
- luaL_checktype(L, narg, LUA_TUSERDATA);
- void *ud = luaL_checkudata(L, narg, className);
- if(!ud) luaL_typerror(L, narg, className);
- return *(LuaItemStack**)ud; // unbox pointer
+ return *(LuaItemStack **)luaL_checkudata(L, narg, className);
}
void LuaItemStack::Register(lua_State *L)
@@ -449,9 +454,10 @@ void LuaItemStack::Register(lua_State *L)
luaL_newmetatable(L, className);
int metatable = lua_gettop(L);
+ // hide metatable from Lua getmetatable()
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable);
- lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+ lua_settable(L, metatable);
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
@@ -461,12 +467,16 @@ void LuaItemStack::Register(lua_State *L)
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, mt_tostring);
+ lua_settable(L, metatable);
+
lua_pop(L, 1); // drop metatable
luaL_openlib(L, 0, methods, 0); // fill methodtable
lua_pop(L, 1); // drop methodtable
- // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil))
+ // Can be created from Lua (ItemStack(itemstack or itemstring or table or nil))
lua_register(L, className, create_object);
}
@@ -522,7 +532,6 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
lua_getfield(L, table, "name");
if(lua_isstring(L, -1)){
name = readParam<std::string>(L, -1);
- verbosestream<<"register_item_raw: "<<name<<std::endl;
} else {
throw LuaError("register_item_raw: name is not defined or not a string");
}
@@ -611,10 +620,21 @@ int ModApiItemMod::l_get_content_id(lua_State *L)
NO_MAP_LOCK_REQUIRED;
std::string name = luaL_checkstring(L, 1);
+ const IItemDefManager *idef = getGameDef(L)->getItemDefManager();
const NodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
+
+ // If this is called at mod load time, NodeDefManager isn't aware of
+ // aliases yet, so we need to handle them manually
+ std::string alias_name = idef->getAlias(name);
+
content_t content_id;
- if (!ndef->getId(name, content_id))
+ if (alias_name != name) {
+ if (!ndef->getId(alias_name, content_id))
+ throw LuaError("Unknown node: " + alias_name +
+ " (from alias " + name + ")");
+ } else if (!ndef->getId(name, content_id)) {
throw LuaError("Unknown node: " + name);
+ }
lua_pushinteger(L, content_id);
return 1; /* number of results */
diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h
index 6fab58045..98744c071 100644
--- a/src/script/lua_api/l_item.h
+++ b/src/script/lua_api/l_item.h
@@ -34,6 +34,9 @@ private:
// garbage collector
static int gc_object(lua_State *L);
+ // __tostring metamethod
+ static int mt_tostring(lua_State *L);
+
// is_empty(self) -> true/false
static int l_is_empty(lua_State *L);
diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp
index 821b1cb66..851ede535 100644
--- a/src/script/lua_api/l_localplayer.cpp
+++ b/src/script/lua_api/l_localplayer.cpp
@@ -19,10 +19,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "l_localplayer.h"
#include "l_internal.h"
+#include "lua_api/l_item.h"
#include "script/common/c_converter.h"
#include "client/localplayer.h"
#include "hud.h"
#include "common/c_content.h"
+#include "client/content_cao.h"
LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m)
{
@@ -74,6 +76,26 @@ int LuaLocalPlayer::l_get_name(lua_State *L)
return 1;
}
+// get_wield_index(self)
+int LuaLocalPlayer::l_get_wield_index(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushinteger(L, player->getWieldIndex());
+ return 1;
+}
+
+// get_wielded_item(self)
+int LuaLocalPlayer::l_get_wielded_item(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ ItemStack selected_item;
+ player->getWieldedItem(&selected_item, nullptr);
+ LuaItemStack::create(L, selected_item);
+ return 1;
+}
+
int LuaLocalPlayer::l_is_attached(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
@@ -130,6 +152,7 @@ int LuaLocalPlayer::l_swimming_vertical(lua_State *L)
return 1;
}
+// get_physics_override(self)
int LuaLocalPlayer::l_get_physics_override(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
@@ -150,14 +173,9 @@ int LuaLocalPlayer::l_get_physics_override(lua_State *L)
lua_pushboolean(L, player->physics_override_sneak_glitch);
lua_setfield(L, -2, "sneak_glitch");
- return 1;
-}
-
-int LuaLocalPlayer::l_get_override_pos(lua_State *L)
-{
- LocalPlayer *player = getobject(L, 1);
+ lua_pushboolean(L, player->physics_override_new_move);
+ lua_setfield(L, -2, "new_move");
- push_v3f(L, player->getPosition());
return 1;
}
@@ -193,14 +211,33 @@ int LuaLocalPlayer::l_get_last_look_horizontal(lua_State *L)
return 1;
}
-int LuaLocalPlayer::l_get_key_pressed(lua_State *L)
+// get_control(self)
+int LuaLocalPlayer::l_get_control(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
+ const PlayerControl &c = player->getPlayerControl();
+
+ auto set = [L] (const char *name, bool value) {
+ lua_pushboolean(L, value);
+ lua_setfield(L, -2, name);
+ };
+
+ lua_createtable(L, 0, 12);
+ set("up", c.up);
+ set("down", c.down);
+ set("left", c.left);
+ set("right", c.right);
+ set("jump", c.jump);
+ set("aux1", c.aux1);
+ set("sneak", c.sneak);
+ set("zoom", c.zoom);
+ set("LMB", c.LMB);
+ set("RMB", c.RMB);
- lua_pushinteger(L, player->last_keyPressed);
return 1;
}
+// get_breath(self)
int LuaLocalPlayer::l_get_breath(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
@@ -209,6 +246,7 @@ int LuaLocalPlayer::l_get_breath(lua_State *L)
return 1;
}
+// get_pos(self)
int LuaLocalPlayer::l_get_pos(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
@@ -217,6 +255,7 @@ int LuaLocalPlayer::l_get_pos(lua_State *L)
return 1;
}
+// get_movement_acceleration(self)
int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
@@ -234,6 +273,7 @@ int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L)
return 1;
}
+// get_movement_speed(self)
int LuaLocalPlayer::l_get_movement_speed(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
@@ -257,6 +297,7 @@ int LuaLocalPlayer::l_get_movement_speed(lua_State *L)
return 1;
}
+// get_movement(self)
int LuaLocalPlayer::l_get_movement(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
@@ -278,6 +319,13 @@ int LuaLocalPlayer::l_get_movement(lua_State *L)
return 1;
}
+// get_armor_groups(self)
+int LuaLocalPlayer::l_get_armor_groups(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+ push_groups(L, player->getCAO()->getGroups());
+ return 1;
+}
// hud_add(self, form)
int LuaLocalPlayer::l_hud_add(lua_State *L)
@@ -407,6 +455,8 @@ const luaL_Reg LuaLocalPlayer::methods[] = {
luamethod(LuaLocalPlayer, get_velocity),
luamethod(LuaLocalPlayer, get_hp),
luamethod(LuaLocalPlayer, get_name),
+ luamethod(LuaLocalPlayer, get_wield_index),
+ luamethod(LuaLocalPlayer, get_wielded_item),
luamethod(LuaLocalPlayer, is_attached),
luamethod(LuaLocalPlayer, is_touching_ground),
luamethod(LuaLocalPlayer, is_in_liquid),
@@ -415,17 +465,19 @@ const luaL_Reg LuaLocalPlayer::methods[] = {
luamethod(LuaLocalPlayer, is_climbing),
luamethod(LuaLocalPlayer, swimming_vertical),
luamethod(LuaLocalPlayer, get_physics_override),
- luamethod(LuaLocalPlayer, get_override_pos),
+ // TODO: figure our if these are useful in any way
luamethod(LuaLocalPlayer, get_last_pos),
luamethod(LuaLocalPlayer, get_last_velocity),
luamethod(LuaLocalPlayer, get_last_look_horizontal),
luamethod(LuaLocalPlayer, get_last_look_vertical),
- luamethod(LuaLocalPlayer, get_key_pressed),
+ //
+ luamethod(LuaLocalPlayer, get_control),
luamethod(LuaLocalPlayer, get_breath),
luamethod(LuaLocalPlayer, get_pos),
luamethod(LuaLocalPlayer, get_movement_acceleration),
luamethod(LuaLocalPlayer, get_movement_speed),
luamethod(LuaLocalPlayer, get_movement),
+ luamethod(LuaLocalPlayer, get_armor_groups),
luamethod(LuaLocalPlayer, hud_add),
luamethod(LuaLocalPlayer, hud_remove),
luamethod(LuaLocalPlayer, hud_change),
diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h
index 01de2ed4e..4413f2bdb 100644
--- a/src/script/lua_api/l_localplayer.h
+++ b/src/script/lua_api/l_localplayer.h
@@ -32,12 +32,21 @@ private:
// garbage collector
static int gc_object(lua_State *L);
+ // get_velocity(self)
static int l_get_velocity(lua_State *L);
+ // get_hp(self)
static int l_get_hp(lua_State *L);
+ // get_name(self)
static int l_get_name(lua_State *L);
+ // get_wield_index(self)
+ static int l_get_wield_index(lua_State *L);
+
+ // get_wielded_item(self)
+ static int l_get_wielded_item(lua_State *L);
+
static int l_is_attached(lua_State *L);
static int l_is_touching_ground(lua_State *L);
static int l_is_in_liquid(lua_State *L);
@@ -54,18 +63,28 @@ private:
static int l_get_last_velocity(lua_State *L);
static int l_get_last_look_vertical(lua_State *L);
static int l_get_last_look_horizontal(lua_State *L);
- static int l_get_key_pressed(lua_State *L);
+ // get_control(self)
+ static int l_get_control(lua_State *L);
+
+ // get_breath(self)
static int l_get_breath(lua_State *L);
+ // get_pos(self)
static int l_get_pos(lua_State *L);
+ // get_movement_acceleration(self)
static int l_get_movement_acceleration(lua_State *L);
+ // get_movement_speed(self)
static int l_get_movement_speed(lua_State *L);
+ // get_movement(self)
static int l_get_movement(lua_State *L);
+ // get_armor_groups(self)
+ static int l_get_armor_groups(lua_State *L);
+
// hud_add(self, id, form)
static int l_hud_add(lua_State *L);
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index 76db7ed13..f32c477c2 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -280,8 +280,8 @@ int ModApiMainMenu::l_get_favorites(lua_State *L)
{
std::string listtype = "local";
- if (!lua_isnone(L,1)) {
- listtype = luaL_checkstring(L,1);
+ if (!lua_isnone(L, 1)) {
+ listtype = luaL_checkstring(L, 1);
}
std::vector<ServerListSpec> servers;
@@ -298,7 +298,7 @@ int ModApiMainMenu::l_get_favorites(lua_State *L)
for (const Json::Value &server : servers) {
- lua_pushnumber(L,index);
+ lua_pushnumber(L, index);
lua_newtable(L);
int top_lvl2 = lua_gettop(L);
@@ -306,11 +306,11 @@ int ModApiMainMenu::l_get_favorites(lua_State *L)
if (!server["clients"].asString().empty()) {
std::string clients_raw = server["clients"].asString();
char* endptr = 0;
- int numbervalue = strtol(clients_raw.c_str(),&endptr,10);
+ int numbervalue = strtol(clients_raw.c_str(), &endptr,10);
if ((!clients_raw.empty()) && (*endptr == 0)) {
- lua_pushstring(L,"clients");
- lua_pushnumber(L,numbervalue);
+ lua_pushstring(L, "clients");
+ lua_pushnumber(L, numbervalue);
lua_settable(L, top_lvl2);
}
}
@@ -319,83 +319,83 @@ int ModApiMainMenu::l_get_favorites(lua_State *L)
std::string clients_max_raw = server["clients_max"].asString();
char* endptr = 0;
- int numbervalue = strtol(clients_max_raw.c_str(),&endptr,10);
+ int numbervalue = strtol(clients_max_raw.c_str(), &endptr,10);
if ((!clients_max_raw.empty()) && (*endptr == 0)) {
- lua_pushstring(L,"clients_max");
- lua_pushnumber(L,numbervalue);
+ lua_pushstring(L, "clients_max");
+ lua_pushnumber(L, numbervalue);
lua_settable(L, top_lvl2);
}
}
if (!server["version"].asString().empty()) {
- lua_pushstring(L,"version");
+ lua_pushstring(L, "version");
std::string topush = server["version"].asString();
- lua_pushstring(L,topush.c_str());
+ lua_pushstring(L, topush.c_str());
lua_settable(L, top_lvl2);
}
if (!server["proto_min"].asString().empty()) {
- lua_pushstring(L,"proto_min");
+ lua_pushstring(L, "proto_min");
lua_pushinteger(L, server["proto_min"].asInt());
lua_settable(L, top_lvl2);
}
if (!server["proto_max"].asString().empty()) {
- lua_pushstring(L,"proto_max");
+ lua_pushstring(L, "proto_max");
lua_pushinteger(L, server["proto_max"].asInt());
lua_settable(L, top_lvl2);
}
if (!server["password"].asString().empty()) {
- lua_pushstring(L,"password");
+ lua_pushstring(L, "password");
lua_pushboolean(L, server["password"].asBool());
lua_settable(L, top_lvl2);
}
if (!server["creative"].asString().empty()) {
- lua_pushstring(L,"creative");
+ lua_pushstring(L, "creative");
lua_pushboolean(L, server["creative"].asBool());
lua_settable(L, top_lvl2);
}
if (!server["damage"].asString().empty()) {
- lua_pushstring(L,"damage");
+ lua_pushstring(L, "damage");
lua_pushboolean(L, server["damage"].asBool());
lua_settable(L, top_lvl2);
}
if (!server["pvp"].asString().empty()) {
- lua_pushstring(L,"pvp");
+ lua_pushstring(L, "pvp");
lua_pushboolean(L, server["pvp"].asBool());
lua_settable(L, top_lvl2);
}
if (!server["description"].asString().empty()) {
- lua_pushstring(L,"description");
+ lua_pushstring(L, "description");
std::string topush = server["description"].asString();
- lua_pushstring(L,topush.c_str());
+ lua_pushstring(L, topush.c_str());
lua_settable(L, top_lvl2);
}
if (!server["name"].asString().empty()) {
- lua_pushstring(L,"name");
+ lua_pushstring(L, "name");
std::string topush = server["name"].asString();
- lua_pushstring(L,topush.c_str());
+ lua_pushstring(L, topush.c_str());
lua_settable(L, top_lvl2);
}
if (!server["address"].asString().empty()) {
- lua_pushstring(L,"address");
+ lua_pushstring(L, "address");
std::string topush = server["address"].asString();
- lua_pushstring(L,topush.c_str());
+ lua_pushstring(L, topush.c_str());
lua_settable(L, top_lvl2);
}
if (!server["port"].asString().empty()) {
- lua_pushstring(L,"port");
+ lua_pushstring(L, "port");
std::string topush = server["port"].asString();
- lua_pushstring(L,topush.c_str());
+ lua_pushstring(L, topush.c_str());
lua_settable(L, top_lvl2);
}
@@ -406,6 +406,37 @@ int ModApiMainMenu::l_get_favorites(lua_State *L)
lua_settable(L, top_lvl2);
}
+ if (server["clients_list"].isArray()) {
+ unsigned int index_lvl2 = 1;
+ lua_pushstring(L, "clients_list");
+ lua_newtable(L);
+ int top_lvl3 = lua_gettop(L);
+ for (const Json::Value &client : server["clients_list"]) {
+ lua_pushnumber(L, index_lvl2);
+ std::string topush = client.asString();
+ lua_pushstring(L, topush.c_str());
+ lua_settable(L, top_lvl3);
+ index_lvl2++;
+ }
+ lua_settable(L, top_lvl2);
+ }
+
+ if (server["mods"].isArray()) {
+ unsigned int index_lvl2 = 1;
+ lua_pushstring(L, "mods");
+ lua_newtable(L);
+ int top_lvl3 = lua_gettop(L);
+ for (const Json::Value &mod : server["mods"]) {
+
+ lua_pushnumber(L, index_lvl2);
+ std::string topush = mod.asString();
+ lua_pushstring(L, topush.c_str());
+ lua_settable(L, top_lvl3);
+ index_lvl2++;
+ }
+ lua_settable(L, top_lvl2);
+ }
+
lua_settable(L, top);
index++;
}
@@ -571,9 +602,10 @@ int ModApiMainMenu::l_show_keys_menu(lua_State *L)
sanity_check(engine != NULL);
GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(RenderingEngine::get_gui_env(),
- engine->m_parent,
- -1,
- engine->m_menumanager);
+ engine->m_parent,
+ -1,
+ engine->m_menumanager,
+ engine->m_texture_source);
kmenu->drop();
return 0;
}
@@ -904,12 +936,12 @@ int ModApiMainMenu::l_show_path_select_dialog(lua_State *L)
GUIFileSelectMenu* fileOpenMenu =
new GUIFileSelectMenu(RenderingEngine::get_gui_env(),
- engine->m_parent,
- -1,
- engine->m_menumanager,
- title,
- formname,
- is_file_select);
+ engine->m_parent,
+ -1,
+ engine->m_menumanager,
+ title,
+ formname,
+ is_file_select);
fileOpenMenu->setTextDest(engine->m_buttonhandler);
fileOpenMenu->drop();
return 0;
@@ -1032,6 +1064,14 @@ int ModApiMainMenu::l_get_max_supp_proto(lua_State *L)
}
/******************************************************************************/
+int ModApiMainMenu::l_open_url(lua_State *L)
+{
+ std::string url = luaL_checkstring(L, 1);
+ lua_pushboolean(L, porting::openURL(url));
+ return 1;
+}
+
+/******************************************************************************/
int ModApiMainMenu::l_do_async_callback(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
@@ -1093,6 +1133,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
API_FCT(get_screen_info);
API_FCT(get_min_supp_proto);
API_FCT(get_max_supp_proto);
+ API_FCT(open_url);
API_FCT(do_async_callback);
}
diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h
index b2ca49320..5a16b3bfe 100644
--- a/src/script/lua_api/l_mainmenu.h
+++ b/src/script/lua_api/l_mainmenu.h
@@ -145,6 +145,9 @@ private:
static int l_get_max_supp_proto(lua_State *L);
+ // other
+ static int l_open_url(lua_State *L);
+
// async
static int l_do_async_callback(lua_State *L);
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp
index cb0d6ac95..834938e56 100644
--- a/src/script/lua_api/l_mapgen.cpp
+++ b/src/script/lua_api/l_mapgen.cpp
@@ -91,13 +91,13 @@ struct EnumString ModApiMapgen::es_SchematicFormatType[] =
{0, NULL},
};
-ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr);
+ObjDef *get_objdef(lua_State *L, int index, const ObjDefManager *objmgr);
Biome *get_or_load_biome(lua_State *L, int index,
BiomeManager *biomemgr);
Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef);
size_t get_biome_list(lua_State *L, int index,
- BiomeManager *biomemgr, std::unordered_set<u8> *biome_id_list);
+ BiomeManager *biomemgr, std::unordered_set<biome_t> *biome_id_list);
Schematic *get_or_load_schematic(lua_State *L, int index,
SchematicManager *schemmgr, StringMap *replace_names);
@@ -114,7 +114,7 @@ bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic
///////////////////////////////////////////////////////////////////////////////
-ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr)
+ObjDef *get_objdef(lua_State *L, int index, const ObjDefManager *objmgr)
{
if (index < 0)
index = lua_gettop(L) + 1 + index;
@@ -425,7 +425,7 @@ Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef)
size_t get_biome_list(lua_State *L, int index,
- BiomeManager *biomemgr, std::unordered_set<u8> *biome_id_list)
+ BiomeManager *biomemgr, std::unordered_set<biome_t> *biome_id_list)
{
if (index < 0)
index = lua_gettop(L) + 1 + index;
@@ -486,11 +486,11 @@ int ModApiMapgen::l_get_biome_id(lua_State *L)
if (!biome_str)
return 0;
- BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
+ const BiomeManager *bmgr = getServer(L)->getEmergeManager()->getBiomeManager();
if (!bmgr)
return 0;
- Biome *biome = (Biome *)bmgr->getByName(biome_str);
+ const Biome *biome = (Biome *)bmgr->getByName(biome_str);
if (!biome || biome->index == OBJDEF_INVALID_INDEX)
return 0;
@@ -508,11 +508,11 @@ int ModApiMapgen::l_get_biome_name(lua_State *L)
int biome_id = luaL_checkinteger(L, 1);
- BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
+ const BiomeManager *bmgr = getServer(L)->getEmergeManager()->getBiomeManager();
if (!bmgr)
return 0;
- Biome *b = (Biome *)bmgr->getRaw(biome_id);
+ const Biome *b = (Biome *)bmgr->getRaw(biome_id);
lua_pushstring(L, b->name.c_str());
return 1;
@@ -546,13 +546,11 @@ int ModApiMapgen::l_get_heat(lua_State *L)
u64 seed;
ss >> seed;
- BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
+ const BiomeManager *bmgr = getServer(L)->getEmergeManager()->getBiomeManager();
if (!bmgr)
return 0;
float heat = bmgr->getHeatAtPosOriginal(pos, np_heat, np_heat_blend, seed);
- if (!heat)
- return 0;
lua_pushnumber(L, heat);
@@ -587,14 +585,12 @@ int ModApiMapgen::l_get_humidity(lua_State *L)
u64 seed;
ss >> seed;
- BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
+ const BiomeManager *bmgr = getServer(L)->getEmergeManager()->getBiomeManager();
if (!bmgr)
return 0;
float humidity = bmgr->getHumidityAtPosOriginal(pos, np_humidity,
np_humidity_blend, seed);
- if (!humidity)
- return 0;
lua_pushnumber(L, humidity);
@@ -635,7 +631,7 @@ int ModApiMapgen::l_get_biome_data(lua_State *L)
u64 seed;
ss >> seed;
- BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
+ const BiomeManager *bmgr = getServer(L)->getEmergeManager()->getBiomeManager();
if (!bmgr)
return 0;
@@ -648,7 +644,7 @@ int ModApiMapgen::l_get_biome_data(lua_State *L)
if (!humidity)
return 0;
- Biome *biome = (Biome *)bmgr->getBiomeFromNoiseOriginal(heat, humidity, pos);
+ const Biome *biome = bmgr->getBiomeFromNoiseOriginal(heat, humidity, pos);
if (!biome || biome->index == OBJDEF_INVALID_INDEX)
return 0;
@@ -710,7 +706,7 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
if (!mg->heightmap)
return 0;
- lua_newtable(L);
+ lua_createtable(L, maplen, 0);
for (size_t i = 0; i != maplen; i++) {
lua_pushinteger(L, mg->heightmap[i]);
lua_rawseti(L, -2, i + 1);
@@ -722,7 +718,7 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
if (!mg->biomegen)
return 0;
- lua_newtable(L);
+ lua_createtable(L, maplen, 0);
for (size_t i = 0; i != maplen; i++) {
lua_pushinteger(L, mg->biomegen->biomemap[i]);
lua_rawseti(L, -2, i + 1);
@@ -736,7 +732,7 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
BiomeGenOriginal *bg = (BiomeGenOriginal *)mg->biomegen;
- lua_newtable(L);
+ lua_createtable(L, maplen, 0);
for (size_t i = 0; i != maplen; i++) {
lua_pushnumber(L, bg->heatmap[i]);
lua_rawseti(L, -2, i + 1);
@@ -751,7 +747,7 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
BiomeGenOriginal *bg = (BiomeGenOriginal *)mg->biomegen;
- lua_newtable(L);
+ lua_createtable(L, maplen, 0);
for (size_t i = 0; i != maplen; i++) {
lua_pushnumber(L, bg->humidmap[i]);
lua_rawseti(L, -2, i + 1);
@@ -761,13 +757,12 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
}
case MGOBJ_GENNOTIFY: {
std::map<std::string, std::vector<v3s16> >event_map;
- std::map<std::string, std::vector<v3s16> >::iterator it;
mg->gennotify.getEvents(event_map);
- lua_newtable(L);
- for (it = event_map.begin(); it != event_map.end(); ++it) {
- lua_newtable(L);
+ lua_createtable(L, 0, event_map.size());
+ for (auto it = event_map.begin(); it != event_map.end(); ++it) {
+ lua_createtable(L, it->second.size(), 0);
for (size_t j = 0; j != it->second.size(); j++) {
push_v3s16(L, it->second[j]);
@@ -1067,7 +1062,8 @@ int ModApiMapgen::l_get_decoration_id(lua_State *L)
if (!deco_str)
return 0;
- DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr;
+ const DecorationManager *dmgr =
+ getServer(L)->getEmergeManager()->getDecorationManager();
if (!dmgr)
return 0;
@@ -1092,7 +1088,7 @@ int ModApiMapgen::l_register_biome(lua_State *L)
luaL_checktype(L, index, LUA_TTABLE);
const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
- BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
+ BiomeManager *bmgr = getServer(L)->getEmergeManager()->getWritableBiomeManager();
Biome *biome = read_biome_def(L, index, ndef);
if (!biome)
@@ -1118,9 +1114,10 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
luaL_checktype(L, index, LUA_TTABLE);
const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
- DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr;
- BiomeManager *biomemgr = getServer(L)->getEmergeManager()->biomemgr;
- SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
+ EmergeManager *emerge = getServer(L)->getEmergeManager();
+ DecorationManager *decomgr = emerge->getWritableDecorationManager();
+ BiomeManager *biomemgr = emerge->getWritableBiomeManager();
+ SchematicManager *schemmgr = emerge->getWritableSchematicManager();
enum DecorationType decotype = (DecorationType)getenumfield(L, index,
"deco_type", es_DecorationType, -1);
@@ -1275,8 +1272,9 @@ int ModApiMapgen::l_register_ore(lua_State *L)
luaL_checktype(L, index, LUA_TTABLE);
const NodeDefManager *ndef = getServer(L)->getNodeDefManager();
- BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
- OreManager *oremgr = getServer(L)->getEmergeManager()->oremgr;
+ EmergeManager *emerge = getServer(L)->getEmergeManager();
+ BiomeManager *bmgr = emerge->getWritableBiomeManager();
+ OreManager *oremgr = emerge->getWritableOreManager();
enum OreType oretype = (OreType)getenumfield(L, index,
"ore_type", es_OreType, ORE_SCATTER);
@@ -1423,7 +1421,8 @@ int ModApiMapgen::l_register_schematic(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
+ SchematicManager *schemmgr =
+ getServer(L)->getEmergeManager()->getWritableSchematicManager();
StringMap replace_names;
if (lua_istable(L, 2))
@@ -1450,7 +1449,8 @@ int ModApiMapgen::l_clear_registered_biomes(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
+ BiomeManager *bmgr =
+ getServer(L)->getEmergeManager()->getWritableBiomeManager();
bmgr->clear();
return 0;
}
@@ -1461,7 +1461,8 @@ int ModApiMapgen::l_clear_registered_decorations(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr;
+ DecorationManager *dmgr =
+ getServer(L)->getEmergeManager()->getWritableDecorationManager();
dmgr->clear();
return 0;
}
@@ -1472,7 +1473,8 @@ int ModApiMapgen::l_clear_registered_ores(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- OreManager *omgr = getServer(L)->getEmergeManager()->oremgr;
+ OreManager *omgr =
+ getServer(L)->getEmergeManager()->getWritableOreManager();
omgr->clear();
return 0;
}
@@ -1483,7 +1485,8 @@ int ModApiMapgen::l_clear_registered_schematics(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- SchematicManager *smgr = getServer(L)->getEmergeManager()->schemmgr;
+ SchematicManager *smgr =
+ getServer(L)->getEmergeManager()->getWritableSchematicManager();
smgr->clear();
return 0;
}
@@ -1708,7 +1711,7 @@ int ModApiMapgen::l_serialize_schematic(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
+ const SchematicManager *schemmgr = getServer(L)->getEmergeManager()->getSchematicManager();
//// Read options
bool use_comments = getboolfield_default(L, 3, "lua_use_comments", false);
@@ -1716,7 +1719,7 @@ int ModApiMapgen::l_serialize_schematic(lua_State *L)
//// Get schematic
bool was_loaded = false;
- Schematic *schem = (Schematic *)get_objdef(L, 1, schemmgr);
+ const Schematic *schem = (Schematic *)get_objdef(L, 1, schemmgr);
if (!schem) {
schem = load_schematic(L, 1, NULL, NULL);
was_loaded = true;
@@ -1759,7 +1762,8 @@ int ModApiMapgen::l_read_schematic(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
+ const SchematicManager *schemmgr =
+ getServer(L)->getEmergeManager()->getSchematicManager();
//// Read options
std::string write_yslice = getstringfield_default(L, 2, "write_yslice_prob", "all");
diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h
index 4a6a9ccf4..0bdc56fc5 100644
--- a/src/script/lua_api/l_mapgen.h
+++ b/src/script/lua_api/l_mapgen.h
@@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_base.h"
+typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include
+
class ModApiMapgen : public ModApiBase
{
private:
diff --git a/src/script/lua_api/l_metadata.cpp b/src/script/lua_api/l_metadata.cpp
index 21002e6a7..61a25a761 100644
--- a/src/script/lua_api/l_metadata.cpp
+++ b/src/script/lua_api/l_metadata.cpp
@@ -153,7 +153,9 @@ int MetaDataRef::l_set_int(lua_State *L)
MetaDataRef *ref = checkobject(L, 1);
std::string name = luaL_checkstring(L, 2);
int a = luaL_checkint(L, 3);
- std::string str = itos(a);
+ std::string str;
+ if (a != 0)
+ str = itos(a);
Metadata *meta = ref->getmeta(true);
if (meta == NULL || str == meta->getString(name))
@@ -191,7 +193,9 @@ int MetaDataRef::l_set_float(lua_State *L)
MetaDataRef *ref = checkobject(L, 1);
std::string name = luaL_checkstring(L, 2);
float a = readParam<float>(L, 3);
- std::string str = ftos(a);
+ std::string str;
+ if (a != 0)
+ str = ftos(a);
Metadata *meta = ref->getmeta(true);
if (meta == NULL || str == meta->getString(name))
diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp
index 229ce73db..57052cb42 100644
--- a/src/script/lua_api/l_nodemeta.cpp
+++ b/src/script/lua_api/l_nodemeta.cpp
@@ -55,11 +55,13 @@ Metadata* NodeMetaRef::getmeta(bool auto_create)
void NodeMetaRef::clearMeta()
{
+ SANITY_CHECK(!m_is_local);
m_env->getMap().removeNodeMetadata(m_p);
}
void NodeMetaRef::reportMetadataChange(const std::string *name)
{
+ SANITY_CHECK(!m_is_local);
// NOTE: This same code is in rollback_interface.cpp
// Inform other things that the metadata has changed
NodeMetadata *meta = dynamic_cast<NodeMetadata*>(m_meta);
diff --git a/src/script/lua_api/l_nodetimer.cpp b/src/script/lua_api/l_nodetimer.cpp
index 15a59744f..c2df52c05 100644
--- a/src/script/lua_api/l_nodetimer.cpp
+++ b/src/script/lua_api/l_nodetimer.cpp
@@ -41,11 +41,9 @@ int NodeTimerRef::l_set(lua_State *L)
{
MAP_LOCK_REQUIRED;
NodeTimerRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->m_env;
- if(env == NULL) return 0;
f32 t = readParam<float>(L,2);
f32 e = readParam<float>(L,3);
- env->getMap().setNodeTimer(NodeTimer(t, e, o->m_p));
+ o->m_map->setNodeTimer(NodeTimer(t, e, o->m_p));
return 0;
}
@@ -53,10 +51,8 @@ int NodeTimerRef::l_start(lua_State *L)
{
MAP_LOCK_REQUIRED;
NodeTimerRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->m_env;
- if(env == NULL) return 0;
f32 t = readParam<float>(L,2);
- env->getMap().setNodeTimer(NodeTimer(t, 0, o->m_p));
+ o->m_map->setNodeTimer(NodeTimer(t, 0, o->m_p));
return 0;
}
@@ -64,9 +60,7 @@ int NodeTimerRef::l_stop(lua_State *L)
{
MAP_LOCK_REQUIRED;
NodeTimerRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->m_env;
- if(env == NULL) return 0;
- env->getMap().removeNodeTimer(o->m_p);
+ o->m_map->removeNodeTimer(o->m_p);
return 0;
}
@@ -74,10 +68,7 @@ int NodeTimerRef::l_is_started(lua_State *L)
{
MAP_LOCK_REQUIRED;
NodeTimerRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->m_env;
- if(env == NULL) return 0;
-
- NodeTimer t = env->getMap().getNodeTimer(o->m_p);
+ NodeTimer t = o->m_map->getNodeTimer(o->m_p);
lua_pushboolean(L,(t.timeout != 0));
return 1;
}
@@ -86,10 +77,7 @@ int NodeTimerRef::l_get_timeout(lua_State *L)
{
MAP_LOCK_REQUIRED;
NodeTimerRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->m_env;
- if(env == NULL) return 0;
-
- NodeTimer t = env->getMap().getNodeTimer(o->m_p);
+ NodeTimer t = o->m_map->getNodeTimer(o->m_p);
lua_pushnumber(L,t.timeout);
return 1;
}
@@ -98,37 +86,21 @@ int NodeTimerRef::l_get_elapsed(lua_State *L)
{
MAP_LOCK_REQUIRED;
NodeTimerRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->m_env;
- if(env == NULL) return 0;
-
- NodeTimer t = env->getMap().getNodeTimer(o->m_p);
+ NodeTimer t = o->m_map->getNodeTimer(o->m_p);
lua_pushnumber(L,t.elapsed);
return 1;
}
-
-NodeTimerRef::NodeTimerRef(v3s16 p, ServerEnvironment *env):
- m_p(p),
- m_env(env)
-{
-}
-
// Creates an NodeTimerRef and leaves it on top of stack
// Not callable from Lua; all references are created on the C side.
-void NodeTimerRef::create(lua_State *L, v3s16 p, ServerEnvironment *env)
+void NodeTimerRef::create(lua_State *L, v3s16 p, ServerMap *map)
{
- NodeTimerRef *o = new NodeTimerRef(p, env);
+ NodeTimerRef *o = new NodeTimerRef(p, map);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
}
-void NodeTimerRef::set_null(lua_State *L)
-{
- NodeTimerRef *o = checkobject(L, -1);
- o->m_env = NULL;
-}
-
void NodeTimerRef::Register(lua_State *L)
{
lua_newtable(L);
diff --git a/src/script/lua_api/l_nodetimer.h b/src/script/lua_api/l_nodetimer.h
index b894c5c8c..bbc975fd2 100644
--- a/src/script/lua_api/l_nodetimer.h
+++ b/src/script/lua_api/l_nodetimer.h
@@ -22,13 +22,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irr_v3d.h"
#include "lua_api/l_base.h"
-class ServerEnvironment;
+class ServerMap;
class NodeTimerRef : public ModApiBase
{
private:
v3s16 m_p;
- ServerEnvironment *m_env = nullptr;
+ ServerMap *m_map;
static const char className[];
static const luaL_Reg methods[];
@@ -50,14 +50,12 @@ private:
static int l_get_elapsed(lua_State *L);
public:
- NodeTimerRef(v3s16 p, ServerEnvironment *env);
+ NodeTimerRef(v3s16 p, ServerMap *map) : m_p(p), m_map(map) {}
~NodeTimerRef() = default;
// Creates an NodeTimerRef and leaves it on top of stack
// Not callable from Lua; all references are created on the C side.
- static void create(lua_State *L, v3s16 p, ServerEnvironment *env);
-
- static void set_null(lua_State *L);
+ static void create(lua_State *L, v3s16 p, ServerMap *map);
static void Register(lua_State *L);
};
diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp
index e38d319f4..9aeb15709 100644
--- a/src/script/lua_api/l_noise.cpp
+++ b/src/script/lua_api/l_noise.cpp
@@ -171,9 +171,9 @@ int LuaPerlinNoiseMap::l_get_2d_map(lua_State *L)
Noise *n = o->noise;
n->perlinMap2D(p.X, p.Y);
- lua_newtable(L);
+ lua_createtable(L, n->sy, 0);
for (u32 y = 0; y != n->sy; y++) {
- lua_newtable(L);
+ lua_createtable(L, n->sx, 0);
for (u32 x = 0; x != n->sx; x++) {
lua_pushnumber(L, n->result[i++]);
lua_rawseti(L, -2, x + 1);
@@ -200,7 +200,7 @@ int LuaPerlinNoiseMap::l_get_2d_map_flat(lua_State *L)
if (use_buffer)
lua_pushvalue(L, 3);
else
- lua_newtable(L);
+ lua_createtable(L, maplen, 0);
for (size_t i = 0; i != maplen; i++) {
lua_pushnumber(L, n->result[i]);
@@ -224,11 +224,11 @@ int LuaPerlinNoiseMap::l_get_3d_map(lua_State *L)
Noise *n = o->noise;
n->perlinMap3D(p.X, p.Y, p.Z);
- lua_newtable(L);
+ lua_createtable(L, n->sz, 0);
for (u32 z = 0; z != n->sz; z++) {
- lua_newtable(L);
+ lua_createtable(L, n->sy, 0);
for (u32 y = 0; y != n->sy; y++) {
- lua_newtable(L);
+ lua_createtable(L, n->sx, 0);
for (u32 x = 0; x != n->sx; x++) {
lua_pushnumber(L, n->result[i++]);
lua_rawseti(L, -2, x + 1);
@@ -260,7 +260,7 @@ int LuaPerlinNoiseMap::l_get_3d_map_flat(lua_State *L)
if (use_buffer)
lua_pushvalue(L, 3);
else
- lua_newtable(L);
+ lua_createtable(L, maplen, 0);
for (size_t i = 0; i != maplen; i++) {
lua_pushnumber(L, n->result[i]);
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 23ed1ffe0..e7394133a 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -27,12 +27,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_content.h"
#include "log.h"
#include "tool.h"
-#include "serverobject.h"
-#include "content_sao.h"
#include "remoteplayer.h"
#include "server.h"
#include "hud.h"
#include "scripting_server.h"
+#include "server/luaentity_sao.h"
+#include "server/player_sao.h"
+#include "server/serverinventorymgr.h"
/*
ObjectRef
@@ -50,6 +51,8 @@ ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
{
ServerActiveObject *co = ref->m_object;
+ if (co && co->isGone())
+ return NULL;
return co;
}
@@ -60,8 +63,6 @@ LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
return NULL;
if (obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
return NULL;
- if (obj->isGone())
- return NULL;
return (LuaEntitySAO*)obj;
}
@@ -72,8 +73,6 @@ PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
return NULL;
if (obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
return NULL;
- if (obj->isGone())
- return NULL;
return (PlayerSAO*)obj;
}
@@ -123,14 +122,7 @@ int ObjectRef::l_get_pos(lua_State *L)
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
if (co == NULL) return 0;
- v3f pos = co->getBasePosition() / BS;
- lua_newtable(L);
- lua_pushnumber(L, pos.X);
- lua_setfield(L, -2, "x");
- lua_pushnumber(L, pos.Y);
- lua_setfield(L, -2, "y");
- lua_pushnumber(L, pos.Z);
- lua_setfield(L, -2, "z");
+ push_v3f(L, co->getBasePosition() / BS);
return 1;
}
@@ -139,7 +131,6 @@ int ObjectRef::l_set_pos(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- //LuaEntitySAO *co = getluaobject(ref);
ServerActiveObject *co = getobject(ref);
if (co == NULL) return 0;
// pos
@@ -154,7 +145,6 @@ int ObjectRef::l_move_to(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
- //LuaEntitySAO *co = getluaobject(ref);
ServerActiveObject *co = getobject(ref);
if (co == NULL) return 0;
// pos
@@ -300,7 +290,7 @@ int ObjectRef::l_get_inventory(lua_State *L)
if (co == NULL) return 0;
// Do it
InventoryLocation loc = co->getInventoryLocation();
- if (getServer(L)->getInventory(loc) != NULL)
+ if (getServerInventoryMgr(L)->getInventory(loc) != NULL)
InvRef::create(L, loc);
else
lua_pushnil(L); // An object may have no inventory (nil)
@@ -533,7 +523,7 @@ int ObjectRef::l_set_local_animation(lua_State *L)
// get_local_animation(self)
int ObjectRef::l_get_local_animation(lua_State *L)
{
- NO_MAP_LOCK_REQUIRED
+ NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
@@ -685,8 +675,13 @@ int ObjectRef::l_set_attach(lua_State *L)
ServerActiveObject *parent = getobject(parent_ref);
if (co == NULL)
return 0;
+
if (parent == NULL)
return 0;
+
+ if (co == parent)
+ throw LuaError("ObjectRef::set_attach: attaching object to itself is not allowed.");
+
// Do it
int parent_id = 0;
std::string bone;
@@ -1109,17 +1104,13 @@ int ObjectRef::l_add_player_velocity(lua_State *L)
ObjectRef *ref = checkobject(L, 1);
v3f vel = checkFloatPos(L, 2);
- RemotePlayer *player = getplayer(ref);
PlayerSAO *co = getplayersao(ref);
- if (!player || !co)
+ if (!co)
return 0;
- session_t peer_id = player->getPeerId();
- if (peer_id == PEER_ID_INEXISTENT)
- return 0;
// Do it
co->setMaxSpeedOverride(vel);
- getServer(L)->SendPlayerSpeed(peer_id, vel);
+ getServer(L)->SendPlayerSpeed(co->getPeerID(), vel);
return 0;
}
@@ -1259,7 +1250,7 @@ int ObjectRef::l_set_look_yaw(lua_State *L)
return 1;
}
-// set_fov(self, degrees[, is_multiplier])
+// set_fov(self, degrees[, is_multiplier, transition_time])
int ObjectRef::l_set_fov(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@@ -1268,7 +1259,11 @@ int ObjectRef::l_set_fov(lua_State *L)
if (!player)
return 0;
- player->setFov({ static_cast<f32>(luaL_checknumber(L, 2)), readParam<bool>(L, 3) });
+ player->setFov({
+ static_cast<f32>(luaL_checknumber(L, 2)),
+ readParam<bool>(L, 3, false),
+ lua_isnumber(L, 4) ? static_cast<f32>(luaL_checknumber(L, 4)) : 0.0f
+ });
getServer(L)->SendPlayerFov(player->getPeerId());
return 0;
@@ -1286,8 +1281,9 @@ int ObjectRef::l_get_fov(lua_State *L)
PlayerFovSpec fov_spec = player->getFov();
lua_pushnumber(L, fov_spec.fov);
lua_pushboolean(L, fov_spec.is_multiplier);
+ lua_pushnumber(L, fov_spec.transition_time);
- return 2;
+ return 3;
}
// set_breath(self, breath)
@@ -1463,6 +1459,8 @@ int ObjectRef::l_get_player_control(lua_State *L)
lua_setfield(L, -2, "LMB");
lua_pushboolean(L, control.RMB);
lua_setfield(L, -2, "RMB");
+ lua_pushboolean(L, control.zoom);
+ lua_setfield(L, -2, "zoom");
return 1;
}
@@ -1787,19 +1785,19 @@ int ObjectRef::l_set_sky(lua_State *L)
lua_pop(L, 1);
// Prevent flickering clouds at dawn/dusk:
- skybox_params.sun_tint = video::SColor(255, 255, 255, 255);
+ skybox_params.fog_sun_tint = video::SColor(255, 255, 255, 255);
lua_getfield(L, -1, "fog_sun_tint");
- read_color(L, -1, &skybox_params.sun_tint);
+ read_color(L, -1, &skybox_params.fog_sun_tint);
lua_pop(L, 1);
- skybox_params.moon_tint = video::SColor(255, 255, 255, 255);
+ skybox_params.fog_moon_tint = video::SColor(255, 255, 255, 255);
lua_getfield(L, -1, "fog_moon_tint");
- read_color(L, -1, &skybox_params.moon_tint);
+ read_color(L, -1, &skybox_params.fog_moon_tint);
lua_pop(L, 1);
lua_getfield(L, -1, "fog_tint_type");
if (!lua_isnil(L, -1))
- skybox_params.tint_type = luaL_checkstring(L, -1);
+ skybox_params.fog_tint_type = luaL_checkstring(L, -1);
lua_pop(L, 1);
// Because we need to leave the "sky_color" table.
@@ -1917,12 +1915,12 @@ int ObjectRef::l_get_sky_color(lua_State *L)
push_ARGB8(L, skybox_params.sky_color.indoors);
lua_setfield(L, -2, "indoors");
}
- push_ARGB8(L, skybox_params.sun_tint);
- lua_setfield(L, -2, "sun_tint");
- push_ARGB8(L, skybox_params.moon_tint);
- lua_setfield(L, -2, "moon_tint");
- lua_pushstring(L, skybox_params.tint_type.c_str());
- lua_setfield(L, -2, "tint_type");
+ push_ARGB8(L, skybox_params.fog_sun_tint);
+ lua_setfield(L, -2, "fog_sun_tint");
+ push_ARGB8(L, skybox_params.fog_moon_tint);
+ lua_setfield(L, -2, "fog_moon_tint");
+ lua_pushstring(L, skybox_params.fog_tint_type.c_str());
+ lua_setfield(L, -2, "fog_tint_type");
return 1;
}
@@ -2177,9 +2175,7 @@ int ObjectRef::l_override_day_night_ratio(lua_State *L)
ratio = readParam<float>(L, 2);
}
- if (!getServer(L)->overrideDayNightRatio(player, do_override, ratio))
- return 0;
-
+ getServer(L)->overrideDayNightRatio(player, do_override, ratio);
lua_pushboolean(L, true);
return 1;
}
diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp
index 340903ebf..a51c4fe20 100644
--- a/src/script/lua_api/l_particles.cpp
+++ b/src/script/lua_api/l_particles.cpp
@@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_converter.h"
#include "common/c_content.h"
#include "server.h"
-#include "client/particles.h"
+#include "particles.h"
// add_particle({pos=, velocity=, acceleration=, expirationtime=,
// size=, collisiondetection=, collision_removal=, object_collision=,
@@ -40,85 +40,88 @@ with this program; if not, write to the Free Software Foundation, Inc.,
// glow = num
int ModApiParticles::l_add_particle(lua_State *L)
{
- MAP_LOCK_REQUIRED;
+ NO_MAP_LOCK_REQUIRED;
// Get parameters
- v3f pos, vel, acc;
- float expirationtime, size;
- expirationtime = size = 1;
- bool collisiondetection, vertical, collision_removal, object_collision;
- collisiondetection = vertical = collision_removal = object_collision = false;
- struct TileAnimationParams animation;
- animation.type = TAT_NONE;
- std::string texture;
+ struct ParticleParameters p;
std::string playername;
- u8 glow = 0;
if (lua_gettop(L) > 1) // deprecated
{
- log_deprecated(L, "Deprecated add_particle call with individual parameters instead of definition");
- pos = check_v3f(L, 1);
- vel = check_v3f(L, 2);
- acc = check_v3f(L, 3);
- expirationtime = luaL_checknumber(L, 4);
- size = luaL_checknumber(L, 5);
- collisiondetection = readParam<bool>(L, 6);
- texture = luaL_checkstring(L, 7);
+ log_deprecated(L, "Deprecated add_particle call with "
+ "individual parameters instead of definition");
+ p.pos = check_v3f(L, 1);
+ p.vel = check_v3f(L, 2);
+ p.acc = check_v3f(L, 3);
+ p.expirationtime = luaL_checknumber(L, 4);
+ p.size = luaL_checknumber(L, 5);
+ p.collisiondetection = readParam<bool>(L, 6);
+ p.texture = luaL_checkstring(L, 7);
if (lua_gettop(L) == 8) // only spawn for a single player
playername = luaL_checkstring(L, 8);
}
else if (lua_istable(L, 1))
{
lua_getfield(L, 1, "pos");
- pos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f();
+ if (lua_istable(L, -1))
+ p.pos = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "vel");
if (lua_istable(L, -1)) {
- vel = check_v3f(L, -1);
+ p.vel = check_v3f(L, -1);
log_deprecated(L, "The use of vel is deprecated. "
"Use velocity instead");
}
lua_pop(L, 1);
lua_getfield(L, 1, "velocity");
- vel = lua_istable(L, -1) ? check_v3f(L, -1) : vel;
+ if (lua_istable(L, -1))
+ p.vel = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "acc");
if (lua_istable(L, -1)) {
- acc = check_v3f(L, -1);
+ p.acc = check_v3f(L, -1);
log_deprecated(L, "The use of acc is deprecated. "
"Use acceleration instead");
}
lua_pop(L, 1);
lua_getfield(L, 1, "acceleration");
- acc = lua_istable(L, -1) ? check_v3f(L, -1) : acc;
+ if (lua_istable(L, -1))
+ p.acc = check_v3f(L, -1);
lua_pop(L, 1);
- expirationtime = getfloatfield_default(L, 1, "expirationtime", 1);
- size = getfloatfield_default(L, 1, "size", 1);
- collisiondetection = getboolfield_default(L, 1,
- "collisiondetection", collisiondetection);
- collision_removal = getboolfield_default(L, 1,
- "collision_removal", collision_removal);
- object_collision = getboolfield_default(L, 1,
- "object_collision", object_collision);
- vertical = getboolfield_default(L, 1, "vertical", vertical);
+ p.expirationtime = getfloatfield_default(L, 1, "expirationtime",
+ p.expirationtime);
+ p.size = getfloatfield_default(L, 1, "size", p.size);
+ p.collisiondetection = getboolfield_default(L, 1,
+ "collisiondetection", p.collisiondetection);
+ p.collision_removal = getboolfield_default(L, 1,
+ "collision_removal", p.collision_removal);
+ p.object_collision = getboolfield_default(L, 1,
+ "object_collision", p.object_collision);
+ p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
lua_getfield(L, 1, "animation");
- animation = read_animation_definition(L, -1);
+ p.animation = read_animation_definition(L, -1);
lua_pop(L, 1);
- texture = getstringfield_default(L, 1, "texture", "");
- playername = getstringfield_default(L, 1, "playername", "");
+ p.texture = getstringfield_default(L, 1, "texture", p.texture);
+ p.glow = getintfield_default(L, 1, "glow", p.glow);
+
+ lua_getfield(L, 1, "node");
+ if (lua_istable(L, -1))
+ p.node = readnode(L, -1, getGameDef(L)->ndef());
+ lua_pop(L, 1);
- glow = getintfield_default(L, 1, "glow", 0);
+ p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
+
+ playername = getstringfield_default(L, 1, "playername", "");
}
- getServer(L)->spawnParticle(playername, pos, vel, acc, expirationtime, size,
- collisiondetection, collision_removal, object_collision, vertical,
- texture, animation, glow);
+
+ getServer(L)->spawnParticle(playername, p);
return 1;
}
@@ -146,84 +149,82 @@ int ModApiParticles::l_add_particle(lua_State *L)
// glow = num
int ModApiParticles::l_add_particlespawner(lua_State *L)
{
- MAP_LOCK_REQUIRED;
+ NO_MAP_LOCK_REQUIRED;
// Get parameters
- u16 amount = 1;
- v3f minpos, maxpos, minvel, maxvel, minacc, maxacc;
- float time, minexptime, maxexptime, minsize, maxsize;
- time = minexptime = maxexptime = minsize = maxsize = 1;
- bool collisiondetection, vertical, collision_removal, object_collision;
- collisiondetection = vertical = collision_removal = object_collision = false;
- struct TileAnimationParams animation;
- animation.type = TAT_NONE;
+ ParticleSpawnerParameters p;
ServerActiveObject *attached = NULL;
- std::string texture;
std::string playername;
- u8 glow = 0;
if (lua_gettop(L) > 1) //deprecated
{
- log_deprecated(L,"Deprecated add_particlespawner call with individual parameters instead of definition");
- amount = luaL_checknumber(L, 1);
- time = luaL_checknumber(L, 2);
- minpos = check_v3f(L, 3);
- maxpos = check_v3f(L, 4);
- minvel = check_v3f(L, 5);
- maxvel = check_v3f(L, 6);
- minacc = check_v3f(L, 7);
- maxacc = check_v3f(L, 8);
- minexptime = luaL_checknumber(L, 9);
- maxexptime = luaL_checknumber(L, 10);
- minsize = luaL_checknumber(L, 11);
- maxsize = luaL_checknumber(L, 12);
- collisiondetection = readParam<bool>(L, 13);
- texture = luaL_checkstring(L, 14);
+ log_deprecated(L, "Deprecated add_particlespawner call with "
+ "individual parameters instead of definition");
+ p.amount = luaL_checknumber(L, 1);
+ p.time = luaL_checknumber(L, 2);
+ p.minpos = check_v3f(L, 3);
+ p.maxpos = check_v3f(L, 4);
+ p.minvel = check_v3f(L, 5);
+ p.maxvel = check_v3f(L, 6);
+ p.minacc = check_v3f(L, 7);
+ p.maxacc = check_v3f(L, 8);
+ p.minexptime = luaL_checknumber(L, 9);
+ p.maxexptime = luaL_checknumber(L, 10);
+ p.minsize = luaL_checknumber(L, 11);
+ p.maxsize = luaL_checknumber(L, 12);
+ p.collisiondetection = readParam<bool>(L, 13);
+ p.texture = luaL_checkstring(L, 14);
if (lua_gettop(L) == 15) // only spawn for a single player
playername = luaL_checkstring(L, 15);
}
else if (lua_istable(L, 1))
{
- amount = getintfield_default(L, 1, "amount", amount);
- time = getfloatfield_default(L, 1, "time", time);
+ p.amount = getintfield_default(L, 1, "amount", p.amount);
+ p.time = getfloatfield_default(L, 1, "time", p.time);
lua_getfield(L, 1, "minpos");
- minpos = lua_istable(L, -1) ? check_v3f(L, -1) : minpos;
+ if (lua_istable(L, -1))
+ p.minpos = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "maxpos");
- maxpos = lua_istable(L, -1) ? check_v3f(L, -1) : maxpos;
+ if (lua_istable(L, -1))
+ p.maxpos = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "minvel");
- minvel = lua_istable(L, -1) ? check_v3f(L, -1) : minvel;
+ if (lua_istable(L, -1))
+ p.minvel = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "maxvel");
- maxvel = lua_istable(L, -1) ? check_v3f(L, -1) : maxvel;
+ if (lua_istable(L, -1))
+ p.maxvel = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "minacc");
- minacc = lua_istable(L, -1) ? check_v3f(L, -1) : minacc;
+ if (lua_istable(L, -1))
+ p.minacc = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "maxacc");
- maxacc = lua_istable(L, -1) ? check_v3f(L, -1) : maxacc;
+ if (lua_istable(L, -1))
+ p.maxacc = check_v3f(L, -1);
lua_pop(L, 1);
- minexptime = getfloatfield_default(L, 1, "minexptime", minexptime);
- maxexptime = getfloatfield_default(L, 1, "maxexptime", maxexptime);
- minsize = getfloatfield_default(L, 1, "minsize", minsize);
- maxsize = getfloatfield_default(L, 1, "maxsize", maxsize);
- collisiondetection = getboolfield_default(L, 1,
- "collisiondetection", collisiondetection);
- collision_removal = getboolfield_default(L, 1,
- "collision_removal", collision_removal);
- object_collision = getboolfield_default(L, 1,
- "object_collision", object_collision);
+ p.minexptime = getfloatfield_default(L, 1, "minexptime", p.minexptime);
+ p.maxexptime = getfloatfield_default(L, 1, "maxexptime", p.maxexptime);
+ p.minsize = getfloatfield_default(L, 1, "minsize", p.minsize);
+ p.maxsize = getfloatfield_default(L, 1, "maxsize", p.maxsize);
+ p.collisiondetection = getboolfield_default(L, 1,
+ "collisiondetection", p.collisiondetection);
+ p.collision_removal = getboolfield_default(L, 1,
+ "collision_removal", p.collision_removal);
+ p.object_collision = getboolfield_default(L, 1,
+ "object_collision", p.object_collision);
lua_getfield(L, 1, "animation");
- animation = read_animation_definition(L, -1);
+ p.animation = read_animation_definition(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "attached");
@@ -233,25 +234,20 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
attached = ObjectRef::getobject(ref);
}
- vertical = getboolfield_default(L, 1, "vertical", vertical);
- texture = getstringfield_default(L, 1, "texture", "");
+ p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
+ p.texture = getstringfield_default(L, 1, "texture", p.texture);
playername = getstringfield_default(L, 1, "playername", "");
- glow = getintfield_default(L, 1, "glow", 0);
+ p.glow = getintfield_default(L, 1, "glow", p.glow);
+
+ lua_getfield(L, 1, "node");
+ if (lua_istable(L, -1))
+ p.node = readnode(L, -1, getGameDef(L)->ndef());
+ lua_pop(L, 1);
+
+ p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
}
- u32 id = getServer(L)->addParticleSpawner(amount, time,
- minpos, maxpos,
- minvel, maxvel,
- minacc, maxacc,
- minexptime, maxexptime,
- minsize, maxsize,
- collisiondetection,
- collision_removal,
- object_collision,
- attached,
- vertical,
- texture, playername,
- animation, glow);
+ u32 id = getServer(L)->addParticleSpawner(p, attached, playername);
lua_pushnumber(L, id);
return 1;
@@ -261,7 +257,7 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
// player (string) is optional
int ModApiParticles::l_delete_particlespawner(lua_State *L)
{
- MAP_LOCK_REQUIRED;
+ NO_MAP_LOCK_REQUIRED;
// Get parameters
u32 id = luaL_checknumber(L, 1);
diff --git a/src/script/lua_api/l_particles_local.cpp b/src/script/lua_api/l_particles_local.cpp
index a9bf55665..cc68b13a5 100644
--- a/src/script/lua_api/l_particles_local.cpp
+++ b/src/script/lua_api/l_particles_local.cpp
@@ -32,56 +32,51 @@ int ModApiParticlesLocal::l_add_particle(lua_State *L)
luaL_checktype(L, 1, LUA_TTABLE);
// Get parameters
- v3f pos, vel, acc;
- float expirationtime, size;
- bool collisiondetection, vertical, collision_removal;
-
- struct TileAnimationParams animation;
- animation.type = TAT_NONE;
-
- std::string texture;
-
- u8 glow;
+ ParticleParameters p;
lua_getfield(L, 1, "pos");
- pos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+ if (lua_istable(L, -1))
+ p.pos = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "velocity");
- vel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+ if (lua_istable(L, -1))
+ p.vel = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "acceleration");
- acc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+ if (lua_istable(L, -1))
+ p.acc = check_v3f(L, -1);
lua_pop(L, 1);
- expirationtime = getfloatfield_default(L, 1, "expirationtime", 1);
- size = getfloatfield_default(L, 1, "size", 1);
- collisiondetection = getboolfield_default(L, 1, "collisiondetection", false);
- collision_removal = getboolfield_default(L, 1, "collision_removal", false);
- vertical = getboolfield_default(L, 1, "vertical", false);
+ p.expirationtime = getfloatfield_default(L, 1, "expirationtime",
+ p.expirationtime);
+ p.size = getfloatfield_default(L, 1, "size", p.size);
+ p.collisiondetection = getboolfield_default(L, 1,
+ "collisiondetection", p.collisiondetection);
+ p.collision_removal = getboolfield_default(L, 1,
+ "collision_removal", p.collision_removal);
+ p.object_collision = getboolfield_default(L, 1,
+ "object_collision", p.object_collision);
+ p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
lua_getfield(L, 1, "animation");
- animation = read_animation_definition(L, -1);
+ p.animation = read_animation_definition(L, -1);
lua_pop(L, 1);
- texture = getstringfield_default(L, 1, "texture", "");
+ p.texture = getstringfield_default(L, 1, "texture", p.texture);
+ p.glow = getintfield_default(L, 1, "glow", p.glow);
+
+ lua_getfield(L, 1, "node");
+ if (lua_istable(L, -1))
+ p.node = readnode(L, -1, getGameDef(L)->ndef());
+ lua_pop(L, 1);
- glow = getintfield_default(L, 1, "glow", 0);
+ p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
ClientEvent *event = new ClientEvent();
- event->type = CE_SPAWN_PARTICLE;
- event->spawn_particle.pos = new v3f (pos);
- event->spawn_particle.vel = new v3f (vel);
- event->spawn_particle.acc = new v3f (acc);
- event->spawn_particle.expirationtime = expirationtime;
- event->spawn_particle.size = size;
- event->spawn_particle.collisiondetection = collisiondetection;
- event->spawn_particle.collision_removal = collision_removal;
- event->spawn_particle.vertical = vertical;
- event->spawn_particle.texture = new std::string(texture);
- event->spawn_particle.animation = animation;
- event->spawn_particle.glow = glow;
+ event->type = CE_SPAWN_PARTICLE;
+ event->spawn_particle = new ParticleParameters(p);
getClient(L)->pushToEventQueue(event);
return 0;
@@ -90,94 +85,76 @@ int ModApiParticlesLocal::l_add_particle(lua_State *L)
int ModApiParticlesLocal::l_add_particlespawner(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);
- // Get parameters
- u16 amount;
- v3f minpos, maxpos, minvel, maxvel, minacc, maxacc;
- float time, minexptime, maxexptime, minsize, maxsize;
- bool collisiondetection, vertical, collision_removal;
- struct TileAnimationParams animation;
- animation.type = TAT_NONE;
- // TODO: Implement this when there is a way to get an objectref.
- // ServerActiveObject *attached = NULL;
- std::string texture;
- u8 glow;
+ // Get parameters
+ ParticleSpawnerParameters p;
- amount = getintfield_default(L, 1, "amount", 1);
- time = getfloatfield_default(L, 1, "time", 1);
+ p.amount = getintfield_default(L, 1, "amount", p.amount);
+ p.time = getfloatfield_default(L, 1, "time", p.time);
lua_getfield(L, 1, "minpos");
- minpos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+ if (lua_istable(L, -1))
+ p.minpos = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "maxpos");
- maxpos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+ if (lua_istable(L, -1))
+ p.maxpos = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "minvel");
- minvel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+ if (lua_istable(L, -1))
+ p.minvel = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "maxvel");
- maxvel = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+ if (lua_istable(L, -1))
+ p.maxvel = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "minacc");
- minacc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+ if (lua_istable(L, -1))
+ p.minacc = check_v3f(L, -1);
lua_pop(L, 1);
lua_getfield(L, 1, "maxacc");
- maxacc = lua_istable(L, -1) ? check_v3f(L, -1) : v3f(0, 0, 0);
+ if (lua_istable(L, -1))
+ p.maxacc = check_v3f(L, -1);
lua_pop(L, 1);
- minexptime = getfloatfield_default(L, 1, "minexptime", 1);
- maxexptime = getfloatfield_default(L, 1, "maxexptime", 1);
- minsize = getfloatfield_default(L, 1, "minsize", 1);
- maxsize = getfloatfield_default(L, 1, "maxsize", 1);
-
- collisiondetection = getboolfield_default(L, 1, "collisiondetection", false);
- collision_removal = getboolfield_default(L, 1, "collision_removal", false);
- vertical = getboolfield_default(L, 1, "vertical", false);
+ p.minexptime = getfloatfield_default(L, 1, "minexptime", p.minexptime);
+ p.maxexptime = getfloatfield_default(L, 1, "maxexptime", p.maxexptime);
+ p.minsize = getfloatfield_default(L, 1, "minsize", p.minsize);
+ p.maxsize = getfloatfield_default(L, 1, "maxsize", p.maxsize);
+ p.collisiondetection = getboolfield_default(L, 1,
+ "collisiondetection", p.collisiondetection);
+ p.collision_removal = getboolfield_default(L, 1,
+ "collision_removal", p.collision_removal);
+ p.object_collision = getboolfield_default(L, 1,
+ "object_collision", p.object_collision);
lua_getfield(L, 1, "animation");
- animation = read_animation_definition(L, -1);
+ p.animation = read_animation_definition(L, -1);
lua_pop(L, 1);
- // TODO: Implement this when a way to get an objectref on the client is added
-// lua_getfield(L, 1, "attached");
-// if (!lua_isnil(L, -1)) {
-// ObjectRef *ref = ObjectRef::checkobject(L, -1);
-// lua_pop(L, 1);
-// attached = ObjectRef::getobject(ref);
-// }
+ p.vertical = getboolfield_default(L, 1, "vertical", p.vertical);
+ p.texture = getstringfield_default(L, 1, "texture", p.texture);
+ p.glow = getintfield_default(L, 1, "glow", p.glow);
+
+ lua_getfield(L, 1, "node");
+ if (lua_istable(L, -1))
+ p.node = readnode(L, -1, getGameDef(L)->ndef());
+ lua_pop(L, 1);
- texture = getstringfield_default(L, 1, "texture", "");
- glow = getintfield_default(L, 1, "glow", 0);
+ p.node_tile = getintfield_default(L, 1, "node_tile", p.node_tile);
u64 id = getClient(L)->getParticleManager()->generateSpawnerId();
auto event = new ClientEvent();
- event->type = CE_ADD_PARTICLESPAWNER;
- event->add_particlespawner.amount = amount;
- event->add_particlespawner.spawntime = time;
- event->add_particlespawner.minpos = new v3f (minpos);
- event->add_particlespawner.maxpos = new v3f (maxpos);
- event->add_particlespawner.minvel = new v3f (minvel);
- event->add_particlespawner.maxvel = new v3f (maxvel);
- event->add_particlespawner.minacc = new v3f (minacc);
- event->add_particlespawner.maxacc = new v3f (maxacc);
- event->add_particlespawner.minexptime = minexptime;
- event->add_particlespawner.maxexptime = maxexptime;
- event->add_particlespawner.minsize = minsize;
- event->add_particlespawner.maxsize = maxsize;
- event->add_particlespawner.collisiondetection = collisiondetection;
- event->add_particlespawner.collision_removal = collision_removal;
- event->add_particlespawner.attached_id = 0;
- event->add_particlespawner.vertical = vertical;
- event->add_particlespawner.texture = new std::string(texture);
- event->add_particlespawner.id = id;
- event->add_particlespawner.animation = animation;
- event->add_particlespawner.glow = glow;
+ event->type = CE_ADD_PARTICLESPAWNER;
+ event->add_particlespawner.p = new ParticleSpawnerParameters(p);
+ event->add_particlespawner.attached_id = 0;
+ event->add_particlespawner.id = id;
getClient(L)->pushToEventQueue(event);
lua_pushnumber(L, id);
diff --git a/src/script/lua_api/l_particles_local.h b/src/script/lua_api/l_particles_local.h
index 5dff153b3..d8bb2b1c6 100644
--- a/src/script/lua_api/l_particles_local.h
+++ b/src/script/lua_api/l_particles_local.h
@@ -18,6 +18,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#pragma once
+
#include "lua_api/l_base.h"
class ModApiParticlesLocal : public ModApiBase
diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp
index 00e849cdf..6f934bb9d 100644
--- a/src/script/lua_api/l_server.cpp
+++ b/src/script/lua_api/l_server.cpp
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_converter.h"
#include "common/c_content.h"
#include "cpp_api/s_base.h"
+#include "cpp_api/s_security.h"
#include "server.h"
#include "environment.h"
#include "remoteplayer.h"
@@ -138,52 +139,54 @@ int ModApiServer::l_get_player_ip(lua_State *L)
// get_player_information(name)
int ModApiServer::l_get_player_information(lua_State *L)
{
-
NO_MAP_LOCK_REQUIRED;
- const char * name = luaL_checkstring(L, 1);
- RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
- if (player == NULL) {
+
+ Server *server = getServer(L);
+
+ const char *name = luaL_checkstring(L, 1);
+ RemotePlayer *player = server->getEnv().getPlayer(name);
+ if (!player) {
lua_pushnil(L); // no such player
return 1;
}
Address addr;
- try
- {
- addr = getServer(L)->getPeerAddress(player->getPeerId());
- } catch(const con::PeerNotFoundException &) {
+ try {
+ addr = server->getPeerAddress(player->getPeerId());
+ } catch (const con::PeerNotFoundException &) {
dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
lua_pushnil(L); // error
return 1;
}
- float min_rtt,max_rtt,avg_rtt,min_jitter,max_jitter,avg_jitter;
+ float min_rtt, max_rtt, avg_rtt, min_jitter, max_jitter, avg_jitter;
ClientState state;
u32 uptime;
u16 prot_vers;
- u8 ser_vers,major,minor,patch;
- std::string vers_string;
-
-#define ERET(code) \
- if (!(code)) { \
- dstream << FUNCTION_NAME << ": peer was not found" << std::endl; \
- lua_pushnil(L); /* error */ \
- return 1; \
+ u8 ser_vers, major, minor, patch;
+ std::string vers_string, lang_code;
+
+ auto getConInfo = [&] (con::rtt_stat_type type, float *value) -> bool {
+ return server->getClientConInfo(player->getPeerId(), type, value);
+ };
+
+ bool have_con_info =
+ getConInfo(con::MIN_RTT, &min_rtt) &&
+ getConInfo(con::MAX_RTT, &max_rtt) &&
+ getConInfo(con::AVG_RTT, &avg_rtt) &&
+ getConInfo(con::MIN_JITTER, &min_jitter) &&
+ getConInfo(con::MAX_JITTER, &max_jitter) &&
+ getConInfo(con::AVG_JITTER, &avg_jitter);
+
+ bool r = server->getClientInfo(player->getPeerId(), &state, &uptime,
+ &ser_vers, &prot_vers, &major, &minor, &patch, &vers_string,
+ &lang_code);
+ if (!r) {
+ dstream << FUNCTION_NAME << ": peer was not found" << std::endl;
+ lua_pushnil(L); // error
+ return 1;
}
- ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::MIN_RTT, &min_rtt))
- ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::MAX_RTT, &max_rtt))
- ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::AVG_RTT, &avg_rtt))
- ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::MIN_JITTER,
- &min_jitter))
- ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::MAX_JITTER,
- &max_jitter))
- ERET(getServer(L)->getClientConInfo(player->getPeerId(), con::AVG_JITTER,
- &avg_jitter))
-
- ERET(getServer(L)->getClientInfo(player->getPeerId(), &state, &uptime, &ser_vers,
- &prot_vers, &major, &minor, &patch, &vers_string))
-
lua_newtable(L);
int table = lua_gettop(L);
@@ -201,29 +204,31 @@ int ModApiServer::l_get_player_information(lua_State *L)
}
lua_settable(L, table);
- lua_pushstring(L,"min_rtt");
- lua_pushnumber(L, min_rtt);
- lua_settable(L, table);
+ if (have_con_info) { // may be missing
+ lua_pushstring(L, "min_rtt");
+ lua_pushnumber(L, min_rtt);
+ lua_settable(L, table);
- lua_pushstring(L,"max_rtt");
- lua_pushnumber(L, max_rtt);
- lua_settable(L, table);
+ lua_pushstring(L, "max_rtt");
+ lua_pushnumber(L, max_rtt);
+ lua_settable(L, table);
- lua_pushstring(L,"avg_rtt");
- lua_pushnumber(L, avg_rtt);
- lua_settable(L, table);
+ lua_pushstring(L, "avg_rtt");
+ lua_pushnumber(L, avg_rtt);
+ lua_settable(L, table);
- lua_pushstring(L,"min_jitter");
- lua_pushnumber(L, min_jitter);
- lua_settable(L, table);
+ lua_pushstring(L, "min_jitter");
+ lua_pushnumber(L, min_jitter);
+ lua_settable(L, table);
- lua_pushstring(L,"max_jitter");
- lua_pushnumber(L, max_jitter);
- lua_settable(L, table);
+ lua_pushstring(L, "max_jitter");
+ lua_pushnumber(L, max_jitter);
+ lua_settable(L, table);
- lua_pushstring(L,"avg_jitter");
- lua_pushnumber(L, avg_jitter);
- lua_settable(L, table);
+ lua_pushstring(L, "avg_jitter");
+ lua_pushnumber(L, avg_jitter);
+ lua_settable(L, table);
+ }
lua_pushstring(L,"connection_uptime");
lua_pushnumber(L, uptime);
@@ -237,6 +242,10 @@ int ModApiServer::l_get_player_information(lua_State *L)
lua_pushnumber(L, player->formspec_version);
lua_settable(L, table);
+ lua_pushstring(L, "lang_code");
+ lua_pushstring(L, lang_code.c_str());
+ lua_settable(L, table);
+
#ifndef NDEBUG
lua_pushstring(L,"serialization_version");
lua_pushnumber(L, ser_vers);
@@ -263,7 +272,6 @@ int ModApiServer::l_get_player_information(lua_State *L)
lua_settable(L, table);
#endif
-#undef ERET
return 1;
}
@@ -405,9 +413,6 @@ int ModApiServer::l_get_modnames(lua_State *L)
std::vector<std::string> modlist;
getServer(L)->getModNames(modlist);
- // Take unsorted items from mods_unsorted and sort them into
- // mods_sorted; not great performance but the number of mods on a
- // server will likely be small.
std::sort(modlist.begin(), modlist.end());
// Package them up for Lua
@@ -467,6 +472,23 @@ int ModApiServer::l_sound_fade(lua_State *L)
return 0;
}
+// dynamic_add_media(filepath)
+int ModApiServer::l_dynamic_add_media(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ // Reject adding media before the server has started up
+ if (!getEnv(L))
+ throw LuaError("Dynamic media cannot be added before server has started up");
+
+ std::string filepath = readParam<std::string>(L, 1);
+ CHECK_SECURE_PATH(L, filepath.c_str(), false);
+
+ bool ok = getServer(L)->dynamicAddMedia(filepath);
+ lua_pushboolean(L, ok);
+ return 1;
+}
+
// is_singleplayer()
int ModApiServer::l_is_singleplayer(lua_State *L)
{
@@ -531,6 +553,7 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(sound_play);
API_FCT(sound_stop);
API_FCT(sound_fade);
+ API_FCT(dynamic_add_media);
API_FCT(get_player_information);
API_FCT(get_player_privs);
diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h
index 3aa1785a2..938bfa8ef 100644
--- a/src/script/lua_api/l_server.h
+++ b/src/script/lua_api/l_server.h
@@ -70,6 +70,9 @@ private:
// sound_fade(handle, step, gain)
static int l_sound_fade(lua_State *L);
+ // dynamic_add_media(filepath)
+ static int l_dynamic_add_media(lua_State *L);
+
// get_player_privs(name, text)
static int l_get_player_privs(lua_State *L);
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index ae3e5df3d..cd63e20c2 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -44,7 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
// log([level,] text)
// Writes a line to the logger.
-// The one-argument version logs to infostream.
+// The one-argument version logs to LL_NONE.
// The two-argument version accepts a log level.
// Either the special case "deprecated" for deprecation notices, or any specified in
// Logger::stringToLevel(name).
@@ -318,9 +318,13 @@ int ModApiUtil::l_decode_base64(lua_State *L)
NO_MAP_LOCK_REQUIRED;
size_t size;
- const char *data = luaL_checklstring(L, 1, &size);
+ const char *d = luaL_checklstring(L, 1, &size);
+ const std::string data = std::string(d, size);
+
+ if (!base64_is_valid(data))
+ return 0;
- std::string out = base64_decode(std::string(data, size));
+ std::string out = base64_decode(data);
lua_pushlstring(L, out.data(), out.size());
return 1;
diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h
index 5697aab15..9ff91bb53 100644
--- a/src/script/lua_api/l_util.h
+++ b/src/script/lua_api/l_util.h
@@ -37,7 +37,7 @@ private:
// log([level,] text)
// Writes a line to the logger.
- // The one-argument version logs to infostream.
+ // The one-argument version logs to LL_NONE.
// The two-argument version accepts a log level.
static int l_log(lua_State *L);
diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp
index fd73d21d1..b99b1d98c 100644
--- a/src/script/lua_api/l_vmanip.cpp
+++ b/src/script/lua_api/l_vmanip.cpp
@@ -72,7 +72,7 @@ int LuaVoxelManip::l_get_data(lua_State *L)
if (use_buffer)
lua_pushvalue(L, 2);
else
- lua_newtable(L);
+ lua_createtable(L, volume, 0);
for (u32 i = 0; i != volume; i++) {
lua_Integer cid = vm->m_data[i].getContent();
@@ -261,7 +261,7 @@ int LuaVoxelManip::l_get_light_data(lua_State *L)
u32 volume = vm->m_area.getVolume();
- lua_newtable(L);
+ lua_createtable(L, volume, 0);
for (u32 i = 0; i != volume; i++) {
lua_Integer light = vm->m_data[i].param1;
lua_pushinteger(L, light);
@@ -309,7 +309,7 @@ int LuaVoxelManip::l_get_param2_data(lua_State *L)
if (use_buffer)
lua_pushvalue(L, 2);
else
- lua_newtable(L);
+ lua_createtable(L, volume, 0);
for (u32 i = 0; i != volume; i++) {
lua_Integer param2 = vm->m_data[i].param2;
diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp
index 1288b1df7..6643a9509 100644
--- a/src/script/scripting_client.cpp
+++ b/src/script/scripting_client.cpp
@@ -55,9 +55,6 @@ ClientScripting::ClientScripting(Client *client):
InitializeModApi(L, top);
lua_pop(L, 1);
- if (client->getMinimap())
- LuaMinimap::create(L, client->getMinimap());
-
// Push builtin initialization type
lua_pushstring(L, "client");
lua_setglobal(L, "INIT");
@@ -94,3 +91,8 @@ void ClientScripting::on_camera_ready(Camera *camera)
{
LuaCamera::create(getStack(), camera);
}
+
+void ClientScripting::on_minimap_ready(Minimap *minimap)
+{
+ LuaMinimap::create(getStack(), minimap);
+}
diff --git a/src/script/scripting_client.h b/src/script/scripting_client.h
index cfecfa165..3088029f0 100644
--- a/src/script/scripting_client.h
+++ b/src/script/scripting_client.h
@@ -28,6 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class Client;
class LocalPlayer;
class Camera;
+class Minimap;
+
class ClientScripting:
virtual public ScriptApiBase,
public ScriptApiSecurity,
@@ -38,6 +40,7 @@ public:
ClientScripting(Client *client);
void on_client_ready(LocalPlayer *localplayer);
void on_camera_ready(Camera *camera);
+ void on_minimap_ready(Minimap *minimap);
private:
virtual void InitializeModApi(lua_State *L, int top);
diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp
index b6068439a..0f672f917 100644
--- a/src/script/scripting_mainmenu.cpp
+++ b/src/script/scripting_mainmenu.cpp
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content/mods.h"
#include "cpp_api/s_internal.h"
#include "lua_api/l_base.h"
+#include "lua_api/l_http.h"
#include "lua_api/l_mainmenu.h"
#include "lua_api/l_sound.h"
#include "lua_api/l_util.h"
@@ -67,10 +68,12 @@ void MainMenuScripting::initializeModApi(lua_State *L, int top)
ModApiMainMenu::Initialize(L, top);
ModApiUtil::Initialize(L, top);
ModApiSound::Initialize(L, top);
+ ModApiHttp::Initialize(L, top);
asyncEngine.registerStateInitializer(registerLuaClasses);
asyncEngine.registerStateInitializer(ModApiMainMenu::InitializeAsync);
asyncEngine.registerStateInitializer(ModApiUtil::InitializeAsync);
+ asyncEngine.registerStateInitializer(ModApiHttp::InitializeAsync);
// Initialize async environment
//TODO possibly make number of async threads configurable
diff --git a/src/script/scripting_server.cpp b/src/script/scripting_server.cpp
index cbf229640..85411ded4 100644
--- a/src/script/scripting_server.cpp
+++ b/src/script/scripting_server.cpp
@@ -62,6 +62,10 @@ ServerScripting::ServerScripting(Server* server):
if (g_settings->getBool("secure.enable_security")) {
initializeSecurity();
+ } else {
+ warningstream << "\\!/ Mod security should never be disabled, as it allows any mod to "
+ << "access the host machine."
+ << "Mods should use minetest.request_insecure_environment() instead \\!/" << std::endl;
}
lua_getglobal(L, "core");