summaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/CMakeLists.txt7
-rw-r--r--src/script/common/c_content.cpp472
-rw-r--r--src/script/common/c_content.h35
-rw-r--r--src/script/common/c_converter.cpp4
-rw-r--r--src/script/common/c_converter.h2
-rw-r--r--src/script/cpp_api/CMakeLists.txt1
-rw-r--r--src/script/cpp_api/s_async.cpp33
-rw-r--r--src/script/cpp_api/s_async.h25
-rw-r--r--src/script/cpp_api/s_base.cpp45
-rw-r--r--src/script/cpp_api/s_base.h17
-rw-r--r--src/script/cpp_api/s_client.cpp230
-rw-r--r--src/script/cpp_api/s_client.h63
-rw-r--r--src/script/cpp_api/s_entity.cpp22
-rw-r--r--src/script/cpp_api/s_entity.h4
-rw-r--r--src/script/cpp_api/s_env.cpp12
-rw-r--r--src/script/cpp_api/s_item.cpp35
-rw-r--r--src/script/cpp_api/s_mainmenu.cpp8
-rw-r--r--src/script/cpp_api/s_node.cpp27
-rw-r--r--src/script/cpp_api/s_node.h1
-rw-r--r--src/script/cpp_api/s_player.h14
-rw-r--r--src/script/cpp_api/s_security.cpp187
-rw-r--r--src/script/cpp_api/s_security.h2
-rw-r--r--src/script/lua_api/CMakeLists.txt10
-rw-r--r--src/script/lua_api/l_areastore.cpp4
-rw-r--r--src/script/lua_api/l_areastore.h7
-rw-r--r--src/script/lua_api/l_base.cpp26
-rw-r--r--src/script/lua_api/l_base.h16
-rw-r--r--src/script/lua_api/l_camera.cpp202
-rw-r--r--src/script/lua_api/l_camera.h44
-rw-r--r--src/script/lua_api/l_client.cpp356
-rw-r--r--src/script/lua_api/l_client.h98
-rw-r--r--src/script/lua_api/l_craft.cpp2
-rw-r--r--src/script/lua_api/l_env.cpp109
-rw-r--r--src/script/lua_api/l_env.h14
-rw-r--r--src/script/lua_api/l_internal.h14
-rw-r--r--src/script/lua_api/l_inventory.cpp12
-rw-r--r--src/script/lua_api/l_inventory.h2
-rw-r--r--src/script/lua_api/l_item.cpp66
-rw-r--r--src/script/lua_api/l_item.h7
-rw-r--r--src/script/lua_api/l_itemstackmeta.cpp120
-rw-r--r--src/script/lua_api/l_itemstackmeta.h59
-rw-r--r--src/script/lua_api/l_localplayer.cpp358
-rw-r--r--src/script/lua_api/l_localplayer.h85
-rw-r--r--src/script/lua_api/l_mainmenu.cpp76
-rw-r--r--src/script/lua_api/l_mainmenu.h10
-rw-r--r--src/script/lua_api/l_mapgen.cpp20
-rw-r--r--src/script/lua_api/l_mapgen.h3
-rw-r--r--src/script/lua_api/l_metadata.cpp266
-rw-r--r--src/script/lua_api/l_metadata.h75
-rw-r--r--src/script/lua_api/l_minimap.cpp227
-rw-r--r--src/script/lua_api/l_minimap.h65
-rw-r--r--src/script/lua_api/l_nodemeta.cpp330
-rw-r--r--src/script/lua_api/l_nodemeta.h48
-rw-r--r--src/script/lua_api/l_nodetimer.cpp4
-rw-r--r--src/script/lua_api/l_nodetimer.h9
-rw-r--r--src/script/lua_api/l_noise.cpp10
-rw-r--r--src/script/lua_api/l_noise.h37
-rw-r--r--src/script/lua_api/l_object.cpp271
-rw-r--r--src/script/lua_api/l_object.h67
-rw-r--r--src/script/lua_api/l_particles.cpp29
-rw-r--r--src/script/lua_api/l_server.cpp79
-rw-r--r--src/script/lua_api/l_server.h17
-rw-r--r--src/script/lua_api/l_settings.cpp85
-rw-r--r--src/script/lua_api/l_settings.h43
-rw-r--r--src/script/lua_api/l_sound.cpp53
-rw-r--r--src/script/lua_api/l_sound.h36
-rw-r--r--src/script/lua_api/l_storage.cpp147
-rw-r--r--src/script/lua_api/l_storage.h63
-rw-r--r--src/script/lua_api/l_util.cpp137
-rw-r--r--src/script/lua_api/l_util.h24
-rw-r--r--src/script/lua_api/l_vmanip.cpp49
-rw-r--r--src/script/lua_api/l_vmanip.h9
-rw-r--r--src/script/scripting_client.cpp88
-rw-r--r--src/script/scripting_client.h46
-rw-r--r--src/script/scripting_mainmenu.cpp29
-rw-r--r--src/script/scripting_mainmenu.h7
-rw-r--r--src/script/scripting_server.cpp (renamed from src/script/scripting_game.cpp)37
-rw-r--r--src/script/scripting_server.h (renamed from src/script/scripting_game.h)12
78 files changed, 4418 insertions, 947 deletions
diff --git a/src/script/CMakeLists.txt b/src/script/CMakeLists.txt
index 5ef672ca9..bebe2f037 100644
--- a/src/script/CMakeLists.txt
+++ b/src/script/CMakeLists.txt
@@ -3,16 +3,17 @@ add_subdirectory(cpp_api)
add_subdirectory(lua_api)
# Used by server and client
-set(common_SCRIPT_SRCS
- ${CMAKE_CURRENT_SOURCE_DIR}/scripting_game.cpp
+set(common_SCRIPT_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/scripting_server.cpp
${common_SCRIPT_COMMON_SRCS}
${common_SCRIPT_CPP_API_SRCS}
${common_SCRIPT_LUA_API_SRCS}
PARENT_SCOPE)
# Used by client only
-set(client_SCRIPT_SRCS
+set(client_SCRIPT_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/scripting_mainmenu.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/scripting_client.cpp
${client_SCRIPT_COMMON_SRCS}
${client_SCRIPT_CPP_API_SRCS}
${client_SCRIPT_LUA_API_SRCS}
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index 541744895..c0e29abf0 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_converter.h"
#include "common/c_types.h"
#include "nodedef.h"
-#include "itemdef.h"
#include "object_properties.h"
#include "cpp_api/s_node.h"
#include "lua_api/l_object.h"
@@ -33,31 +32,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h"
#include "mg_schematic.h"
#include "noise.h"
+#include "util/pointedthing.h"
+#include "debug.h" // For FATAL_ERROR
#include <json/json.h>
struct EnumString es_TileAnimationType[] =
{
{TAT_NONE, "none"},
{TAT_VERTICAL_FRAMES, "vertical_frames"},
+ {TAT_SHEET_2D, "sheet_2d"},
{0, NULL},
};
/******************************************************************************/
-ItemDefinition read_item_definition(lua_State* L,int index,
- ItemDefinition default_def)
+void read_item_definition(lua_State* L, int index,
+ const ItemDefinition &default_def, ItemDefinition &def)
{
- if(index < 0)
+ if (index < 0)
index = lua_gettop(L) + 1 + index;
- // Read the item definition
- ItemDefinition def = default_def;
-
def.type = (ItemType)getenumfield(L, index, "type",
es_ItemType, ITEM_NONE);
getstringfield(L, index, "name", def.name);
getstringfield(L, index, "description", def.description);
getstringfield(L, index, "inventory_image", def.inventory_image);
getstringfield(L, index, "wield_image", def.wield_image);
+ getstringfield(L, index, "palette", def.palette_image);
+
+ // Read item color.
+ lua_getfield(L, index, "color");
+ read_color(L, -1, &def.color);
+ lua_pop(L, 1);
lua_getfield(L, index, "wield_scale");
if(lua_istable(L, -1)){
@@ -112,13 +117,66 @@ ItemDefinition read_item_definition(lua_State* L,int index,
// "" = no prediction
getstringfield(L, index, "node_placement_prediction",
def.node_placement_prediction);
+}
+
+/******************************************************************************/
+void push_item_definition(lua_State *L, const ItemDefinition &i)
+{
+ lua_newtable(L);
+ lua_pushstring(L, i.name.c_str());
+ lua_setfield(L, -2, "name");
+ lua_pushstring(L, i.description.c_str());
+ lua_setfield(L, -2, "description");
+}
- return def;
+void push_item_definition_full(lua_State *L, const ItemDefinition &i)
+{
+ std::string type(es_ItemType[(int)i.type].str);
+
+ lua_newtable(L);
+ lua_pushstring(L, i.name.c_str());
+ lua_setfield(L, -2, "name");
+ lua_pushstring(L, i.description.c_str());
+ lua_setfield(L, -2, "description");
+ lua_pushstring(L, type.c_str());
+ lua_setfield(L, -2, "type");
+ lua_pushstring(L, i.inventory_image.c_str());
+ lua_setfield(L, -2, "inventory_image");
+ lua_pushstring(L, i.wield_image.c_str());
+ lua_setfield(L, -2, "wield_image");
+ lua_pushstring(L, i.palette_image.c_str());
+ lua_setfield(L, -2, "palette_image");
+ push_ARGB8(L, i.color);
+ lua_setfield(L, -2, "color");
+ push_v3f(L, i.wield_scale);
+ lua_setfield(L, -2, "wield_scale");
+ lua_pushinteger(L, i.stack_max);
+ lua_setfield(L, -2, "stack_max");
+ lua_pushboolean(L, i.usable);
+ lua_setfield(L, -2, "usable");
+ lua_pushboolean(L, i.liquids_pointable);
+ lua_setfield(L, -2, "liquids_pointable");
+ if (i.type == ITEM_TOOL) {
+ push_tool_capabilities(L, ToolCapabilities(
+ i.tool_capabilities->full_punch_interval,
+ i.tool_capabilities->max_drop_level,
+ i.tool_capabilities->groupcaps,
+ i.tool_capabilities->damageGroups));
+ lua_setfield(L, -2, "tool_capabilities");
+ }
+ push_groups(L, i.groups);
+ lua_setfield(L, -2, "groups");
+ push_soundspec(L, i.sound_place);
+ lua_setfield(L, -2, "sound_place");
+ push_soundspec(L, i.sound_place_failed);
+ lua_setfield(L, -2, "sound_place_failed");
+ lua_pushstring(L, i.node_placement_prediction.c_str());
+ lua_setfield(L, -2, "node_placement_prediction");
}
/******************************************************************************/
void read_object_properties(lua_State *L, int index,
- ObjectProperties *prop)
+ ObjectProperties *prop, IItemDefManager *idef)
{
if(index < 0)
index = lua_gettop(L) + 1 + index;
@@ -216,6 +274,10 @@ void read_object_properties(lua_State *L, int index,
}
lua_pop(L, 1);
getstringfield(L, -1, "infotext", prop->infotext);
+ lua_getfield(L, -1, "wield_item");
+ if (!lua_isnil(L, -1))
+ prop->wield_item = read_item(L, -1, idef).getItemString();
+ lua_pop(L, 1);
}
/******************************************************************************/
@@ -284,6 +346,8 @@ void push_object_properties(lua_State *L, ObjectProperties *prop)
lua_setfield(L, -2, "automatic_face_movement_max_rotation_per_sec");
lua_pushlstring(L, prop->infotext.c_str(), prop->infotext.size());
lua_setfield(L, -2, "infotext");
+ lua_pushlstring(L, prop->wield_item.c_str(), prop->wield_item.size());
+ lua_setfield(L, -2, "wield_item");
}
/******************************************************************************/
@@ -321,7 +385,7 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype)
}
else if(lua_istable(L, index))
{
- // {name="default_lava.png", animation={}}
+ // name="default_lava.png"
tiledef.name = "";
getstringfield(L, index, "name", tiledef.name);
getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat.
@@ -331,20 +395,13 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype)
L, index, "tileable_horizontal", default_tiling);
tiledef.tileable_vertical = getboolfield_default(
L, index, "tileable_vertical", default_tiling);
+ // color = ...
+ lua_getfield(L, index, "color");
+ tiledef.has_color = read_color(L, -1, &tiledef.color);
+ lua_pop(L, 1);
// animation = {}
lua_getfield(L, index, "animation");
- if(lua_istable(L, -1)){
- // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
- tiledef.animation.type = (TileAnimationType)
- getenumfield(L, -1, "type", es_TileAnimationType,
- TAT_NONE);
- tiledef.animation.aspect_w =
- getintfield_default(L, -1, "aspect_w", 16);
- tiledef.animation.aspect_h =
- getintfield_default(L, -1, "aspect_h", 16);
- tiledef.animation.length =
- getfloatfield_default(L, -1, "length", 1.0);
- }
+ tiledef.animation = read_animation_definition(L, -1);
lua_pop(L, 1);
}
@@ -426,6 +483,34 @@ ContentFeatures read_content_features(lua_State *L, int index)
}
lua_pop(L, 1);
+ // overlay_tiles = {}
+ lua_getfield(L, index, "overlay_tiles");
+ if (lua_istable(L, -1)) {
+ int table = lua_gettop(L);
+ lua_pushnil(L);
+ int i = 0;
+ while (lua_next(L, table) != 0) {
+ // Read tiledef from value
+ f.tiledef_overlay[i] = read_tiledef(L, -1, f.drawtype);
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ i++;
+ if (i == 6) {
+ lua_pop(L, 1);
+ break;
+ }
+ }
+ // Copy last value to all remaining textures
+ if (i >= 1) {
+ TileDef lasttile = f.tiledef_overlay[i - 1];
+ while (i < 6) {
+ f.tiledef_overlay[i] = lasttile;
+ i++;
+ }
+ }
+ }
+ lua_pop(L, 1);
+
// special_tiles = {}
lua_getfield(L, index, "special_tiles");
// If nil, try the deprecated name "special_materials" instead
@@ -460,6 +545,13 @@ ContentFeatures read_content_features(lua_State *L, int index)
if (usealpha)
f.alpha = 0;
+ // Read node color.
+ lua_getfield(L, index, "color");
+ read_color(L, -1, &f.color);
+ lua_pop(L, 1);
+
+ getstringfield(L, index, "palette", f.palette_name);
+
/* Other stuff */
lua_getfield(L, index, "post_effect_color");
@@ -471,6 +563,13 @@ ContentFeatures read_content_features(lua_State *L, int index)
f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
ScriptApiNode::es_ContentParamType2, CPT2_NONE);
+ if (f.palette_name != "" &&
+ !(f.param_type_2 == CPT2_COLOR ||
+ f.param_type_2 == CPT2_COLORED_FACEDIR ||
+ f.param_type_2 == CPT2_COLORED_WALLMOUNTED))
+ warningstream << "Node " << f.name.c_str()
+ << " has a palette, but not a suitable paramtype2." << std::endl;
+
// Warn about some deprecated fields
warn_if_field_exists(L, index, "wall_mounted",
"Deprecated; use paramtype2 = 'wallmounted'");
@@ -616,6 +715,204 @@ ContentFeatures read_content_features(lua_State *L, int index)
return f;
}
+void push_content_features(lua_State *L, const ContentFeatures &c)
+{
+ std::string paramtype(ScriptApiNode::es_ContentParamType[(int)c.param_type].str);
+ std::string paramtype2(ScriptApiNode::es_ContentParamType2[(int)c.param_type_2].str);
+ std::string drawtype(ScriptApiNode::es_DrawType[(int)c.drawtype].str);
+ std::string liquid_type(ScriptApiNode::es_LiquidType[(int)c.liquid_type].str);
+
+ /* Missing "tiles" because I don't see a usecase (at least not yet). */
+
+ lua_newtable(L);
+ lua_pushboolean(L, c.has_on_construct);
+ lua_setfield(L, -2, "has_on_construct");
+ lua_pushboolean(L, c.has_on_destruct);
+ lua_setfield(L, -2, "has_on_destruct");
+ lua_pushboolean(L, c.has_after_destruct);
+ lua_setfield(L, -2, "has_after_destruct");
+ lua_pushstring(L, c.name.c_str());
+ lua_setfield(L, -2, "name");
+ push_groups(L, c.groups);
+ lua_setfield(L, -2, "groups");
+ lua_pushstring(L, paramtype.c_str());
+ lua_setfield(L, -2, "paramtype");
+ lua_pushstring(L, paramtype2.c_str());
+ lua_setfield(L, -2, "paramtype2");
+ lua_pushstring(L, drawtype.c_str());
+ lua_setfield(L, -2, "drawtype");
+ if (!c.mesh.empty()) {
+ lua_pushstring(L, c.mesh.c_str());
+ lua_setfield(L, -2, "mesh");
+ }
+#ifndef SERVER
+ push_ARGB8(L, c.minimap_color); // I know this is not set-able w/ register_node,
+ lua_setfield(L, -2, "minimap_color"); // but the people need to know!
+#endif
+ lua_pushnumber(L, c.visual_scale);
+ lua_setfield(L, -2, "visual_scale");
+ lua_pushnumber(L, c.alpha);
+ lua_setfield(L, -2, "alpha");
+ if (!c.palette_name.empty()) {
+ push_ARGB8(L, c.color);
+ lua_setfield(L, -2, "color");
+
+ lua_pushstring(L, c.palette_name.c_str());
+ lua_setfield(L, -2, "palette_name");
+
+ push_palette(L, c.palette);
+ lua_setfield(L, -2, "palette");
+ }
+ lua_pushnumber(L, c.waving);
+ lua_setfield(L, -2, "waving");
+ lua_pushnumber(L, c.connect_sides);
+ lua_setfield(L, -2, "connect_sides");
+
+ lua_newtable(L);
+ u16 i = 1;
+ for (std::vector<std::string>::const_iterator it = c.connects_to.begin();
+ it != c.connects_to.end(); ++it) {
+ lua_pushlstring(L, it->c_str(), it->size());
+ lua_rawseti(L, -2, i);
+ }
+ lua_setfield(L, -2, "connects_to");
+
+ push_ARGB8(L, c.post_effect_color);
+ lua_setfield(L, -2, "post_effect_color");
+ lua_pushnumber(L, c.leveled);
+ lua_setfield(L, -2, "leveled");
+ lua_pushboolean(L, c.sunlight_propagates);
+ lua_setfield(L, -2, "sunlight_propagates");
+ lua_pushnumber(L, c.light_source);
+ lua_setfield(L, -2, "light_source");
+ lua_pushboolean(L, c.is_ground_content);
+ lua_setfield(L, -2, "is_ground_content");
+ lua_pushboolean(L, c.walkable);
+ lua_setfield(L, -2, "walkable");
+ lua_pushboolean(L, c.pointable);
+ lua_setfield(L, -2, "pointable");
+ lua_pushboolean(L, c.diggable);
+ lua_setfield(L, -2, "diggable");
+ lua_pushboolean(L, c.climbable);
+ lua_setfield(L, -2, "climbable");
+ lua_pushboolean(L, c.buildable_to);
+ lua_setfield(L, -2, "buildable_to");
+ lua_pushboolean(L, c.rightclickable);
+ lua_setfield(L, -2, "rightclickable");
+ lua_pushnumber(L, c.damage_per_second);
+ lua_setfield(L, -2, "damage_per_second");
+ if (c.isLiquid()) {
+ lua_pushstring(L, liquid_type.c_str());
+ lua_setfield(L, -2, "liquid_type");
+ lua_pushstring(L, c.liquid_alternative_flowing.c_str());
+ lua_setfield(L, -2, "liquid_alternative_flowing");
+ lua_pushstring(L, c.liquid_alternative_source.c_str());
+ lua_setfield(L, -2, "liquid_alternative_source");
+ lua_pushnumber(L, c.liquid_viscosity);
+ lua_setfield(L, -2, "liquid_viscosity");
+ lua_pushboolean(L, c.liquid_renewable);
+ lua_setfield(L, -2, "liquid_renewable");
+ lua_pushnumber(L, c.liquid_range);
+ lua_setfield(L, -2, "liquid_range");
+ }
+ lua_pushnumber(L, c.drowning);
+ lua_setfield(L, -2, "drowning");
+ lua_pushboolean(L, c.floodable);
+ lua_setfield(L, -2, "floodable");
+ push_nodebox(L, c.node_box);
+ lua_setfield(L, -2, "node_box");
+ push_nodebox(L, c.selection_box);
+ lua_setfield(L, -2, "selection_box");
+ push_nodebox(L, c.collision_box);
+ lua_setfield(L, -2, "collision_box");
+ lua_newtable(L);
+ push_soundspec(L, c.sound_footstep);
+ lua_setfield(L, -2, "sound_footstep");
+ push_soundspec(L, c.sound_dig);
+ lua_setfield(L, -2, "sound_dig");
+ push_soundspec(L, c.sound_dug);
+ lua_setfield(L, -2, "sound_dug");
+ lua_setfield(L, -2, "sounds");
+ lua_pushboolean(L, c.legacy_facedir_simple);
+ lua_setfield(L, -2, "legacy_facedir_simple");
+ lua_pushboolean(L, c.legacy_wallmounted);
+ lua_setfield(L, -2, "legacy_wallmounted");
+}
+
+/******************************************************************************/
+void push_nodebox(lua_State *L, const NodeBox &box)
+{
+ lua_newtable(L);
+ switch (box.type)
+ {
+ case NODEBOX_REGULAR:
+ lua_pushstring(L, "regular");
+ lua_setfield(L, -2, "type");
+ break;
+ case NODEBOX_LEVELED:
+ case NODEBOX_FIXED:
+ lua_pushstring(L, "fixed");
+ lua_setfield(L, -2, "type");
+ push_box(L, box.fixed);
+ lua_setfield(L, -2, "fixed");
+ break;
+ case NODEBOX_WALLMOUNTED:
+ lua_pushstring(L, "wallmounted");
+ lua_setfield(L, -2, "type");
+ push_aabb3f(L, box.wall_top);
+ lua_setfield(L, -2, "wall_top");
+ push_aabb3f(L, box.wall_bottom);
+ lua_setfield(L, -2, "wall_bottom");
+ push_aabb3f(L, box.wall_side);
+ lua_setfield(L, -2, "wall_side");
+ break;
+ case NODEBOX_CONNECTED:
+ lua_pushstring(L, "connected");
+ lua_setfield(L, -2, "type");
+ push_box(L, box.connect_top);
+ lua_setfield(L, -2, "connect_top");
+ push_box(L, box.connect_bottom);
+ lua_setfield(L, -2, "connect_bottom");
+ push_box(L, box.connect_front);
+ lua_setfield(L, -2, "connect_front");
+ push_box(L, box.connect_back);
+ lua_setfield(L, -2, "connect_back");
+ push_box(L, box.connect_left);
+ lua_setfield(L, -2, "connect_left");
+ push_box(L, box.connect_right);
+ lua_setfield(L, -2, "connect_right");
+ break;
+ default:
+ FATAL_ERROR("Invalid box.type");
+ break;
+ }
+}
+
+void push_box(lua_State *L, const std::vector<aabb3f> &box)
+{
+ lua_newtable(L);
+ u8 i = 1;
+ for (std::vector<aabb3f>::const_iterator it = box.begin();
+ it != box.end(); ++it) {
+ push_aabb3f(L, (*it));
+ lua_rawseti(L, -2, i);
+ }
+}
+
+/******************************************************************************/
+void push_palette(lua_State *L, const std::vector<video::SColor> *palette)
+{
+ lua_createtable(L, palette->size(), 0);
+ int newTable = lua_gettop(L);
+ int index = 1;
+ std::vector<video::SColor>::const_iterator iter;
+ for (iter = palette->begin(); iter != palette->end(); ++iter) {
+ push_ARGB8(L, (*iter));
+ lua_rawseti(L, newTable, index);
+ index++;
+ }
+}
+
/******************************************************************************/
void read_server_sound_params(lua_State *L, int index,
ServerSoundParams &params)
@@ -627,6 +924,7 @@ void read_server_sound_params(lua_State *L, int index,
if(lua_istable(L, index)){
getfloatfield(L, index, "gain", params.gain);
getstringfield(L, index, "to_player", params.to_player);
+ getfloatfield(L, index, "fade", params.fade);
lua_getfield(L, index, "pos");
if(!lua_isnil(L, -1)){
v3f p = read_v3f(L, -1)*BS;
@@ -659,11 +957,23 @@ void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec)
} else if(lua_istable(L, index)){
getstringfield(L, index, "name", spec.name);
getfloatfield(L, index, "gain", spec.gain);
+ getfloatfield(L, index, "fade", spec.fade);
} 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_pushstring(L, spec.name.c_str());
+ lua_setfield(L, -2, "name");
+ lua_pushnumber(L, spec.gain);
+ lua_setfield(L, -2, "gain");
+ lua_pushnumber(L, spec.fade);
+ lua_setfield(L, -2, "fade");
+}
+
/******************************************************************************/
NodeBox read_nodebox(lua_State *L, int index)
{
@@ -776,7 +1086,7 @@ bool string_to_enum(const EnumString *spec, int &result,
}
/******************************************************************************/
-ItemStack read_item(lua_State* L, int index,Server* srv)
+ItemStack read_item(lua_State* L, int index, IItemDefManager *idef)
{
if(index < 0)
index = lua_gettop(L) + 1 + index;
@@ -795,7 +1105,6 @@ ItemStack read_item(lua_State* L, int index,Server* srv)
{
// Convert from itemstring
std::string itemstring = lua_tostring(L, index);
- IItemDefManager *idef = srv->idef();
try
{
ItemStack item;
@@ -812,15 +1121,34 @@ ItemStack read_item(lua_State* L, int index,Server* srv)
else if(lua_istable(L, index))
{
// Convert from table
- IItemDefManager *idef = srv->idef();
std::string name = getstringfield_default(L, index, "name", "");
int count = getintfield_default(L, index, "count", 1);
int wear = getintfield_default(L, index, "wear", 0);
- std::string metadata = getstringfield_default(L, index, "metadata", "");
- return ItemStack(name, count, wear, metadata, idef);
- }
- else
- {
+
+ ItemStack istack(name, count, wear, idef);
+
+ // BACKWARDS COMPATIBLITY
+ std::string value = getstringfield_default(L, index, "metadata", "");
+ istack.metadata.setString("", value);
+
+ // Get meta
+ lua_getfield(L, index, "meta");
+ int fieldstable = lua_gettop(L);
+ if (lua_istable(L, fieldstable)) {
+ lua_pushnil(L);
+ while (lua_next(L, fieldstable) != 0) {
+ // key at index -2 and value at index -1
+ std::string key = lua_tostring(L, -2);
+ size_t value_len;
+ const char *value_cs = lua_tolstring(L, -1, &value_len);
+ std::string value(value_cs, value_len);
+ istack.metadata.setString(key, value);
+ lua_pop(L, 1); // removes value, keeps key for next iteration
+ }
+ }
+
+ return istack;
+ } else {
throw LuaError("Expecting itemstack, itemstring, table or nil");
}
}
@@ -836,7 +1164,7 @@ void push_tool_capabilities(lua_State *L,
lua_newtable(L);
// For each groupcap
for (ToolGCMap::const_iterator i = toolcap.groupcaps.begin();
- i != toolcap.groupcaps.end(); i++) {
+ i != toolcap.groupcaps.end(); ++i) {
// Create groupcap table
lua_newtable(L);
const std::string &name = i->first;
@@ -844,7 +1172,7 @@ void push_tool_capabilities(lua_State *L,
// Create subtable "times"
lua_newtable(L);
for (UNORDERED_MAP<int, float>::const_iterator
- i = groupcap.times.begin(); i != groupcap.times.end(); i++) {
+ i = groupcap.times.begin(); i != groupcap.times.end(); ++i) {
lua_pushinteger(L, i->first);
lua_pushnumber(L, i->second);
lua_settable(L, -3);
@@ -863,7 +1191,7 @@ void push_tool_capabilities(lua_State *L,
lua_newtable(L);
// For each damage group
for (DamageGroup::const_iterator i = toolcap.damageGroups.begin();
- i != toolcap.damageGroups.end(); i++) {
+ i != toolcap.damageGroups.end(); ++i) {
// Create damage group table
lua_pushinteger(L, i->second);
lua_setfield(L, -2, i->first.c_str());
@@ -902,7 +1230,7 @@ void read_inventory_list(lua_State *L, int tableindex,
InventoryList *invlist = inv->addList(name, listsize);
int index = 0;
for(std::vector<ItemStack>::const_iterator
- i = items.begin(); i != items.end(); i++){
+ i = items.begin(); i != items.end(); ++i){
if(forcesize != -1 && index == forcesize)
break;
invlist->changeItem(index, *i);
@@ -915,6 +1243,41 @@ void read_inventory_list(lua_State *L, int tableindex,
}
/******************************************************************************/
+struct TileAnimationParams read_animation_definition(lua_State *L, int index)
+{
+ if(index < 0)
+ index = lua_gettop(L) + 1 + index;
+
+ struct TileAnimationParams anim;
+ anim.type = TAT_NONE;
+ if (!lua_istable(L, index))
+ return anim;
+
+ anim.type = (TileAnimationType)
+ getenumfield(L, index, "type", es_TileAnimationType,
+ TAT_NONE);
+ if (anim.type == TAT_VERTICAL_FRAMES) {
+ // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
+ anim.vertical_frames.aspect_w =
+ getintfield_default(L, index, "aspect_w", 16);
+ anim.vertical_frames.aspect_h =
+ getintfield_default(L, index, "aspect_h", 16);
+ anim.vertical_frames.length =
+ getfloatfield_default(L, index, "length", 1.0);
+ } else if (anim.type == TAT_SHEET_2D) {
+ // {type="sheet_2d", frames_w=5, frames_h=3, frame_length=0.5}
+ getintfield(L, index, "frames_w",
+ anim.sheet_2d.frames_w);
+ getintfield(L, index, "frames_h",
+ anim.sheet_2d.frames_h);
+ getfloatfield(L, index, "frame_length",
+ anim.sheet_2d.frame_length);
+ }
+
+ return anim;
+}
+
+/******************************************************************************/
ToolCapabilities read_tool_capabilities(
lua_State *L, int table)
{
@@ -1124,7 +1487,7 @@ std::vector<ItemStack> read_items(lua_State *L, int index, Server *srv)
if (items.size() < (u32) key) {
items.resize(key);
}
- items[key - 1] = read_item(L, -1, srv);
+ items[key - 1] = read_item(L, -1, srv->idef());
lua_pop(L, 1);
}
return items;
@@ -1332,3 +1695,42 @@ void read_json_value(lua_State *L, Json::Value &root, int index, u8 recursion)
}
lua_pop(L, 1); // Pop value
}
+
+void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm)
+{
+ lua_newtable(L);
+ if (pointed.type == POINTEDTHING_NODE) {
+ lua_pushstring(L, "node");
+ lua_setfield(L, -2, "type");
+ push_v3s16(L, pointed.node_undersurface);
+ lua_setfield(L, -2, "under");
+ push_v3s16(L, pointed.node_abovesurface);
+ lua_setfield(L, -2, "above");
+ } else if (pointed.type == POINTEDTHING_OBJECT) {
+ lua_pushstring(L, "object");
+ lua_setfield(L, -2, "type");
+
+ if (csm) {
+ lua_pushinteger(L, pointed.object_id);
+ lua_setfield(L, -2, "id");
+ } else {
+ push_objectRef(L, pointed.object_id);
+ lua_setfield(L, -2, "ref");
+ }
+ } else {
+ lua_pushstring(L, "nothing");
+ lua_setfield(L, -2, "type");
+ }
+}
+
+void push_objectRef(lua_State *L, const u16 id)
+{
+ // Get core.object_refs[i]
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "object_refs");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ lua_pushnumber(L, id);
+ lua_gettable(L, -2);
+ lua_remove(L, -2); // object_refs
+ lua_remove(L, -2); // core
+}
diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h
index 2a2228b6d..9b8796297 100644
--- a/src/script/common/c_content.h
+++ b/src/script/common/c_content.h
@@ -38,6 +38,8 @@ extern "C" {
#include "irrlichttypes_bloated.h"
#include "util/string.h"
#include "itemgroup.h"
+#include "itemdef.h"
+#include "c_types.h"
namespace Json { class Value; }
@@ -63,8 +65,20 @@ class Schematic;
ContentFeatures read_content_features (lua_State *L, int index);
+void push_content_features (lua_State *L,
+ const ContentFeatures &c);
+
+void push_nodebox (lua_State *L,
+ const NodeBox &box);
+void push_box (lua_State *L,
+ const std::vector<aabb3f> &box);
+
+void push_palette (lua_State *L,
+ const std::vector<video::SColor> *palette);
+
TileDef read_tiledef (lua_State *L, int index,
u8 drawtype);
+
void read_soundspec (lua_State *L, int index,
SimpleSoundSpec &spec);
NodeBox read_nodebox (lua_State *L, int index);
@@ -77,17 +91,24 @@ void push_dig_params (lua_State *L,
void push_hit_params (lua_State *L,
const HitParams &params);
-ItemStack read_item (lua_State *L, int index, Server *srv);
+ItemStack read_item (lua_State *L, int index, IItemDefManager *idef);
+struct TileAnimationParams read_animation_definition(lua_State *L, int index);
ToolCapabilities read_tool_capabilities (lua_State *L, int table);
void push_tool_capabilities (lua_State *L,
const ToolCapabilities &prop);
-ItemDefinition read_item_definition (lua_State *L, int index,
- ItemDefinition default_def);
+void read_item_definition (lua_State *L, int index, const ItemDefinition &default_def,
+ ItemDefinition &def);
+void push_item_definition (lua_State *L,
+ const ItemDefinition &i);
+void push_item_definition_full (lua_State *L,
+ const ItemDefinition &i);
+
void read_object_properties (lua_State *L, int index,
- ObjectProperties *prop);
+ ObjectProperties *prop,
+ IItemDefManager *idef);
void push_object_properties (lua_State *L,
ObjectProperties *prop);
@@ -142,6 +163,8 @@ std::vector<ItemStack> read_items (lua_State *L,
void read_soundspec (lua_State *L,
int index,
SimpleSoundSpec &spec);
+void push_soundspec (lua_State *L,
+ const SimpleSoundSpec &spec);
bool string_to_enum (const EnumString *spec,
int &result,
@@ -159,6 +182,10 @@ bool push_json_value (lua_State *L,
void read_json_value (lua_State *L, Json::Value &root,
int index, u8 recursion = 0);
+void push_pointed_thing (lua_State *L, const PointedThing &pointed, bool csm = false);
+
+void push_objectRef (lua_State *L, const u16 id);
+
extern struct EnumString es_TileAnimationType[];
#endif /* C_CONTENT_H_ */
diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp
index f36298915..fc516d56a 100644
--- a/src/script/common/c_converter.cpp
+++ b/src/script/common/c_converter.cpp
@@ -26,15 +26,17 @@ extern "C" {
#include "util/serialize.h"
#include "util/string.h"
#include "common/c_converter.h"
+#include "common/c_internal.h"
#include "constants.h"
#define CHECK_TYPE(index, name, type) do { \
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) + ")."); \
+ " got " + lua_typename(L, t) + ").\n" + traceback); \
} \
} while(0)
#define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER)
diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h
index a5fbee765..b0f61a8ca 100644
--- a/src/script/common/c_converter.h
+++ b/src/script/common/c_converter.h
@@ -77,6 +77,8 @@ void setfloatfield(lua_State *L, int table,
const char *fieldname, float value);
void setboolfield(lua_State *L, int table,
const char *fieldname, bool value);
+void setstringfield(lua_State *L, int table,
+ const char *fieldname, const char *value);
v3f checkFloatPos (lua_State *L, int index);
v2f check_v2f (lua_State *L, int index);
diff --git a/src/script/cpp_api/CMakeLists.txt b/src/script/cpp_api/CMakeLists.txt
index be4d0131e..4b13356a8 100644
--- a/src/script/cpp_api/CMakeLists.txt
+++ b/src/script/cpp_api/CMakeLists.txt
@@ -13,6 +13,7 @@ set(common_SCRIPT_CPP_API_SRCS
PARENT_SCOPE)
set(client_SCRIPT_CPP_API_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/s_client.cpp
${CMAKE_CURRENT_SOURCE_DIR}/s_mainmenu.cpp
PARENT_SCOPE)
diff --git a/src/script/cpp_api/s_async.cpp b/src/script/cpp_api/s_async.cpp
index 1fb84fab6..722359066 100644
--- a/src/script/cpp_api/s_async.cpp
+++ b/src/script/cpp_api/s_async.cpp
@@ -46,26 +46,26 @@ AsyncEngine::~AsyncEngine()
// Request all threads to stop
for (std::vector<AsyncWorkerThread *>::iterator it = workerThreads.begin();
- it != workerThreads.end(); it++) {
+ it != workerThreads.end(); ++it) {
(*it)->stop();
}
// Wake up all threads
for (std::vector<AsyncWorkerThread *>::iterator it = workerThreads.begin();
- it != workerThreads.end(); it++) {
+ it != workerThreads.end(); ++it) {
jobQueueCounter.post();
}
// Wait for threads to finish
for (std::vector<AsyncWorkerThread *>::iterator it = workerThreads.begin();
- it != workerThreads.end(); it++) {
+ it != workerThreads.end(); ++it) {
(*it)->wait();
}
// Force kill all threads
for (std::vector<AsyncWorkerThread *>::iterator it = workerThreads.begin();
- it != workerThreads.end(); it++) {
+ it != workerThreads.end(); ++it) {
delete *it;
}
@@ -76,14 +76,9 @@ AsyncEngine::~AsyncEngine()
}
/******************************************************************************/
-bool AsyncEngine::registerFunction(const char* name, lua_CFunction func)
+void AsyncEngine::registerStateInitializer(StateInitializer func)
{
- if (initDone) {
- return false;
- }
-
- functionList[name] = func;
- return true;
+ stateInitializers.push_back(func);
}
/******************************************************************************/
@@ -100,7 +95,8 @@ void AsyncEngine::initialize(unsigned int numEngines)
}
/******************************************************************************/
-unsigned int AsyncEngine::queueAsyncJob(std::string func, std::string params)
+unsigned int AsyncEngine::queueAsyncJob(const std::string &func,
+ const std::string &params)
{
jobQueueMutex.lock();
LuaJobInfo toAdd;
@@ -124,7 +120,6 @@ LuaJobInfo AsyncEngine::getJob()
jobQueueMutex.lock();
LuaJobInfo retval;
- retval.valid = false;
if (!jobQueue.empty()) {
retval = jobQueue.front();
@@ -137,7 +132,7 @@ LuaJobInfo AsyncEngine::getJob()
}
/******************************************************************************/
-void AsyncEngine::putJobResult(LuaJobInfo result)
+void AsyncEngine::putJobResult(const LuaJobInfo &result)
{
resultQueueMutex.lock();
resultQueue.push_back(result);
@@ -204,11 +199,9 @@ void AsyncEngine::pushFinishedJobs(lua_State* L) {
/******************************************************************************/
void AsyncEngine::prepareEnvironment(lua_State* L, int top)
{
- for (UNORDERED_MAP<std::string, lua_CFunction>::iterator it = functionList.begin();
- it != functionList.end(); it++) {
- lua_pushstring(L, it->first.c_str());
- lua_pushcfunction(L, it->second);
- lua_settable(L, top);
+ for (std::vector<StateInitializer>::iterator it = stateInitializers.begin();
+ it != stateInitializers.end(); it++) {
+ (*it)(L, top);
}
}
@@ -264,7 +257,7 @@ void* AsyncWorkerThread::run()
// Wait for job
LuaJobInfo toProcess = jobDispatcher->getJob();
- if (toProcess.valid == false || stopRequested()) {
+ if (!toProcess.valid || stopRequested()) {
continue;
}
diff --git a/src/script/cpp_api/s_async.h b/src/script/cpp_api/s_async.h
index 016381e5f..dbe0654e2 100644
--- a/src/script/cpp_api/s_async.h
+++ b/src/script/cpp_api/s_async.h
@@ -38,7 +38,16 @@ class AsyncEngine;
// Declarations
// Data required to queue a job
-struct LuaJobInfo {
+struct LuaJobInfo
+{
+ LuaJobInfo() :
+ serializedFunction(""),
+ serializedParams(""),
+ serializedResult(""),
+ id(0),
+ valid(false)
+ {}
+
// Function to be called in async environment
std::string serializedFunction;
// Parameter to be passed to function
@@ -66,16 +75,16 @@ private:
// Asynchornous thread and job management
class AsyncEngine {
friend class AsyncWorkerThread;
+ typedef void (*StateInitializer)(lua_State *L, int top);
public:
AsyncEngine();
~AsyncEngine();
/**
- * Register function to be used within engine
- * @param name Function name to be used within Lua environment
+ * Register function to be called on new states
* @param func C function to be called
*/
- bool registerFunction(const char* name, lua_CFunction func);
+ void registerStateInitializer(StateInitializer func);
/**
* Create async engine tasks and lock function registration
@@ -89,7 +98,7 @@ public:
* @param params Serialized parameters
* @return jobid The job is queued
*/
- unsigned int queueAsyncJob(std::string func, std::string params);
+ unsigned int queueAsyncJob(const std::string &func, const std::string &params);
/**
* Engine step to process finished jobs
@@ -116,7 +125,7 @@ protected:
* Put a Job result back to result queue
* @param result result of completed job
*/
- void putJobResult(LuaJobInfo result);
+ void putJobResult(const LuaJobInfo &result);
/**
* Initialize environment with current registred functions
@@ -131,8 +140,8 @@ private:
// Variable locking the engine against further modification
bool initDone;
- // Internal store for registred functions
- UNORDERED_MAP<std::string, lua_CFunction> functionList;
+ // Internal store for registred state initializers
+ std::vector<StateInitializer> stateInitializers;
// Internal counter to create job IDs
unsigned int jobIdCounter;
diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp
index 679a517ee..4d7461c5b 100644
--- a/src/script/cpp_api/s_base.cpp
+++ b/src/script/cpp_api/s_base.cpp
@@ -23,12 +23,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_object.h"
#include "common/c_converter.h"
#include "serverobject.h"
-#include "debug.h"
#include "filesys.h"
-#include "log.h"
#include "mods.h"
#include "porting.h"
#include "util/string.h"
+#include "server.h"
+#ifndef SERVER
+#include "client.h"
+#endif
extern "C" {
@@ -40,6 +42,8 @@ extern "C" {
#include <stdio.h>
#include <cstdarg>
+#include "script/common/c_content.h"
+#include <sstream>
class ModNameStorer
@@ -68,7 +72,8 @@ public:
*/
ScriptApiBase::ScriptApiBase() :
- m_luastackmutex()
+ m_luastackmutex(),
+ m_gamedef(NULL)
{
#ifdef SCRIPTAPI_LOCK_DEBUG
m_lock_recursion_count = 0;
@@ -77,6 +82,8 @@ ScriptApiBase::ScriptApiBase() :
m_luastack = luaL_newstate();
FATAL_ERROR_IF(!m_luastack, "luaL_newstate() failed");
+ lua_atpanic(m_luastack, &luaPanic);
+
luaL_openlibs(m_luastack);
// Make the ScriptApiBase* accessible to ModApiBase
@@ -110,7 +117,6 @@ ScriptApiBase::ScriptApiBase() :
// Default to false otherwise
m_secure = false;
- m_server = NULL;
m_environment = NULL;
m_guiengine = NULL;
}
@@ -120,6 +126,16 @@ ScriptApiBase::~ScriptApiBase()
lua_close(m_luastack);
}
+int ScriptApiBase::luaPanic(lua_State *L)
+{
+ std::ostringstream oss;
+ oss << "LUA PANIC: unprotected error in call to Lua API ("
+ << lua_tostring(L, -1) << ")";
+ FATAL_ERROR(oss.str().c_str());
+ // NOTREACHED
+ return 0;
+}
+
void ScriptApiBase::loadMod(const std::string &script_path,
const std::string &mod_name)
{
@@ -224,7 +240,7 @@ void ScriptApiBase::stackDump(std::ostream &o)
break;
case LUA_TNUMBER: /* numbers */ {
char buf[10];
- snprintf(buf, 10, "%g", lua_tonumber(m_luastack, i));
+ snprintf(buf, 10, "%lf", lua_tonumber(m_luastack, i));
o << buf;
break;
}
@@ -305,18 +321,17 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L,
if (cobj == NULL || cobj->getId() == 0) {
ObjectRef::create(L, cobj);
} else {
- objectrefGet(L, cobj->getId());
+ push_objectRef(L, cobj->getId());
}
}
-void ScriptApiBase::objectrefGet(lua_State *L, u16 id)
+Server* ScriptApiBase::getServer()
{
- // Get core.object_refs[i]
- lua_getglobal(L, "core");
- lua_getfield(L, -1, "object_refs");
- luaL_checktype(L, -1, LUA_TTABLE);
- lua_pushnumber(L, id);
- lua_gettable(L, -2);
- lua_remove(L, -2); // object_refs
- lua_remove(L, -2); // core
+ return dynamic_cast<Server *>(m_gamedef);
}
+#ifndef SERVER
+Client* ScriptApiBase::getClient()
+{
+ return dynamic_cast<Client *>(m_gamedef);
+}
+#endif
diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h
index f52474f00..5b047a081 100644
--- a/src/script/cpp_api/s_base.h
+++ b/src/script/cpp_api/s_base.h
@@ -55,6 +55,10 @@ extern "C" {
setOriginFromTableRaw(index, __FUNCTION__)
class Server;
+#ifndef SERVER
+class Client;
+#endif
+class IGameDef;
class Environment;
class GUIEngine;
class ServerActiveObject;
@@ -75,7 +79,11 @@ public:
void addObjectReference(ServerActiveObject *cobj);
void removeObjectReference(ServerActiveObject *cobj);
- Server* getServer() { return m_server; }
+ IGameDef *getGameDef() { return m_gamedef; }
+ Server* getServer();
+#ifndef SERVER
+ Client* getClient();
+#endif
std::string getOrigin() { return m_last_run_mod; }
void setOriginDirect(const char *origin);
@@ -98,7 +106,7 @@ protected:
void scriptError(int result, const char *fxn);
void stackDump(std::ostream &o);
- void setServer(Server* server) { m_server = server; }
+ void setGameDef(IGameDef* gamedef) { m_gamedef = gamedef; }
Environment* getEnv() { return m_environment; }
void setEnv(Environment* env) { m_environment = env; }
@@ -107,7 +115,6 @@ protected:
void setGuiEngine(GUIEngine* guiengine) { m_guiengine = guiengine; }
void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj);
- void objectrefGet(lua_State *L, u16 id);
RecursiveMutex m_luastackmutex;
std::string m_last_run_mod;
@@ -118,9 +125,11 @@ protected:
#endif
private:
+ static int luaPanic(lua_State *L);
+
lua_State* m_luastack;
- Server* m_server;
+ IGameDef* m_gamedef;
Environment* m_environment;
GUIEngine* m_guiengine;
};
diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp
new file mode 100644
index 000000000..55d309fda
--- /dev/null
+++ b/src/script/cpp_api/s_client.cpp
@@ -0,0 +1,230 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "s_client.h"
+#include "s_internal.h"
+#include "client.h"
+#include "common/c_converter.h"
+#include "common/c_content.h"
+#include "s_item.h"
+
+void ScriptApiClient::on_shutdown()
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get registered shutdown hooks
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_shutdown");
+ // Call callbacks
+ runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
+}
+
+void ScriptApiClient::on_connect()
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // get registered connect hooks
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_connect");
+ // Call callback
+ runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
+}
+
+bool ScriptApiClient::on_sending_message(const std::string &message)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_chat_messages
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_sending_chat_messages");
+ // Call callbacks
+ lua_pushstring(L, message.c_str());
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ bool ate = lua_toboolean(L, -1);
+ return ate;
+}
+
+bool ScriptApiClient::on_receiving_message(const std::string &message)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_chat_messages
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_receiving_chat_messages");
+ // Call callbacks
+ lua_pushstring(L, message.c_str());
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+ bool ate = lua_toboolean(L, -1);
+ return ate;
+}
+
+void ScriptApiClient::on_damage_taken(int32_t damage_amount)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_chat_messages
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_damage_taken");
+ // Call callbacks
+ lua_pushinteger(L, damage_amount);
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+}
+
+void ScriptApiClient::on_hp_modification(int32_t newhp)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_chat_messages
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_hp_modification");
+ // Call callbacks
+ lua_pushinteger(L, newhp);
+ runCallbacks(1, RUN_CALLBACKS_MODE_OR_SC);
+}
+
+void ScriptApiClient::on_death()
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get registered shutdown hooks
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_death");
+ // Call callbacks
+ runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
+}
+
+void ScriptApiClient::environment_step(float dtime)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_globalsteps
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_globalsteps");
+ // Call callbacks
+ lua_pushnumber(L, dtime);
+ try {
+ runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+ } catch (LuaError &e) {
+ getClient()->setFatalError(std::string("Client environment_step: ") + e.what() + "\n"
+ + script_get_backtrace(L));
+ }
+}
+
+void ScriptApiClient::on_formspec_input(const std::string &formname,
+ const StringMap &fields)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_chat_messages
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_formspec_input");
+ // Call callbacks
+ // param 1
+ lua_pushstring(L, formname.c_str());
+ // param 2
+ lua_newtable(L);
+ StringMap::const_iterator it;
+ for (it = fields.begin(); it != fields.end(); ++it) {
+ const std::string &name = it->first;
+ const std::string &value = it->second;
+ lua_pushstring(L, name.c_str());
+ lua_pushlstring(L, value.c_str(), value.size());
+ lua_settable(L, -3);
+ }
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC);
+}
+
+bool ScriptApiClient::on_dignode(v3s16 p, MapNode node)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ INodeDefManager *ndef = getClient()->ndef();
+
+ // Get core.registered_on_dignode
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_dignode");
+
+ // Push data
+ push_v3s16(L, p);
+ pushnode(L, node, ndef);
+
+ // Call functions
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ return lua_toboolean(L, -1);
+}
+
+bool ScriptApiClient::on_punchnode(v3s16 p, MapNode node)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ INodeDefManager *ndef = getClient()->ndef();
+
+ // Get core.registered_on_punchgnode
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_punchnode");
+
+ // Push data
+ push_v3s16(L, p);
+ pushnode(L, node, ndef);
+
+ // Call functions
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ bool blocked = lua_toboolean(L, -1);
+ return blocked;
+}
+
+bool ScriptApiClient::on_placenode(const PointedThing &pointed, const ItemDefinition &item)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_placenode
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_placenode");
+
+ // Push data
+ push_pointed_thing(L, pointed, true);
+ push_item_definition(L, item);
+
+ // Call functions
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ return lua_toboolean(L, -1);
+}
+
+bool ScriptApiClient::on_item_use(const ItemStack &item, const PointedThing &pointed)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.registered_on_item_use
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_item_use");
+
+ // Push data
+ LuaItemStack::create(L, item);
+ push_pointed_thing(L, pointed, true);
+
+ // Call functions
+ runCallbacks(2, RUN_CALLBACKS_MODE_OR);
+ return lua_toboolean(L, -1);
+}
+
+void ScriptApiClient::setEnv(ClientEnvironment *env)
+{
+ ScriptApiBase::setEnv(env);
+}
diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h
new file mode 100644
index 000000000..9133637a6
--- /dev/null
+++ b/src/script/cpp_api/s_client.h
@@ -0,0 +1,63 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef S_CLIENT_H_
+#define S_CLIENT_H_
+
+#include "util/pointedthing.h"
+#include "cpp_api/s_base.h"
+#include "mapnode.h"
+#include "itemdef.h"
+#include "util/string.h"
+#include "util/pointedthing.h"
+#include "lua_api/l_item.h"
+
+#ifdef _CRT_MSVCP_CURRENT
+#include <cstdint>
+#endif
+
+class ClientEnvironment;
+
+class ScriptApiClient : virtual public ScriptApiBase
+{
+public:
+ // Calls on_shutdown handlers
+ void on_shutdown();
+
+ void on_connect();
+
+ // Chat message handlers
+ bool on_sending_message(const std::string &message);
+ bool on_receiving_message(const std::string &message);
+
+ void on_damage_taken(int32_t damage_amount);
+ void on_hp_modification(int32_t newhp);
+ void on_death();
+ void environment_step(float dtime);
+ void on_formspec_input(const std::string &formname, const StringMap &fields);
+
+ bool on_dignode(v3s16 p, MapNode node);
+ bool on_punchnode(v3s16 p, MapNode node);
+ bool on_placenode(const PointedThing &pointed, const ItemDefinition &item);
+ bool on_item_use(const ItemStack &item, const PointedThing &pointed);
+
+ void setEnv(ClientEnvironment *env);
+};
+#endif
diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp
index 378a6bf09..4c1e296d4 100644
--- a/src/script/cpp_api/s_entity.cpp
+++ b/src/script/cpp_api/s_entity.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "object_properties.h"
#include "common/c_converter.h"
#include "common/c_content.h"
+#include "server.h"
bool ScriptApiEntity::luaentity_Add(u16 id, const char *name)
{
@@ -56,7 +57,7 @@ bool ScriptApiEntity::luaentity_Add(u16 id, const char *name)
// Add object reference
// This should be userdata with metatable ObjectRef
- objectrefGet(L, id);
+ push_objectRef(L, id);
luaL_checktype(L, -1, LUA_TUSERDATA);
if (!luaL_checkudata(L, -1, "ObjectRef"))
luaL_typerror(L, -1, "ObjectRef");
@@ -187,11 +188,11 @@ void ScriptApiEntity::luaentity_GetProperties(u16 id,
getstringfield(L, -1, "mesh", prop->mesh);
// Deprecated: read object properties directly
- read_object_properties(L, -1, prop);
+ read_object_properties(L, -1, prop, getServer()->idef());
// Read initial_properties
lua_getfield(L, -1, "initial_properties");
- read_object_properties(L, -1, prop);
+ read_object_properties(L, -1, prop, getServer()->idef());
lua_pop(L, 1);
}
@@ -224,10 +225,10 @@ void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
}
// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch,
-// tool_capabilities, direction)
-void ScriptApiEntity::luaentity_Punch(u16 id,
+// tool_capabilities, direction, damage)
+bool ScriptApiEntity::luaentity_Punch(u16 id,
ServerActiveObject *puncher, float time_from_last_punch,
- const ToolCapabilities *toolcap, v3f dir)
+ const ToolCapabilities *toolcap, v3f dir, s16 damage)
{
SCRIPTAPI_PRECHECKHEADER
@@ -242,8 +243,8 @@ void ScriptApiEntity::luaentity_Punch(u16 id,
// Get function
lua_getfield(L, -1, "on_punch");
if (lua_isnil(L, -1)) {
- lua_pop(L, 2); // Pop on_punch and entitu
- return;
+ lua_pop(L, 2); // Pop on_punch and entity
+ return false;
}
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self
@@ -251,11 +252,14 @@ void ScriptApiEntity::luaentity_Punch(u16 id,
lua_pushnumber(L, time_from_last_punch);
push_tool_capabilities(L, *toolcap);
push_v3f(L, dir);
+ lua_pushnumber(L, damage);
setOriginFromTable(object);
- PCALL_RES(lua_pcall(L, 5, 0, error_handler));
+ PCALL_RES(lua_pcall(L, 6, 1, error_handler));
+ bool retval = lua_toboolean(L, -1);
lua_pop(L, 2); // Pop object and error handler
+ return retval;
}
// Calls entity:on_rightclick(ObjectRef clicker)
diff --git a/src/script/cpp_api/s_entity.h b/src/script/cpp_api/s_entity.h
index 8df9d7f00..4e2a056bb 100644
--- a/src/script/cpp_api/s_entity.h
+++ b/src/script/cpp_api/s_entity.h
@@ -38,9 +38,9 @@ public:
void luaentity_GetProperties(u16 id,
ObjectProperties *prop);
void luaentity_Step(u16 id, float dtime);
- void luaentity_Punch(u16 id,
+ bool luaentity_Punch(u16 id,
ServerActiveObject *puncher, float time_from_last_punch,
- const ToolCapabilities *toolcap, v3f dir);
+ const ToolCapabilities *toolcap, v3f dir, s16 damage);
void luaentity_Rightclick(u16 id,
ServerActiveObject *clicker);
};
diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp
index 913d8539d..b1404bf22 100644
--- a/src/script/cpp_api/s_env.cpp
+++ b/src/script/cpp_api/s_env.cpp
@@ -54,7 +54,9 @@ void ScriptApiEnv::environment_Step(float dtime)
try {
runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
} catch (LuaError &e) {
- getServer()->setAsyncFatalError(e.what());
+ getServer()->setAsyncFatalError(
+ std::string("environment_Step: ") + e.what() + "\n"
+ + script_get_backtrace(L));
}
}
@@ -75,7 +77,9 @@ void ScriptApiEnv::player_event(ServerActiveObject *player, const std::string &t
try {
runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
} catch (LuaError &e) {
- getServer()->setAsyncFatalError(e.what());
+ getServer()->setAsyncFatalError(
+ std::string("player_event: ") + e.what() + "\n"
+ + script_get_backtrace(L) );
}
}
@@ -237,7 +241,9 @@ void ScriptApiEnv::on_emerge_area_completion(
try {
PCALL_RES(lua_pcall(L, 4, 0, error_handler));
} catch (LuaError &e) {
- server->setAsyncFatalError(e.what());
+ server->setAsyncFatalError(
+ std::string("on_emerge_area_completion: ") + e.what() + "\n"
+ + script_get_backtrace(L));
}
lua_pop(L, 1); // Pop error handler
diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp
index 3c84fb8cf..032018f2f 100644
--- a/src/script/cpp_api/s_item.cpp
+++ b/src/script/cpp_api/s_item.cpp
@@ -47,7 +47,7 @@ bool ScriptApiItem::item_OnDrop(ItemStack &item,
PCALL_RES(lua_pcall(L, 3, 1, error_handler));
if (!lua_isnil(L, -1)) {
try {
- item = read_item(L,-1, getServer());
+ item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
throw LuaError(std::string(e.what()) + ". item=" + item.name);
}
@@ -74,7 +74,7 @@ bool ScriptApiItem::item_OnPlace(ItemStack &item,
PCALL_RES(lua_pcall(L, 3, 1, error_handler));
if (!lua_isnil(L, -1)) {
try {
- item = read_item(L,-1, getServer());
+ item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
throw LuaError(std::string(e.what()) + ". item=" + item.name);
}
@@ -101,7 +101,7 @@ bool ScriptApiItem::item_OnUse(ItemStack &item,
PCALL_RES(lua_pcall(L, 3, 1, error_handler));
if(!lua_isnil(L, -1)) {
try {
- item = read_item(L,-1, getServer());
+ item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
throw LuaError(std::string(e.what()) + ". item=" + item.name);
}
@@ -127,7 +127,7 @@ bool ScriptApiItem::item_OnSecondaryUse(ItemStack &item, ServerActiveObject *use
PCALL_RES(lua_pcall(L, 3, 1, error_handler));
if (!lua_isnil(L, -1)) {
try {
- item = read_item(L, -1, getServer());
+ item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
throw LuaError(std::string(e.what()) + ". item=" + item.name);
}
@@ -159,7 +159,7 @@ bool ScriptApiItem::item_OnCraft(ItemStack &item, ServerActiveObject *user,
PCALL_RES(lua_pcall(L, 4, 1, error_handler));
if (!lua_isnil(L, -1)) {
try {
- item = read_item(L,-1, getServer());
+ item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
throw LuaError(std::string(e.what()) + ". item=" + item.name);
}
@@ -191,7 +191,7 @@ bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user,
PCALL_RES(lua_pcall(L, 4, 1, error_handler));
if (!lua_isnil(L, -1)) {
try {
- item = read_item(L,-1, getServer());
+ item = read_item(L, -1, getServer()->idef());
} catch (LuaError &e) {
throw LuaError(std::string(e.what()) + ". item=" + item.name);
}
@@ -249,27 +249,6 @@ void ScriptApiItem::pushPointedThing(const PointedThing& pointed)
{
lua_State* L = getStack();
- lua_newtable(L);
- if(pointed.type == POINTEDTHING_NODE)
- {
- lua_pushstring(L, "node");
- lua_setfield(L, -2, "type");
- push_v3s16(L, pointed.node_undersurface);
- lua_setfield(L, -2, "under");
- push_v3s16(L, pointed.node_abovesurface);
- lua_setfield(L, -2, "above");
- }
- else if(pointed.type == POINTEDTHING_OBJECT)
- {
- lua_pushstring(L, "object");
- lua_setfield(L, -2, "type");
- objectrefGet(L, pointed.object_id);
- lua_setfield(L, -2, "ref");
- }
- else
- {
- lua_pushstring(L, "nothing");
- lua_setfield(L, -2, "type");
- }
+ push_pointed_thing(L, pointed);
}
diff --git a/src/script/cpp_api/s_mainmenu.cpp b/src/script/cpp_api/s_mainmenu.cpp
index e9a7a13b9..1e9ba3a41 100644
--- a/src/script/cpp_api/s_mainmenu.cpp
+++ b/src/script/cpp_api/s_mainmenu.cpp
@@ -34,8 +34,7 @@ void ScriptApiMainMenu::setMainMenuData(MainMenuDataForScript *data)
lua_pushnil(L);
}
lua_settable(L, gamedata_idx);
- setboolfield(L, gamedata_idx, "reconnect_requested",
- data->reconnect_requested);
+ setboolfield(L, gamedata_idx, "reconnect_requested", data->reconnect_requested);
lua_pop(L, 1);
}
@@ -58,7 +57,7 @@ void ScriptApiMainMenu::handleMainMenuEvent(std::string text)
// Call it
lua_pushstring(L, text.c_str());
PCALL_RES(lua_pcall(L, 1, 0, error_handler));
- lua_pop(L, 1); // Pop error handler
+ lua_pop(L, 1); // Pop error handler
}
void ScriptApiMainMenu::handleMainMenuButtons(const StringMap &fields)
@@ -90,6 +89,5 @@ void ScriptApiMainMenu::handleMainMenuButtons(const StringMap &fields)
// Call it
PCALL_RES(lua_pcall(L, 1, 0, error_handler));
- lua_pop(L, 1); // Pop error handler
+ lua_pop(L, 1); // Pop error handler
}
-
diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp
index 379ed773f..1ae8f58a5 100644
--- a/src/script/cpp_api/s_node.cpp
+++ b/src/script/cpp_api/s_node.cpp
@@ -59,6 +59,10 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] =
{CPT2_LEVELED, "leveled"},
{CPT2_DEGROTATE, "degrotate"},
{CPT2_MESHOPTIONS, "meshoptions"},
+ {CPT2_COLOR, "color"},
+ {CPT2_COLORED_FACEDIR, "colorfacedir"},
+ {CPT2_COLORED_WALLMOUNTED, "colorwallmounted"},
+ {CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"},
{0, NULL},
};
@@ -174,6 +178,27 @@ void ScriptApiNode::node_on_destruct(v3s16 p, MapNode node)
lua_pop(L, 1); // Pop error handler
}
+bool ScriptApiNode::node_on_flood(v3s16 p, MapNode node, MapNode newnode)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ int error_handler = PUSH_ERROR_HANDLER(L);
+
+ INodeDefManager *ndef = getServer()->ndef();
+
+ // Push callback function on stack
+ if (!getItemCallback(ndef->get(node).name.c_str(), "on_flood"))
+ return false;
+
+ // Call function
+ push_v3s16(L, p);
+ pushnode(L, node, ndef);
+ pushnode(L, newnode, ndef);
+ PCALL_RES(lua_pcall(L, 3, 1, error_handler));
+ lua_remove(L, error_handler);
+ return (bool) lua_isboolean(L, -1) && (bool) lua_toboolean(L, -1) == true;
+}
+
void ScriptApiNode::node_after_destruct(v3s16 p, MapNode node)
{
SCRIPTAPI_PRECHECKHEADER
@@ -238,7 +263,7 @@ void ScriptApiNode::node_on_receive_fields(v3s16 p,
lua_pushstring(L, formname.c_str()); // formname
lua_newtable(L); // fields
StringMap::const_iterator it;
- for (it = fields.begin(); it != fields.end(); it++) {
+ for (it = fields.begin(); it != fields.end(); ++it) {
const std::string &name = it->first;
const std::string &value = it->second;
lua_pushstring(L, name.c_str());
diff --git a/src/script/cpp_api/s_node.h b/src/script/cpp_api/s_node.h
index fe1180cb3..eb127909d 100644
--- a/src/script/cpp_api/s_node.h
+++ b/src/script/cpp_api/s_node.h
@@ -42,6 +42,7 @@ public:
ServerActiveObject *digger);
void node_on_construct(v3s16 p, MapNode node);
void node_on_destruct(v3s16 p, MapNode node);
+ bool node_on_flood(v3s16 p, MapNode node, MapNode newnode);
void node_after_destruct(v3s16 p, MapNode node);
bool node_on_timer(v3s16 p, MapNode node, f32 dtime);
void node_on_receive_fields(v3s16 p,
diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h
index 86ee1b024..9b4611f9e 100644
--- a/src/script/cpp_api/s_player.h
+++ b/src/script/cpp_api/s_player.h
@@ -26,8 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
struct ToolCapabilities;
-class ScriptApiPlayer
- : virtual public ScriptApiBase
+class ScriptApiPlayer : virtual public ScriptApiBase
{
public:
virtual ~ScriptApiPlayer();
@@ -36,17 +35,16 @@ public:
void on_dieplayer(ServerActiveObject *player);
bool on_respawnplayer(ServerActiveObject *player);
bool on_prejoinplayer(const std::string &name, const std::string &ip,
- std::string *reason);
+ std::string *reason);
void on_joinplayer(ServerActiveObject *player);
void on_leaveplayer(ServerActiveObject *player, bool timeout);
void on_cheat(ServerActiveObject *player, const std::string &cheat_type);
- bool on_punchplayer(ServerActiveObject *player,
- ServerActiveObject *hitter, float time_from_last_punch,
- const ToolCapabilities *toolcap, v3f dir, s16 damage);
+ bool on_punchplayer(ServerActiveObject *player, ServerActiveObject *hitter,
+ float time_from_last_punch, const ToolCapabilities *toolcap,
+ v3f dir, s16 damage);
s16 on_player_hpchange(ServerActiveObject *player, s16 hp_change);
void on_playerReceiveFields(ServerActiveObject *player,
- const std::string &formname, const StringMap &fields);
+ const std::string &formname, const StringMap &fields);
};
-
#endif /* S_PLAYER_H_ */
diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp
index 1b1f148cd..5ad7947d5 100644
--- a/src/script/cpp_api/s_security.cpp
+++ b/src/script/cpp_api/s_security.cpp
@@ -99,7 +99,6 @@ void ScriptApiSecurity::initializeSecurity()
"clock",
"date",
"difftime",
- "exit",
"getenv",
"setlocale",
"time",
@@ -124,6 +123,7 @@ void ScriptApiSecurity::initializeSecurity()
"path",
"searchpath",
};
+#if USE_LUAJIT
static const char *jit_whitelist[] = {
"arch",
"flush",
@@ -135,37 +135,13 @@ void ScriptApiSecurity::initializeSecurity()
"version",
"version_num",
};
-
+#endif
m_secure = true;
lua_State *L = getStack();
- // Backup globals to the registry
- lua_getglobal(L, "_G");
- lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
-
- // Replace the global environment with an empty one
-#if LUA_VERSION_NUM <= 501
- int is_main = lua_pushthread(L); // Push the main thread
- FATAL_ERROR_IF(!is_main, "Security: ScriptApi's Lua state "
- "isn't the main Lua thread!");
-#endif
- lua_newtable(L); // Create new environment
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "_G"); // Set _G of new environment
-#if LUA_VERSION_NUM >= 502 // Lua >= 5.2
- // Set the global environment
- lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
-#else // Lua <= 5.1
- // Set the environment of the main thread
- FATAL_ERROR_IF(!lua_setfenv(L, -2), "Security: Unable to set "
- "environment of the main Lua thread!");
- lua_pop(L, 1); // Pop thread
-#endif
- // Get old globals
- lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
- int old_globals = lua_gettop(L);
+ int old_globals = backupGlobals(L);
// Copy safe base functions
@@ -224,7 +200,113 @@ void ScriptApiSecurity::initializeSecurity()
lua_setglobal(L, "package");
lua_pop(L, 1); // Pop old package
+#if USE_LUAJIT
+ // Copy safe jit functions, if they exist
+ lua_getfield(L, -1, "jit");
+ if (!lua_isnil(L, -1)) {
+ lua_newtable(L);
+ copy_safe(L, jit_whitelist, sizeof(jit_whitelist));
+ lua_setglobal(L, "jit");
+ }
+ lua_pop(L, 1); // Pop old jit
+#endif
+
+ lua_pop(L, 1); // Pop globals_backup
+}
+
+void ScriptApiSecurity::initializeSecurityClient()
+{
+ static const char *whitelist[] = {
+ "assert",
+ "core",
+ "collectgarbage",
+ "DIR_DELIM",
+ "error",
+ "getfenv",
+ "ipairs",
+ "next",
+ "pairs",
+ "pcall",
+ "print",
+ "rawequal",
+ "rawget",
+ "rawset",
+ "select",
+ "setfenv",
+ "setmetatable",
+ "tonumber",
+ "tostring",
+ "type",
+ "unpack",
+ "_VERSION",
+ "xpcall",
+ // Completely safe libraries
+ "coroutine",
+ "string",
+ "table",
+ "math",
+ };
+ static const char *os_whitelist[] = {
+ "clock",
+ "date",
+ "difftime",
+ "time",
+ "setlocale",
+ };
+ static const char *debug_whitelist[] = {
+ "getinfo",
+ };
+
+#if USE_LUAJIT
+ static const char *jit_whitelist[] = {
+ "arch",
+ "flush",
+ "off",
+ "on",
+ "opt",
+ "os",
+ "status",
+ "version",
+ "version_num",
+ };
+#endif
+
+ m_secure = true;
+
+ lua_State *L = getStack();
+
+
+ int old_globals = backupGlobals(L);
+
+
+ // Copy safe base functions
+ lua_getglobal(L, "_G");
+ copy_safe(L, whitelist, sizeof(whitelist));
+
+ // And replace unsafe ones
+ SECURE_API(g, dofile);
+ SECURE_API(g, loadstring);
+ SECURE_API(g, require);
+ lua_pop(L, 1);
+
+
+
+ // Copy safe OS functions
+ lua_getfield(L, old_globals, "os");
+ lua_newtable(L);
+ copy_safe(L, os_whitelist, sizeof(os_whitelist));
+ lua_setglobal(L, "os");
+ lua_pop(L, 1); // Pop old OS
+
+
+ // Copy safe debug functions
+ lua_getfield(L, old_globals, "debug");
+ lua_newtable(L);
+ copy_safe(L, debug_whitelist, sizeof(debug_whitelist));
+ lua_setglobal(L, "debug");
+ lua_pop(L, 1); // Pop old debug
+#if USE_LUAJIT
// Copy safe jit functions, if they exist
lua_getfield(L, -1, "jit");
if (!lua_isnil(L, -1)) {
@@ -233,10 +315,40 @@ void ScriptApiSecurity::initializeSecurity()
lua_setglobal(L, "jit");
}
lua_pop(L, 1); // Pop old jit
+#endif
lua_pop(L, 1); // Pop globals_backup
}
+int ScriptApiSecurity::backupGlobals(lua_State *L)
+{
+ // Backup globals to the registry
+ lua_getglobal(L, "_G");
+ lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
+
+ // Replace the global environment with an empty one
+#if LUA_VERSION_NUM <= 501
+ int is_main = lua_pushthread(L); // Push the main thread
+ FATAL_ERROR_IF(!is_main, "Security: ScriptApi's Lua state "
+ "isn't the main Lua thread!");
+#endif
+ lua_newtable(L); // Create new environment
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "_G"); // Set _G of new environment
+#if LUA_VERSION_NUM >= 502 // Lua >= 5.2
+ // Set the global environment
+ lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
+#else // Lua <= 5.1
+ // Set the environment of the main thread
+ FATAL_ERROR_IF(!lua_setfenv(L, -2), "Security: Unable to set "
+ "environment of the main Lua thread!");
+ lua_pop(L, 1); // Pop thread
+#endif
+
+ // Get old globals
+ lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
+ return lua_gettop(L);
+}
bool ScriptApiSecurity::isSecure(lua_State *L)
{
@@ -294,7 +406,14 @@ bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path)
// Read the file
int ret = std::fseek(fp, 0, SEEK_END);
- CHECK_FILE_ERR(ret, fp);
+ if (ret) {
+ lua_pushfstring(L, "%s: %s", path, strerror(errno));
+ std::fclose(fp);
+ if (path) {
+ delete [] chunk_name;
+ }
+ return false;
+ }
size_t size = std::ftell(fp) - start;
char *code = new char[size];
@@ -383,9 +502,9 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1);
lua_pop(L, 1);
- const Server *server = script->getServer();
-
- if (!server) return false;
+ const IGameDef *gamedef = script->getGameDef();
+ if (!gamedef)
+ return false;
// Get mod name
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
@@ -401,7 +520,7 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
// Allow paths in mod path
// Don't bother if write access isn't important, since it will be handled later
if (write_required || write_allowed != NULL) {
- const ModSpec *mod = server->getModSpec(mod_name);
+ const ModSpec *mod = gamedef->getModSpec(mod_name);
if (mod) {
str = fs::AbsolutePath(mod->path);
if (!str.empty() && fs::PathStartsWith(abs_path, str)) {
@@ -415,7 +534,7 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
// Allow read-only access to all mod directories
if (!write_required) {
- const std::vector<ModSpec> mods = server->getMods();
+ const std::vector<ModSpec> mods = gamedef->getMods();
for (size_t i = 0; i < mods.size(); ++i) {
str = fs::AbsolutePath(mods[i].path);
if (!str.empty() && fs::PathStartsWith(abs_path, str)) {
@@ -424,7 +543,7 @@ bool ScriptApiSecurity::checkPath(lua_State *L, const char *path,
}
}
- str = fs::AbsolutePath(server->getWorldPath());
+ str = fs::AbsolutePath(gamedef->getWorldPath());
if (!str.empty()) {
// Don't allow access to other paths in the world mod/game path.
// These have to be blocked so you can't override a trusted mod
diff --git a/src/script/cpp_api/s_security.h b/src/script/cpp_api/s_security.h
index 6876108e8..f0eef00bb 100644
--- a/src/script/cpp_api/s_security.h
+++ b/src/script/cpp_api/s_security.h
@@ -41,8 +41,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class ScriptApiSecurity : virtual public ScriptApiBase
{
public:
+ int backupGlobals(lua_State *L);
// Sets up security on the ScriptApi's Lua state
void initializeSecurity();
+ void initializeSecurityClient();
// Checks if the Lua state has been secured
static bool isSecure(lua_State *L);
// Loads a file as Lua code safely (doesn't allow bytecode).
diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt
index d507dcf70..1a78580e6 100644
--- a/src/script/lua_api/CMakeLists.txt
+++ b/src/script/lua_api/CMakeLists.txt
@@ -5,7 +5,9 @@ set(common_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_itemstackmeta.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_metadata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_nodemeta.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_nodetimer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_noise.cpp
@@ -13,6 +15,7 @@ set(common_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_particles.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_rollback.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_server.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_util.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_vmanip.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_settings.cpp
@@ -20,6 +23,11 @@ set(common_SCRIPT_LUA_API_SRCS
PARENT_SCOPE)
set(client_SCRIPT_LUA_API_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_client.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_camera.cpp
PARENT_SCOPE)
-
diff --git a/src/script/lua_api/l_areastore.cpp b/src/script/lua_api/l_areastore.cpp
index 09a5c78f9..b81985a7f 100644
--- a/src/script/lua_api/l_areastore.cpp
+++ b/src/script/lua_api/l_areastore.cpp
@@ -74,7 +74,7 @@ static inline void push_areas(lua_State *L, const std::vector<Area *> &areas,
static int deserialization_helper(lua_State *L, AreaStore *as,
std::istream &is)
{
- try {
+ try {
as->deserialize(is);
} catch (const SerializationError &e) {
lua_pushboolean(L, false);
@@ -380,7 +380,7 @@ void LuaAreaStore::Register(lua_State *L)
}
const char LuaAreaStore::className[] = "AreaStore";
-const luaL_reg LuaAreaStore::methods[] = {
+const luaL_Reg LuaAreaStore::methods[] = {
luamethod(LuaAreaStore, get_area),
luamethod(LuaAreaStore, get_areas_for_pos),
luamethod(LuaAreaStore, get_areas_in_area),
diff --git a/src/script/lua_api/l_areastore.h b/src/script/lua_api/l_areastore.h
index 4bd94cebe..8292e7712 100644
--- a/src/script/lua_api/l_areastore.h
+++ b/src/script/lua_api/l_areastore.h
@@ -22,14 +22,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_base.h"
-
class AreaStore;
-class LuaAreaStore : public ModApiBase {
+class LuaAreaStore : public ModApiBase
+{
private:
-
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
static int gc_object(lua_State *L);
diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp
index 515a7d933..5d7ba9640 100644
--- a/src/script/lua_api/l_base.cpp
+++ b/src/script/lua_api/l_base.cpp
@@ -37,6 +37,18 @@ Server *ModApiBase::getServer(lua_State *L)
return getScriptApiBase(L)->getServer();
}
+#ifndef SERVER
+Client *ModApiBase::getClient(lua_State *L)
+{
+ return getScriptApiBase(L)->getClient();
+}
+#endif
+
+IGameDef *ModApiBase::getGameDef(lua_State *L)
+{
+ return getScriptApiBase(L)->getGameDef();
+}
+
Environment *ModApiBase::getEnv(lua_State *L)
{
return getScriptApiBase(L)->getEnv();
@@ -62,17 +74,13 @@ std::string ModApiBase::getCurrentModPath(lua_State *L)
}
-bool ModApiBase::registerFunction(
- lua_State *L,
- const char *name,
- lua_CFunction fct,
- int top)
+bool ModApiBase::registerFunction(lua_State *L, const char *name,
+ lua_CFunction func, int top)
{
- //TODO check presence first!
+ // TODO: Check presence first!
- lua_pushstring(L,name);
- lua_pushcfunction(L,fct);
- lua_settable(L, top);
+ lua_pushcfunction(L, func);
+ lua_setfield(L, top, name);
return true;
}
diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h
index 641013dfd..af89afd93 100644
--- a/src/script/lua_api/l_base.h
+++ b/src/script/lua_api/l_base.h
@@ -22,12 +22,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_types.h"
#include "common/c_internal.h"
+#include "gamedef.h"
extern "C" {
#include <lua.h>
#include <lauxlib.h>
}
+#ifndef SERVER
+#include "client.h"
+#endif
+
class ScriptApiBase;
class Server;
class Environment;
@@ -38,6 +43,12 @@ class ModApiBase {
public:
static ScriptApiBase* getScriptApiBase(lua_State *L);
static Server* getServer(lua_State *L);
+ #ifndef SERVER
+ static Client* getClient(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 "."
@@ -57,9 +68,8 @@ public:
static bool registerFunction(lua_State *L,
const char* name,
- lua_CFunction fct,
- int top
- );
+ lua_CFunction func,
+ int top);
};
#endif /* L_BASE_H_ */
diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp
new file mode 100644
index 000000000..862384198
--- /dev/null
+++ b/src/script/lua_api/l_camera.cpp
@@ -0,0 +1,202 @@
+#include "script/common/c_converter.h"
+#include "l_camera.h"
+#include "l_internal.h"
+#include "content_cao.h"
+#include "camera.h"
+
+LuaCamera::LuaCamera(Camera *m)
+{
+ m_camera = m;
+}
+
+void LuaCamera::create(lua_State *L, Camera *m)
+{
+ LuaCamera *o = new LuaCamera(m);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+
+ int camera_object = lua_gettop(L);
+
+ lua_getglobal(L, "core");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int coretable = lua_gettop(L);
+
+ lua_pushvalue(L, camera_object);
+ lua_setfield(L, coretable, "camera");
+}
+
+int LuaCamera::l_set_camera_mode(lua_State *L)
+{
+ Camera *camera = getobject(L, 1);
+ GenericCAO *playercao = getClient(L)->getEnv().getLocalPlayer()->getCAO();
+ if (!camera)
+ return 0;
+ sanity_check(playercao);
+ if (!lua_isnumber(L, 2))
+ return 0;
+
+ camera->setCameraMode((CameraMode)((int)lua_tonumber(L, 2)));
+ playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
+ playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
+ return 0;
+}
+
+int LuaCamera::l_get_camera_mode(lua_State *L)
+{
+ Camera *camera = getobject(L, 1);
+ if (!camera)
+ return 0;
+
+ lua_pushnumber(L, (int)camera->getCameraMode());
+
+ return 1;
+}
+
+int LuaCamera::l_get_fov(lua_State *L)
+{
+ Camera *camera = getobject(L, 1);
+ if (!camera)
+ return 0;
+
+ lua_newtable(L);
+ lua_pushnumber(L, camera->getFovX() * core::DEGTORAD);
+ lua_setfield(L, -2, "x");
+ lua_pushnumber(L, camera->getFovY() * core::DEGTORAD);
+ lua_setfield(L, -2, "y");
+ lua_pushnumber(L, camera->getCameraNode()->getFOV() * core::RADTODEG);
+ lua_setfield(L, -2, "actual");
+ lua_pushnumber(L, camera->getFovMax() * core::RADTODEG);
+ lua_setfield(L, -2, "max");
+ return 1;
+}
+
+int LuaCamera::l_get_pos(lua_State *L)
+{
+ Camera *camera = getobject(L, 1);
+ if (!camera)
+ return 0;
+
+ push_v3f(L, camera->getPosition());
+ return 1;
+}
+
+int LuaCamera::l_get_offset(lua_State *L)
+{
+ Camera *camera = getobject(L, 1);
+ if (!camera)
+ return 0;
+
+ push_v3s16(L, camera->getOffset());
+ return 1;
+}
+
+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(cos(pitch) * cos(yaw), sin(pitch), cos(pitch) * sin(yaw));
+
+ push_v3f(L, v);
+ return 1;
+}
+
+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);
+ return 1;
+}
+
+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);
+ return 1;
+}
+
+int LuaCamera::l_get_aspect_ratio(lua_State *L)
+{
+ Camera *camera = getobject(L, 1);
+ if (!camera)
+ return 0;
+
+ lua_pushnumber(L, camera->getCameraNode()->getAspectRatio());
+ return 1;
+}
+
+LuaCamera *LuaCamera::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 *(LuaCamera **)ud;
+}
+
+Camera *LuaCamera::getobject(LuaCamera *ref)
+{
+ return ref->m_camera;
+}
+
+Camera *LuaCamera::getobject(lua_State *L, int narg)
+{
+ LuaCamera *ref = checkobject(L, narg);
+ assert(ref);
+ Camera *camera = getobject(ref);
+ if (!camera)
+ return NULL;
+ return camera;
+}
+
+int LuaCamera::gc_object(lua_State *L)
+{
+ LuaCamera *o = *(LuaCamera **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+void LuaCamera::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1);
+
+ luaL_openlib(L, 0, methods, 0);
+ lua_pop(L, 1);
+}
+
+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}};
diff --git a/src/script/lua_api/l_camera.h b/src/script/lua_api/l_camera.h
new file mode 100644
index 000000000..04921ad03
--- /dev/null
+++ b/src/script/lua_api/l_camera.h
@@ -0,0 +1,44 @@
+#ifndef L_CAMERA_H
+#define L_CAMERA_H
+
+#include "l_base.h"
+
+class Camera;
+
+class LuaCamera : public ModApiBase
+{
+private:
+ static const char className[];
+ static const luaL_Reg methods[];
+
+ // garbage collector
+ static int gc_object(lua_State *L);
+
+ static int l_set_camera_mode(lua_State *L);
+ static int l_get_camera_mode(lua_State *L);
+
+ static int l_get_fov(lua_State *L);
+
+ static int l_get_pos(lua_State *L);
+ static int l_get_offset(lua_State *L);
+ static int l_get_look_dir(lua_State *L);
+ static int l_get_look_vertical(lua_State *L);
+ static int l_get_look_horizontal(lua_State *L);
+ static int l_get_aspect_ratio(lua_State *L);
+
+ Camera *m_camera;
+
+public:
+ LuaCamera(Camera *m);
+ ~LuaCamera() {}
+
+ static void create(lua_State *L, Camera *m);
+
+ static LuaCamera *checkobject(lua_State *L, int narg);
+ static Camera *getobject(LuaCamera *ref);
+ static Camera *getobject(lua_State *L, int narg);
+
+ static void Register(lua_State *L);
+};
+
+#endif // L_CAMERA_H
diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp
new file mode 100644
index 000000000..3c2955bcd
--- /dev/null
+++ b/src/script/lua_api/l_client.cpp
@@ -0,0 +1,356 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "l_client.h"
+#include "clientenvironment.h"
+#include "common/c_content.h"
+#include "common/c_converter.h"
+#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 "mainmenumanager.h"
+#include "map.h"
+#include "util/string.h"
+#include "nodedef.h"
+
+extern MainGameCallback *g_gamecallback;
+
+int ModApiClient::l_get_current_modname(lua_State *L)
+{
+ lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
+ return 1;
+}
+
+// get_last_run_mod()
+int ModApiClient::l_get_last_run_mod(lua_State *L)
+{
+ lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
+ const char *current_mod = lua_tostring(L, -1);
+ if (current_mod == NULL || current_mod[0] == '\0') {
+ lua_pop(L, 1);
+ lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
+ }
+ return 1;
+}
+
+// set_last_run_mod(modname)
+int ModApiClient::l_set_last_run_mod(lua_State *L)
+{
+ if (!lua_isstring(L, 1))
+ return 0;
+
+ const char *mod = lua_tostring(L, 1);
+ getScriptApiBase(L)->setOriginDirect(mod);
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+// print(text)
+int ModApiClient::l_print(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ std::string text = luaL_checkstring(L, 1);
+ rawstream << text << std::endl;
+ return 0;
+}
+
+// display_chat_message(message)
+int ModApiClient::l_display_chat_message(lua_State *L)
+{
+ if (!lua_isstring(L, 1))
+ return 0;
+
+ std::string message = luaL_checkstring(L, 1);
+ getClient(L)->pushToChatQueue(utf8_to_wide(message));
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+// send_chat_message(message)
+int ModApiClient::l_send_chat_message(lua_State *L)
+{
+ if (!lua_isstring(L, 1))
+ return 0;
+ std::string message = luaL_checkstring(L, 1);
+ getClient(L)->sendChatMessage(utf8_to_wide(message));
+ return 0;
+}
+
+// clear_out_chat_queue()
+int ModApiClient::l_clear_out_chat_queue(lua_State *L)
+{
+ getClient(L)->clearOutChatQueue();
+ return 0;
+}
+
+// get_player_names()
+int ModApiClient::l_get_player_names(lua_State *L)
+{
+ const std::list<std::string> &plist = getClient(L)->getConnectedPlayerNames();
+ lua_createtable(L, plist.size(), 0);
+ int newTable = lua_gettop(L);
+ int index = 1;
+ std::list<std::string>::const_iterator iter;
+ for (iter = plist.begin(); iter != plist.end(); ++iter) {
+ lua_pushstring(L, (*iter).c_str());
+ lua_rawseti(L, newTable, index);
+ index++;
+ }
+ return 1;
+}
+
+// show_formspec(formspec)
+int ModApiClient::l_show_formspec(lua_State *L)
+{
+ if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
+ return 0;
+
+ ClientEvent event;
+ event.type = CE_SHOW_LOCAL_FORMSPEC;
+ event.show_formspec.formname = new std::string(luaL_checkstring(L, 1));
+ event.show_formspec.formspec = new std::string(luaL_checkstring(L, 2));
+ getClient(L)->pushToEventQueue(event);
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+// send_respawn()
+int ModApiClient::l_send_respawn(lua_State *L)
+{
+ getClient(L)->sendRespawn();
+ return 0;
+}
+
+// disconnect()
+int ModApiClient::l_disconnect(lua_State *L)
+{
+ // Stops badly written Lua code form causing boot loops
+ if (getClient(L)->isShutdown()) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
+
+ g_gamecallback->disconnect();
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+// gettext(text)
+int ModApiClient::l_gettext(lua_State *L)
+{
+ std::string text = strgettext(std::string(luaL_checkstring(L, 1)));
+ lua_pushstring(L, text.c_str());
+
+ return 1;
+}
+
+// get_node(pos)
+// pos = {x=num, y=num, z=num}
+int ModApiClient::l_get_node(lua_State *L)
+{
+ // pos
+ v3s16 pos = read_v3s16(L, 1);
+ // Do it
+ bool pos_ok;
+ MapNode n = getClient(L)->getNode(pos, &pos_ok);
+ // Return node
+ pushnode(L, n, getClient(L)->ndef());
+ return 1;
+}
+
+// get_node_or_nil(pos)
+// pos = {x=num, y=num, z=num}
+int ModApiClient::l_get_node_or_nil(lua_State *L)
+{
+ // pos
+ v3s16 pos = read_v3s16(L, 1);
+ // Do it
+ bool pos_ok;
+ MapNode n = getClient(L)->getNode(pos, &pos_ok);
+ if (pos_ok) {
+ // Return node
+ pushnode(L, n, getClient(L)->ndef());
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+int ModApiClient::l_get_wielded_item(lua_State *L)
+{
+ Client *client = getClient(L);
+
+ Inventory local_inventory(client->idef());
+ client->getLocalInventory(local_inventory);
+
+ InventoryList *mlist = local_inventory.getList("main");
+
+ if (mlist && client->getPlayerItem() < mlist->getSize()) {
+ LuaItemStack::create(L, mlist->getItem(client->getPlayerItem()));
+ } else {
+ LuaItemStack::create(L, ItemStack());
+ }
+ 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);
+ NodeMetaRef::createClient(L, meta);
+ return 1;
+}
+
+int ModApiClient::l_sound_play(lua_State *L)
+{
+ ISoundManager *sound = getClient(L)->getSoundManager();
+
+ SimpleSoundSpec spec;
+ read_soundspec(L, 1, spec);
+ float gain = 1.0;
+ bool looped = false;
+ s32 handle;
+
+ if (lua_istable(L, 2)) {
+ getfloatfield(L, 2, "gain", gain);
+ getboolfield(L, 2, "loop", looped);
+
+ lua_getfield(L, 2, "pos");
+ if (!lua_isnil(L, -1)) {
+ v3f pos = read_v3f(L, -1) * BS;
+ lua_pop(L, 1);
+ handle = sound->playSoundAt(
+ spec.name, looped, gain * spec.gain, pos);
+ lua_pushinteger(L, handle);
+ return 1;
+ }
+ }
+
+ handle = sound->playSound(spec.name, looped, gain * spec.gain);
+ lua_pushinteger(L, handle);
+
+ return 1;
+}
+
+int ModApiClient::l_sound_stop(lua_State *L)
+{
+ u32 handle = luaL_checkinteger(L, 1);
+
+ getClient(L)->getSoundManager()->stopSound(handle);
+
+ return 0;
+}
+
+// get_server_info()
+int ModApiClient::l_get_server_info(lua_State *L)
+{
+ Client *client = getClient(L);
+ Address serverAddress = client->getServerAddress();
+ lua_newtable(L);
+ lua_pushstring(L, client->getAddressName().c_str());
+ lua_setfield(L, -2, "address");
+ lua_pushstring(L, serverAddress.serializeString().c_str());
+ lua_setfield(L, -2, "ip");
+ lua_pushinteger(L, serverAddress.getPort());
+ lua_setfield(L, -2, "port");
+ lua_pushinteger(L, client->getProtoVersion());
+ lua_setfield(L, -2, "protocol_version");
+ return 1;
+}
+
+// get_item_def(itemstring)
+int ModApiClient::l_get_item_def(lua_State *L)
+{
+ IGameDef *gdef = getGameDef(L);
+ assert(gdef);
+
+ IItemDefManager *idef = gdef->idef();
+ assert(idef);
+
+ if (!lua_isstring(L, 1))
+ return 0;
+
+ const std::string &name(lua_tostring(L, 1));
+ if (!idef->isKnown(name))
+ return 0;
+ const ItemDefinition &def = idef->get(name);
+
+ push_item_definition_full(L, def);
+
+ return 1;
+}
+
+// get_node_def(nodename)
+int ModApiClient::l_get_node_def(lua_State *L)
+{
+ IGameDef *gdef = getGameDef(L);
+ assert(gdef);
+
+ INodeDefManager *ndef = gdef->ndef();
+ assert(ndef);
+
+ if (!lua_isstring(L, 1))
+ return 0;
+
+ const std::string &name = lua_tostring(L, 1);
+ const ContentFeatures &cf = ndef->get(ndef->getId(name));
+ if (cf.name != name) // Unknown node. | name = <whatever>, cf.name = ignore
+ return 0;
+
+ push_content_features(L, cf);
+
+ return 1;
+}
+
+int ModApiClient::l_take_screenshot(lua_State *L)
+{
+ Client *client = getClient(L);
+ client->makeScreenshot(client->getDevice());
+ return 0;
+}
+
+void ModApiClient::Initialize(lua_State *L, int top)
+{
+ API_FCT(get_current_modname);
+ API_FCT(print);
+ API_FCT(display_chat_message);
+ API_FCT(send_chat_message);
+ API_FCT(clear_out_chat_queue);
+ API_FCT(get_player_names);
+ API_FCT(set_last_run_mod);
+ API_FCT(get_last_run_mod);
+ API_FCT(show_formspec);
+ API_FCT(send_respawn);
+ API_FCT(gettext);
+ API_FCT(get_node);
+ 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(get_server_info);
+ API_FCT(get_item_def);
+ API_FCT(get_node_def);
+ API_FCT(take_screenshot);
+}
diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h
new file mode 100644
index 000000000..fe5780fb1
--- /dev/null
+++ b/src/script/lua_api/l_client.h
@@ -0,0 +1,98 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef L_CLIENT_H_
+#define L_CLIENT_H_
+
+#include "lua_api/l_base.h"
+#include "itemdef.h"
+#include "tool.h"
+
+class ModApiClient : public ModApiBase
+{
+private:
+ // get_current_modname()
+ static int l_get_current_modname(lua_State *L);
+
+ // print(text)
+ static int l_print(lua_State *L);
+
+ // display_chat_message(message)
+ static int l_display_chat_message(lua_State *L);
+
+ // send_chat_message(message)
+ static int l_send_chat_message(lua_State *L);
+
+ // clear_out_chat_queue()
+ static int l_clear_out_chat_queue(lua_State *L);
+
+ // get_player_names()
+ static int l_get_player_names(lua_State *L);
+
+ // show_formspec(name, formspec)
+ static int l_show_formspec(lua_State *L);
+
+ // send_respawn()
+ static int l_send_respawn(lua_State *L);
+
+ // disconnect()
+ static int l_disconnect(lua_State *L);
+
+ // gettext(text)
+ static int l_gettext(lua_State *L);
+
+ // get_last_run_mod(n)
+ static int l_get_last_run_mod(lua_State *L);
+
+ // set_last_run_mod(modname)
+ static int l_set_last_run_mod(lua_State *L);
+
+ // get_node(pos)
+ static int l_get_node(lua_State *L);
+
+ // get_node_or_nil(pos)
+ static int l_get_node_or_nil(lua_State *L);
+
+ // get_wielded_item()
+ static int l_get_wielded_item(lua_State *L);
+
+ // get_meta(pos)
+ static int l_get_meta(lua_State *L);
+
+ static int l_sound_play(lua_State *L);
+
+ static int l_sound_stop(lua_State *L);
+
+ // get_server_info()
+ static int l_get_server_info(lua_State *L);
+
+ // get_item_def(itemstring)
+ static int l_get_item_def(lua_State *L);
+
+ // get_node_def(nodename)
+ static int l_get_node_def(lua_State *L);
+
+ static int l_take_screenshot(lua_State *L);
+
+public:
+ static void Initialize(lua_State *L, int top);
+};
+
+#endif
diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp
index 2236566de..315391856 100644
--- a/src/script/lua_api/l_craft.cpp
+++ b/src/script/lua_api/l_craft.cpp
@@ -414,7 +414,7 @@ static void push_craft_recipe(lua_State *L, IGameDef *gdef,
lua_newtable(L); // items
std::vector<ItemStack>::const_iterator iter = input.items.begin();
- for (u16 j = 1; iter != input.items.end(); iter++, j++) {
+ for (u16 j = 1; iter != input.items.end(); ++iter, j++) {
if (iter->empty())
continue;
lua_pushstring(L, iter->name.c_str());
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index 68d10308c..b8b6bc5ba 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -25,7 +25,7 @@ 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 "scripting_game.h"
+#include "scripting_server.h"
#include "environment.h"
#include "server.h"
#include "nodedef.h"
@@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "treegen.h"
#include "emerge.h"
#include "pathfinder.h"
+#include "face_position_cache.h"
struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
{
@@ -49,7 +50,7 @@ struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
u32 active_object_count, u32 active_object_count_wider)
{
- GameScripting *scriptIface = env->getScriptIface();
+ ServerScripting *scriptIface = env->getScriptIface();
scriptIface->realityCheck();
lua_State *L = scriptIface->getStack();
@@ -92,7 +93,7 @@ void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
void LuaLBM::trigger(ServerEnvironment *env, v3s16 p, MapNode n)
{
- GameScripting *scriptIface = env->getScriptIface();
+ ServerScripting *scriptIface = env->getScriptIface();
scriptIface->realityCheck();
lua_State *L = scriptIface->getStack();
@@ -284,7 +285,7 @@ int ModApiEnvMod::l_place_node(lua_State *L)
return 1;
}
// Create item to place
- ItemStack item(ndef->get(n).name, 1, 0, "", idef);
+ ItemStack item(ndef->get(n).name, 1, 0, idef);
// Make pointed position
PointedThing pointed;
pointed.type = POINTEDTHING_NODE;
@@ -347,7 +348,10 @@ 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)
{
- GET_ENV_PTR;
+ Environment *env = getEnv(L);
+ if (!env) {
+ return 0;
+ }
v3s16 pos = read_v3s16(L, 1);
MapNode n = env->getMap().getNodeNoEx(pos);
@@ -359,7 +363,10 @@ 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)
{
- GET_ENV_PTR;
+ Environment *env = getEnv(L);
+ if (!env) {
+ return 0;
+ }
v3s16 pos = read_v3s16(L, 1);
MapNode n = env->getMap().getNodeNoEx(pos);
@@ -440,7 +447,7 @@ int ModApiEnvMod::l_get_node_timer(lua_State *L)
return 1;
}
-// add_entity(pos, entityname) -> ObjectRef or nil
+// add_entity(pos, entityname, [staticdata]) -> ObjectRef or nil
// pos = {x=num, y=num, z=num}
int ModApiEnvMod::l_add_entity(lua_State *L)
{
@@ -450,8 +457,10 @@ int ModApiEnvMod::l_add_entity(lua_State *L)
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, "");
+ 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)
@@ -470,7 +479,7 @@ int ModApiEnvMod::l_add_item(lua_State *L)
// pos
//v3f pos = checkFloatPos(L, 1);
// item
- ItemStack item = read_item(L, 2,getServer(L));
+ ItemStack item = read_item(L, 2,getServer(L)->idef());
if(item.empty() || !item.isKnown(getServer(L)->idef()))
return 0;
@@ -526,7 +535,7 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
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++) {
+ for(u32 i = 0; iter != ids.end(); ++iter) {
ServerActiveObject *obj = env->getActiveObject(*iter);
// Insert object reference into table
script->objectrefGetOrCreate(L, obj);
@@ -556,11 +565,14 @@ int ModApiEnvMod::l_set_timeofday(lua_State *L)
// get_timeofday() -> 0...1
int ModApiEnvMod::l_get_timeofday(lua_State *L)
{
- GET_ENV_PTR;
+ Environment *env = getEnv(L);
+ if (!env) {
+ return 0;
+ }
// Do it
int timeofday_mh = env->getTimeOfDay();
- float timeofday_f = (float)timeofday_mh / 24000.0;
+ float timeofday_f = (float)timeofday_mh / 24000.0f;
lua_pushnumber(L, timeofday_f);
return 1;
}
@@ -568,7 +580,10 @@ int ModApiEnvMod::l_get_timeofday(lua_State *L)
// get_day_count() -> int
int ModApiEnvMod::l_get_day_count(lua_State *L)
{
- GET_ENV_PTR;
+ Environment *env = getEnv(L);
+ if (!env) {
+ return 0;
+ }
lua_pushnumber(L, env->getDayCount());
return 1;
@@ -585,37 +600,40 @@ int ModApiEnvMod::l_get_gametime(lua_State *L)
}
-// find_node_near(pos, radius, nodenames) -> pos or nil
+// find_node_near(pos, radius, nodenames, search_center) -> pos or nil
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
int ModApiEnvMod::l_find_node_near(lua_State *L)
{
- GET_ENV_PTR;
+ Environment *env = getEnv(L);
+ if (!env) {
+ return 0;
+ }
- INodeDefManager *ndef = getServer(L)->ndef();
+ INodeDefManager *ndef = getGameDef(L)->ndef();
v3s16 pos = read_v3s16(L, 1);
int radius = luaL_checkinteger(L, 2);
std::set<content_t> filter;
- if(lua_istable(L, 3)){
- int table = 3;
+ if (lua_istable(L, 3)) {
lua_pushnil(L);
- while(lua_next(L, table) != 0){
+ while (lua_next(L, 3) != 0) {
// key at index -2 and value at index -1
luaL_checktype(L, -1, LUA_TSTRING);
ndef->getIds(lua_tostring(L, -1), filter);
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
- } else if(lua_isstring(L, 3)){
+ } else if (lua_isstring(L, 3)) {
ndef->getIds(lua_tostring(L, 3), filter);
}
- for(int d=1; d<=radius; d++){
+ int start_radius = (lua_toboolean(L, 4)) ? 0 : 1;
+ for (int d = start_radius; d <= radius; d++) {
std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
- for(std::vector<v3s16>::iterator i = list.begin();
- i != list.end(); ++i){
+ for (std::vector<v3s16>::iterator i = list.begin();
+ i != list.end(); ++i) {
v3s16 p = pos + (*i);
content_t c = env->getMap().getNodeNoEx(p).getContent();
- if(filter.count(c) != 0){
+ if (filter.count(c) != 0) {
push_v3s16(L, p);
return 1;
}
@@ -830,6 +848,36 @@ int ModApiEnvMod::l_line_of_sight(lua_State *L)
return 1;
}
+// fix_light(p1, p2)
+int ModApiEnvMod::l_fix_light(lua_State *L)
+{
+ GET_ENV_PTR;
+
+ v3s16 blockpos1 = getContainerPos(read_v3s16(L, 1), MAP_BLOCKSIZE);
+ v3s16 blockpos2 = getContainerPos(read_v3s16(L, 2), MAP_BLOCKSIZE);
+ ServerMap &map = env->getServerMap();
+ std::map<v3s16, MapBlock *> modified_blocks;
+ bool success = true;
+ v3s16 blockpos;
+ for (blockpos.X = blockpos1.X; blockpos.X <= blockpos2.X; blockpos.X++)
+ for (blockpos.Y = blockpos1.Y; blockpos.Y <= blockpos2.Y; blockpos.Y++)
+ for (blockpos.Z = blockpos1.Z; blockpos.Z <= blockpos2.Z; blockpos.Z++) {
+ success = success & map.repairBlockLight(blockpos, &modified_blocks);
+ }
+ if (modified_blocks.size() > 0) {
+ MapEditEvent event;
+ event.type = MEET_OTHER;
+ for (std::map<v3s16, MapBlock *>::iterator it = modified_blocks.begin();
+ it != modified_blocks.end(); ++it)
+ event.modified_blocks.insert(it->first);
+
+ map.dispatchEvent(&event);
+ }
+ lua_pushboolean(L, success);
+
+ return 1;
+}
+
// emerge_area(p1, p2, [callback, context])
// emerge mapblocks in area p1..p2, calls callback with context upon completion
int ModApiEnvMod::l_emerge_area(lua_State *L)
@@ -938,8 +986,7 @@ int ModApiEnvMod::l_find_path(lua_State *L)
lua_newtable(L);
int top = lua_gettop(L);
unsigned int index = 1;
- for (std::vector<v3s16>::iterator i = path.begin(); i != path.end();i++)
- {
+ for (std::vector<v3s16>::iterator i = path.begin(); i != path.end(); ++i) {
lua_pushnumber(L,index);
push_v3s16(L, *i);
lua_settable(L, top);
@@ -1072,6 +1119,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
API_FCT(find_node_near);
API_FCT(find_nodes_in_area);
API_FCT(find_nodes_in_area_under_air);
+ API_FCT(fix_light);
API_FCT(emerge_area);
API_FCT(delete_area);
API_FCT(get_perlin);
@@ -1085,3 +1133,12 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
API_FCT(forceload_block);
API_FCT(forceload_free_block);
}
+
+void ModApiEnvMod::InitializeClient(lua_State *L, int top)
+{
+ API_FCT(get_timeofday);
+ API_FCT(get_day_count);
+ API_FCT(get_node_max_level);
+ API_FCT(get_node_level);
+ API_FCT(find_node_near);
+}
diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h
index 89dd7978f..7ce19b085 100644
--- a/src/script/lua_api/l_env.h
+++ b/src/script/lua_api/l_env.h
@@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define L_ENV_H_
#include "lua_api/l_base.h"
-#include "environment.h"
+#include "serverenvironment.h"
class ModApiEnvMod : public ModApiBase {
private:
@@ -116,7 +116,7 @@ private:
// get_day_count() -> int
static int l_get_day_count(lua_State *L);
- // find_node_near(pos, radius, nodenames) -> pos or nil
+ // find_node_near(pos, radius, nodenames, search_center) -> pos or nil
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
static int l_find_node_near(lua_State *L);
@@ -128,6 +128,9 @@ private:
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
static int l_find_nodes_in_area_under_air(lua_State *L);
+ // fix_light(p1, p2) -> true/false
+ static int l_fix_light(lua_State *L);
+
// emerge_area(p1, p2)
static int l_emerge_area(lua_State *L);
@@ -173,6 +176,7 @@ private:
public:
static void Initialize(lua_State *L, int top);
+ static void InitializeClient(lua_State *L, int top);
static struct EnumString es_ClearObjectsMode[];
};
@@ -199,11 +203,11 @@ public:
m_simple_catch_up(simple_catch_up)
{
}
- virtual std::set<std::string> getTriggerContents()
+ virtual const std::set<std::string> &getTriggerContents() const
{
return m_trigger_contents;
}
- virtual std::set<std::string> getRequiredNeighbors()
+ virtual const std::set<std::string> &getRequiredNeighbors() const
{
return m_required_neighbors;
}
@@ -242,7 +246,7 @@ public:
};
struct ScriptCallbackState {
- GameScripting *script;
+ ServerScripting *script;
int callback_ref;
int args_ref;
unsigned int refcount;
diff --git a/src/script/lua_api/l_internal.h b/src/script/lua_api/l_internal.h
index 456c8fcce..e9b689931 100644
--- a/src/script/lua_api/l_internal.h
+++ b/src/script/lua_api/l_internal.h
@@ -30,22 +30,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_internal.h"
#define luamethod(class, name) {#name, class::l_##name}
-#define API_FCT(name) registerFunction(L, #name, l_##name,top)
-#define ASYNC_API_FCT(name) engine.registerFunction(#name, l_##name)
+#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
-/*
-#if (defined(WIN32) || defined(_WIN32_WCE))
- #define NO_MAP_LOCK_REQUIRED
-#else
- #include "profiler.h"
- #define NO_MAP_LOCK_REQUIRED \
- ScopeProfiler nolocktime(g_profiler,"Scriptapi: unlockable time",SPT_ADD)
-#endif
-*/
-
#define GET_ENV_PTR_NO_MAP_LOCK \
ServerEnvironment *env = (ServerEnvironment *)getEnv(L); \
if (env == NULL) \
diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp
index 38eade609..f5e76a7b6 100644
--- a/src/script/lua_api/l_inventory.cpp
+++ b/src/script/lua_api/l_inventory.cpp
@@ -194,7 +194,7 @@ int InvRef::l_set_stack(lua_State *L)
InvRef *ref = checkobject(L, 1);
const char *listname = luaL_checkstring(L, 2);
int i = luaL_checknumber(L, 3) - 1;
- ItemStack newitem = read_item(L, 4, getServer(L));
+ ItemStack newitem = read_item(L, 4, getServer(L)->idef());
InventoryList *list = getlist(L, ref, listname);
if(list != NULL && i >= 0 && i < (int) list->getSize()){
list->changeItem(i, newitem);
@@ -295,7 +295,7 @@ int InvRef::l_add_item(lua_State *L)
NO_MAP_LOCK_REQUIRED;
InvRef *ref = checkobject(L, 1);
const char *listname = luaL_checkstring(L, 2);
- ItemStack item = read_item(L, 3, getServer(L));
+ ItemStack item = read_item(L, 3, getServer(L)->idef());
InventoryList *list = getlist(L, ref, listname);
if(list){
ItemStack leftover = list->addItem(item);
@@ -315,7 +315,7 @@ int InvRef::l_room_for_item(lua_State *L)
NO_MAP_LOCK_REQUIRED;
InvRef *ref = checkobject(L, 1);
const char *listname = luaL_checkstring(L, 2);
- ItemStack item = read_item(L, 3, getServer(L));
+ ItemStack item = read_item(L, 3, getServer(L)->idef());
InventoryList *list = getlist(L, ref, listname);
if(list){
lua_pushboolean(L, list->roomForItem(item));
@@ -332,7 +332,7 @@ int InvRef::l_contains_item(lua_State *L)
NO_MAP_LOCK_REQUIRED;
InvRef *ref = checkobject(L, 1);
const char *listname = luaL_checkstring(L, 2);
- ItemStack item = read_item(L, 3, getServer(L));
+ ItemStack item = read_item(L, 3, getServer(L)->idef());
InventoryList *list = getlist(L, ref, listname);
if(list){
lua_pushboolean(L, list->containsItem(item));
@@ -349,7 +349,7 @@ int InvRef::l_remove_item(lua_State *L)
NO_MAP_LOCK_REQUIRED;
InvRef *ref = checkobject(L, 1);
const char *listname = luaL_checkstring(L, 2);
- ItemStack item = read_item(L, 3, getServer(L));
+ ItemStack item = read_item(L, 3, getServer(L)->idef());
InventoryList *list = getlist(L, ref, listname);
if(list){
ItemStack removed = list->removeItem(item);
@@ -463,7 +463,7 @@ void InvRef::Register(lua_State *L)
}
const char InvRef::className[] = "InvRef";
-const luaL_reg InvRef::methods[] = {
+const luaL_Reg InvRef::methods[] = {
luamethod(InvRef, is_empty),
luamethod(InvRef, get_size),
luamethod(InvRef, set_size),
diff --git a/src/script/lua_api/l_inventory.h b/src/script/lua_api/l_inventory.h
index cc5333965..91d41c0d0 100644
--- a/src/script/lua_api/l_inventory.h
+++ b/src/script/lua_api/l_inventory.h
@@ -36,7 +36,7 @@ private:
InventoryLocation m_loc;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
static InvRef *checkobject(lua_State *L, int narg);
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index ff0baea14..0e4fc4ef0 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "lua_api/l_item.h"
+#include "lua_api/l_itemstackmeta.h"
#include "lua_api/l_internal.h"
#include "common/c_converter.h"
#include "common/c_content.h"
@@ -137,16 +138,28 @@ int LuaItemStack::l_set_wear(lua_State *L)
return 1;
}
+// get_meta(self) -> string
+int LuaItemStack::l_get_meta(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ LuaItemStack *o = checkobject(L, 1);
+ ItemStackMetaRef::create(L, &o->m_stack);
+ return 1;
+}
+
+// DEPRECATED
// get_metadata(self) -> string
int LuaItemStack::l_get_metadata(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack;
- lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
+ const std::string &value = item.metadata.getString("");
+ lua_pushlstring(L, value.c_str(), value.size());
return 1;
}
+// DEPRECATED
// set_metadata(self, string)
int LuaItemStack::l_set_metadata(lua_State *L)
{
@@ -156,7 +169,7 @@ int LuaItemStack::l_set_metadata(lua_State *L)
size_t len = 0;
const char *ptr = luaL_checklstring(L, 2, &len);
- item.metadata.assign(ptr, len);
+ item.metadata.setString("", std::string(ptr, len));
lua_pushboolean(L, true);
return 1;
@@ -177,7 +190,7 @@ int LuaItemStack::l_replace(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
LuaItemStack *o = checkobject(L, 1);
- o->m_stack = read_item(L,2,getServer(L));
+ o->m_stack = read_item(L, 2, getGameDef(L)->idef());
lua_pushboolean(L, true);
return 1;
}
@@ -211,8 +224,24 @@ int LuaItemStack::l_to_table(lua_State *L)
lua_setfield(L, -2, "count");
lua_pushinteger(L, item.wear);
lua_setfield(L, -2, "wear");
- lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
+
+ const std::string &metadata_str = item.metadata.getString("");
+ lua_pushlstring(L, metadata_str.c_str(), metadata_str.size());
lua_setfield(L, -2, "metadata");
+
+ lua_newtable(L);
+ const StringMap &fields = item.metadata.getStrings();
+ for (StringMap::const_iterator it = fields.begin();
+ it != fields.end(); ++it) {
+ const std::string &name = it->first;
+ if (name.empty())
+ continue;
+ const std::string &value = it->second;
+ lua_pushlstring(L, name.c_str(), name.size());
+ lua_pushlstring(L, value.c_str(), value.size());
+ lua_settable(L, -3);
+ }
+ lua_setfield(L, -2, "meta");
}
return 1;
}
@@ -223,7 +252,7 @@ int LuaItemStack::l_get_stack_max(lua_State *L)
NO_MAP_LOCK_REQUIRED;
LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack;
- lua_pushinteger(L, item.getStackMax(getServer(L)->idef()));
+ lua_pushinteger(L, item.getStackMax(getGameDef(L)->idef()));
return 1;
}
@@ -233,7 +262,7 @@ int LuaItemStack::l_get_free_space(lua_State *L)
NO_MAP_LOCK_REQUIRED;
LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack;
- lua_pushinteger(L, item.freeSpace(getServer(L)->idef()));
+ lua_pushinteger(L, item.freeSpace(getGameDef(L)->idef()));
return 1;
}
@@ -244,7 +273,7 @@ int LuaItemStack::l_is_known(lua_State *L)
NO_MAP_LOCK_REQUIRED;
LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack;
- bool is_known = item.isKnown(getServer(L)->idef());
+ bool is_known = item.isKnown(getGameDef(L)->idef());
lua_pushboolean(L, is_known);
return 1;
}
@@ -280,7 +309,7 @@ int LuaItemStack::l_get_tool_capabilities(lua_State *L)
LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack;
const ToolCapabilities &prop =
- item.getToolCapabilities(getServer(L)->idef());
+ item.getToolCapabilities(getGameDef(L)->idef());
push_tool_capabilities(L, prop);
return 1;
}
@@ -295,7 +324,7 @@ int LuaItemStack::l_add_wear(lua_State *L)
LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack;
int amount = lua_tointeger(L, 2);
- bool result = item.addWear(amount, getServer(L)->idef());
+ bool result = item.addWear(amount, getGameDef(L)->idef());
lua_pushboolean(L, result);
return 1;
}
@@ -307,8 +336,8 @@ int LuaItemStack::l_add_item(lua_State *L)
NO_MAP_LOCK_REQUIRED;
LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack;
- ItemStack newitem = read_item(L,-1, getServer(L));
- ItemStack leftover = item.addItem(newitem, getServer(L)->idef());
+ ItemStack newitem = read_item(L, -1, getGameDef(L)->idef());
+ ItemStack leftover = item.addItem(newitem, getGameDef(L)->idef());
create(L, leftover);
return 1;
}
@@ -321,9 +350,9 @@ int LuaItemStack::l_item_fits(lua_State *L)
NO_MAP_LOCK_REQUIRED;
LuaItemStack *o = checkobject(L, 1);
ItemStack &item = o->m_stack;
- ItemStack newitem = read_item(L, 2, getServer(L));
+ ItemStack newitem = read_item(L, 2, getGameDef(L)->idef());
ItemStack restitem;
- bool fits = item.itemFits(newitem, &restitem, getServer(L)->idef());
+ bool fits = item.itemFits(newitem, &restitem, getGameDef(L)->idef());
lua_pushboolean(L, fits); // first return value
create(L, restitem); // second return value
return 2;
@@ -380,7 +409,7 @@ ItemStack& LuaItemStack::getItem()
int LuaItemStack::create_object(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- ItemStack item = read_item(L, 1, getServer(L));
+ ItemStack item = read_item(L, 1, getGameDef(L)->idef());
LuaItemStack *o = new LuaItemStack(item);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
@@ -435,7 +464,7 @@ void LuaItemStack::Register(lua_State *L)
}
const char LuaItemStack::className[] = "ItemStack";
-const luaL_reg LuaItemStack::methods[] = {
+const luaL_Reg LuaItemStack::methods[] = {
luamethod(LuaItemStack, is_empty),
luamethod(LuaItemStack, get_name),
luamethod(LuaItemStack, set_name),
@@ -443,6 +472,7 @@ const luaL_reg LuaItemStack::methods[] = {
luamethod(LuaItemStack, set_count),
luamethod(LuaItemStack, get_wear),
luamethod(LuaItemStack, set_wear),
+ luamethod(LuaItemStack, get_meta),
luamethod(LuaItemStack, get_metadata),
luamethod(LuaItemStack, set_metadata),
luamethod(LuaItemStack, clear),
@@ -496,7 +526,7 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
def.node_placement_prediction = "__default";
// Read the item definition
- def = read_item_definition(L, table, def);
+ read_item_definition(L, table, def, def);
// Default to having client-side placement prediction for nodes
// ("" in item definition sets it off)
@@ -568,7 +598,7 @@ int ModApiItemMod::l_get_content_id(lua_State *L)
NO_MAP_LOCK_REQUIRED;
std::string name = luaL_checkstring(L, 1);
- INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+ INodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
content_t c = ndef->getId(name);
lua_pushinteger(L, c);
@@ -581,7 +611,7 @@ int ModApiItemMod::l_get_name_from_content_id(lua_State *L)
NO_MAP_LOCK_REQUIRED;
content_t c = luaL_checkint(L, 1);
- INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+ INodeDefManager *ndef = getGameDef(L)->getNodeDefManager();
const char *name = ndef->get(c).name.c_str();
lua_pushstring(L, name);
diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h
index be919b701..b4efaefc8 100644
--- a/src/script/lua_api/l_item.h
+++ b/src/script/lua_api/l_item.h
@@ -28,7 +28,7 @@ private:
ItemStack m_stack;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
// Exported functions
@@ -56,9 +56,14 @@ private:
// set_wear(self, number)
static int l_set_wear(lua_State *L);
+ // get_meta(self) -> string
+ static int l_get_meta(lua_State *L);
+
+ // DEPRECATED
// get_metadata(self) -> string
static int l_get_metadata(lua_State *L);
+ // DEPRECATED
// set_metadata(self, string)
static int l_set_metadata(lua_State *L);
diff --git a/src/script/lua_api/l_itemstackmeta.cpp b/src/script/lua_api/l_itemstackmeta.cpp
new file mode 100644
index 000000000..c37a82116
--- /dev/null
+++ b/src/script/lua_api/l_itemstackmeta.cpp
@@ -0,0 +1,120 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "lua_api/l_itemstackmeta.h"
+#include "lua_api/l_internal.h"
+#include "common/c_content.h"
+
+/*
+ NodeMetaRef
+*/
+ItemStackMetaRef* ItemStackMetaRef::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 *(ItemStackMetaRef**)ud; // unbox pointer
+}
+
+Metadata* ItemStackMetaRef::getmeta(bool auto_create)
+{
+ return &istack->metadata;
+}
+
+void ItemStackMetaRef::clearMeta()
+{
+ istack->metadata.clear();
+}
+
+void ItemStackMetaRef::reportMetadataChange()
+{
+ // TODO
+}
+
+// Exported functions
+
+// garbage collector
+int ItemStackMetaRef::gc_object(lua_State *L) {
+ ItemStackMetaRef *o = *(ItemStackMetaRef **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+// Creates an NodeMetaRef and leaves it on top of stack
+// Not callable from Lua; all references are created on the C side.
+void ItemStackMetaRef::create(lua_State *L, ItemStack *istack)
+{
+ ItemStackMetaRef *o = new ItemStackMetaRef(istack);
+ //infostream<<"NodeMetaRef::create: o="<<o<<std::endl;
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+}
+
+void ItemStackMetaRef::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+
+ lua_pushliteral(L, "metadata_class");
+ lua_pushlstring(L, className, strlen(className));
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__eq");
+ lua_pushcfunction(L, l_equals);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+
+ // Cannot be created from Lua
+ //lua_register(L, className, create_object);
+}
+
+const char ItemStackMetaRef::className[] = "ItemStackMetaRef";
+const luaL_Reg ItemStackMetaRef::methods[] = {
+ luamethod(MetaDataRef, get_string),
+ luamethod(MetaDataRef, set_string),
+ luamethod(MetaDataRef, get_int),
+ luamethod(MetaDataRef, set_int),
+ luamethod(MetaDataRef, get_float),
+ luamethod(MetaDataRef, set_float),
+ luamethod(MetaDataRef, to_table),
+ luamethod(MetaDataRef, from_table),
+ luamethod(MetaDataRef, equals),
+ {0,0}
+};
diff --git a/src/script/lua_api/l_itemstackmeta.h b/src/script/lua_api/l_itemstackmeta.h
new file mode 100644
index 000000000..4ef64a91e
--- /dev/null
+++ b/src/script/lua_api/l_itemstackmeta.h
@@ -0,0 +1,59 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef L_ITEMSTACKMETA_H_
+#define L_ITEMSTACKMETA_H_
+
+#include "lua_api/l_base.h"
+#include "lua_api/l_metadata.h"
+#include "irrlichttypes_bloated.h"
+#include "inventory.h"
+
+class ItemStackMetaRef : public MetaDataRef
+{
+private:
+ ItemStack *istack;
+
+ static const char className[];
+ static const luaL_Reg methods[];
+
+ static ItemStackMetaRef *checkobject(lua_State *L, int narg);
+
+ virtual Metadata* getmeta(bool auto_create);
+
+ virtual void clearMeta();
+
+ virtual void reportMetadataChange();
+
+ // Exported functions
+
+ // garbage collector
+ static int gc_object(lua_State *L);
+public:
+ ItemStackMetaRef(ItemStack *istack): istack(istack) {}
+ ~ItemStackMetaRef() {}
+
+ // Creates an ItemStackMetaRef 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, ItemStack *istack);
+
+ static void Register(lua_State *L);
+};
+
+#endif
diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp
new file mode 100644
index 000000000..7ec4eaa62
--- /dev/null
+++ b/src/script/lua_api/l_localplayer.cpp
@@ -0,0 +1,358 @@
+/*
+Minetest
+Copyright (C) 2017 Dumbeldor, Vincent Glize <vincent.glize@live.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "l_localplayer.h"
+#include "l_internal.h"
+#include "script/common/c_converter.h"
+
+LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m)
+{
+ m_localplayer = m;
+}
+
+void LuaLocalPlayer::create(lua_State *L, LocalPlayer *m)
+{
+ LuaLocalPlayer *o = new LuaLocalPlayer(m);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+
+ // Keep localplayer object stack id
+ int localplayer_object = lua_gettop(L);
+
+ lua_getglobal(L, "core");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int coretable = lua_gettop(L);
+
+ lua_pushvalue(L, localplayer_object);
+ lua_setfield(L, coretable, "localplayer");
+}
+
+int LuaLocalPlayer::l_get_velocity(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ push_v3f(L, player->getSpeed() / BS);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_hp(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushinteger(L, player->hp);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_name(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushstring(L, player->getName());
+ return 1;
+}
+
+int LuaLocalPlayer::l_is_attached(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushboolean(L, player->isAttached);
+ return 1;
+}
+
+int LuaLocalPlayer::l_is_touching_ground(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushboolean(L, player->touching_ground);
+ return 1;
+}
+
+int LuaLocalPlayer::l_is_in_liquid(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushboolean(L, player->in_liquid);
+ return 1;
+}
+
+int LuaLocalPlayer::l_is_in_liquid_stable(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushboolean(L, player->in_liquid_stable);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_liquid_viscosity(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushinteger(L, player->liquid_viscosity);
+ return 1;
+}
+
+int LuaLocalPlayer::l_is_climbing(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushboolean(L, player->is_climbing);
+ return 1;
+}
+
+int LuaLocalPlayer::l_swimming_vertical(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushboolean(L, player->swimming_vertical);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_physics_override(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_newtable(L);
+ lua_pushnumber(L, player->physics_override_speed);
+ lua_setfield(L, -2, "speed");
+
+ lua_pushnumber(L, player->physics_override_jump);
+ lua_setfield(L, -2, "jump");
+
+ lua_pushnumber(L, player->physics_override_gravity);
+ lua_setfield(L, -2, "gravity");
+
+ lua_pushboolean(L, player->physics_override_sneak);
+ lua_setfield(L, -2, "sneak");
+
+ 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);
+
+ push_v3f(L, player->overridePosition);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_last_pos(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ push_v3f(L, player->last_position / BS);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_last_velocity(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ push_v3f(L, player->last_speed);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_last_look_vertical(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushnumber(L, -1.0 * player->last_pitch * core::DEGTORAD);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_last_look_horizontal(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushnumber(L, (player->last_yaw + 90.) * core::DEGTORAD);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_key_pressed(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushinteger(L, player->last_keyPressed);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_breath(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_pushinteger(L, player->getBreath());
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_pos(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ push_v3f(L, player->getPosition() / BS);
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_newtable(L);
+ lua_pushnumber(L, player->movement_acceleration_default);
+ lua_setfield(L, -2, "default");
+
+ lua_pushnumber(L, player->movement_acceleration_air);
+ lua_setfield(L, -2, "air");
+
+ lua_pushnumber(L, player->movement_acceleration_fast);
+ lua_setfield(L, -2, "fast");
+
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_movement_speed(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_newtable(L);
+ lua_pushnumber(L, player->movement_speed_walk);
+ lua_setfield(L, -2, "walk");
+
+ lua_pushnumber(L, player->movement_speed_crouch);
+ lua_setfield(L, -2, "crouch");
+
+ lua_pushnumber(L, player->movement_speed_fast);
+ lua_setfield(L, -2, "fast");
+
+ lua_pushnumber(L, player->movement_speed_climb);
+ lua_setfield(L, -2, "climb");
+
+ lua_pushnumber(L, player->movement_speed_jump);
+ lua_setfield(L, -2, "jump");
+
+ return 1;
+}
+
+int LuaLocalPlayer::l_get_movement(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ lua_newtable(L);
+
+ lua_pushnumber(L, player->movement_liquid_fluidity);
+ lua_setfield(L, -2, "liquid_fluidity");
+
+ lua_pushnumber(L, player->movement_liquid_fluidity_smooth);
+ lua_setfield(L, -2, "liquid_fluidity_smooth");
+
+ lua_pushnumber(L, player->movement_liquid_sink);
+ lua_setfield(L, -2, "liquid_sink");
+
+ lua_pushnumber(L, player->movement_gravity);
+ lua_setfield(L, -2, "gravity");
+
+ return 1;
+}
+
+LuaLocalPlayer *LuaLocalPlayer::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 *(LuaLocalPlayer **)ud;
+}
+
+LocalPlayer *LuaLocalPlayer::getobject(LuaLocalPlayer *ref)
+{
+ return ref->m_localplayer;
+}
+
+LocalPlayer *LuaLocalPlayer::getobject(lua_State *L, int narg)
+{
+ LuaLocalPlayer *ref = checkobject(L, narg);
+ assert(ref);
+ LocalPlayer *player = getobject(ref);
+ assert(player);
+ return player;
+}
+
+int LuaLocalPlayer::gc_object(lua_State *L)
+{
+ LuaLocalPlayer *o = *(LuaLocalPlayer **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+void LuaLocalPlayer::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from lua getmetatable()
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // Drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // Drop methodtable
+}
+
+const char LuaLocalPlayer::className[] = "LocalPlayer";
+const luaL_Reg LuaLocalPlayer::methods[] = {
+ luamethod(LuaLocalPlayer, get_velocity),
+ luamethod(LuaLocalPlayer, get_hp),
+ luamethod(LuaLocalPlayer, get_name),
+ luamethod(LuaLocalPlayer, is_attached),
+ luamethod(LuaLocalPlayer, is_touching_ground),
+ luamethod(LuaLocalPlayer, is_in_liquid),
+ luamethod(LuaLocalPlayer, is_in_liquid_stable),
+ luamethod(LuaLocalPlayer, get_liquid_viscosity),
+ luamethod(LuaLocalPlayer, is_climbing),
+ luamethod(LuaLocalPlayer, swimming_vertical),
+ luamethod(LuaLocalPlayer, get_physics_override),
+ luamethod(LuaLocalPlayer, get_override_pos),
+ 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_breath),
+ luamethod(LuaLocalPlayer, get_pos),
+ luamethod(LuaLocalPlayer, get_movement_acceleration),
+ luamethod(LuaLocalPlayer, get_movement_speed),
+ luamethod(LuaLocalPlayer, get_movement),
+
+ {0, 0}
+};
diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h
new file mode 100644
index 000000000..e56ec808f
--- /dev/null
+++ b/src/script/lua_api/l_localplayer.h
@@ -0,0 +1,85 @@
+/*
+Minetest
+Copyright (C) 2017 Dumbeldor, Vincent Glize <vincent.glize@live.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef MINETEST_L_LOCALPLAYER_H
+#define MINETEST_L_LOCALPLAYER_H
+
+#include "l_base.h"
+
+class LocalPlayer;
+
+class LuaLocalPlayer : public ModApiBase
+{
+private:
+ static const char className[];
+ static const luaL_Reg methods[];
+
+ // garbage collector
+ static int gc_object(lua_State *L);
+
+ static int l_get_velocity(lua_State *L);
+
+ static int l_get_hp(lua_State *L);
+
+ static int l_get_name(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);
+ static int l_is_in_liquid_stable(lua_State *L);
+ static int l_get_liquid_viscosity(lua_State *L);
+ static int l_is_climbing(lua_State *L);
+ static int l_swimming_vertical(lua_State *L);
+
+ static int l_get_physics_override(lua_State *L);
+
+ static int l_get_override_pos(lua_State *L);
+
+ static int l_get_last_pos(lua_State *L);
+ 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);
+
+ static int l_get_breath(lua_State *L);
+
+ static int l_get_pos(lua_State *L);
+
+ static int l_get_movement_acceleration(lua_State *L);
+
+ static int l_get_movement_speed(lua_State *L);
+
+ static int l_get_movement(lua_State *L);
+
+ LocalPlayer *m_localplayer;
+
+public:
+ LuaLocalPlayer(LocalPlayer *m);
+ ~LuaLocalPlayer() {}
+
+ static void create(lua_State *L, LocalPlayer *m);
+
+ static LuaLocalPlayer *checkobject(lua_State *L, int narg);
+ static LocalPlayer *getobject(LuaLocalPlayer *ref);
+ static LocalPlayer *getobject(lua_State *L, int narg);
+
+ static void Register(lua_State *L);
+};
+
+#endif // MINETEST_L_LOCALPLAYER_H
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index 4a2484613..dc8654960 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -32,14 +32,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "convert_json.h"
#include "serverlist.h"
#include "mapgen.h"
-#include "sound.h"
#include "settings.h"
-#include "log.h"
#include "EDriverTypes.h"
#include <IFileArchive.h>
#include <IFileSystem.h>
+
/******************************************************************************/
std::string ModApiMainMenu::getTextData(lua_State *L, std::string name)
{
@@ -299,7 +298,7 @@ int ModApiMainMenu::l_get_games(lua_State *L)
int table2 = lua_gettop(L);
int internal_index=1;
for (std::set<std::string>::iterator iter = games[i].addon_mods_paths.begin();
- iter != games[i].addon_mods_paths.end(); iter++) {
+ iter != games[i].addon_mods_paths.end(); ++iter) {
lua_pushnumber(L,internal_index);
lua_pushstring(L,(*iter).c_str());
lua_settable(L, table2);
@@ -577,6 +576,13 @@ int ModApiMainMenu::l_get_favorites(lua_State *L)
lua_settable(L, top_lvl2);
}
+ if (servers[i].isMember("ping")) {
+ float ping = servers[i]["ping"].asFloat();
+ lua_pushstring(L, "ping");
+ lua_pushnumber(L, ping);
+ lua_settable(L, top_lvl2);
+ }
+
lua_settable(L, top);
index++;
}
@@ -956,33 +962,6 @@ int ModApiMainMenu::l_show_file_open_dialog(lua_State *L)
}
/******************************************************************************/
-int ModApiMainMenu::l_sound_play(lua_State *L)
-{
- GUIEngine* engine = getGuiEngine(L);
-
- SimpleSoundSpec spec;
- read_soundspec(L, 1, spec);
- bool looped = lua_toboolean(L, 2);
-
- u32 handle = engine->playSound(spec, looped);
-
- lua_pushinteger(L, handle);
-
- return 1;
-}
-
-/******************************************************************************/
-int ModApiMainMenu::l_sound_stop(lua_State *L)
-{
- GUIEngine* engine = getGuiEngine(L);
-
- u32 handle = luaL_checkinteger(L, 1);
- engine->stopSound(handle);
-
- return 1;
-}
-
-/******************************************************************************/
int ModApiMainMenu::l_download_file(lua_State *L)
{
const char *url = luaL_checkstring(L, 1);
@@ -1153,8 +1132,6 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
API_FCT(download_file);
API_FCT(get_modstore_details);
API_FCT(get_modstore_list);
- API_FCT(sound_play);
- API_FCT(sound_stop);
API_FCT(gettext);
API_FCT(get_video_drivers);
API_FCT(get_video_modes);
@@ -1165,23 +1142,24 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
}
/******************************************************************************/
-void ModApiMainMenu::InitializeAsync(AsyncEngine& engine)
+void ModApiMainMenu::InitializeAsync(lua_State *L, int top)
{
- ASYNC_API_FCT(get_worlds);
- ASYNC_API_FCT(get_games);
- ASYNC_API_FCT(get_favorites);
- ASYNC_API_FCT(get_mapgen_names);
- ASYNC_API_FCT(get_modpath);
- ASYNC_API_FCT(get_gamepath);
- ASYNC_API_FCT(get_texturepath);
- ASYNC_API_FCT(get_texturepath_share);
- ASYNC_API_FCT(create_dir);
- ASYNC_API_FCT(delete_dir);
- ASYNC_API_FCT(copy_dir);
- //ASYNC_API_FCT(extract_zip); //TODO remove dependency to GuiEngine
- ASYNC_API_FCT(download_file);
- ASYNC_API_FCT(get_modstore_details);
- ASYNC_API_FCT(get_modstore_list);
- //ASYNC_API_FCT(gettext); (gettext lib isn't threadsafe)
+ API_FCT(get_worlds);
+ API_FCT(get_games);
+ API_FCT(get_favorites);
+ API_FCT(get_mapgen_names);
+ API_FCT(get_modpath);
+ API_FCT(get_gamepath);
+ API_FCT(get_texturepath);
+ API_FCT(get_texturepath_share);
+ API_FCT(create_dir);
+ API_FCT(delete_dir);
+ API_FCT(copy_dir);
+ //API_FCT(extract_zip); //TODO remove dependency to GuiEngine
+ API_FCT(download_file);
+ API_FCT(get_modstore_details);
+ API_FCT(get_modstore_list);
+ //API_FCT(gettext); (gettext lib isn't threadsafe)
}
+
diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h
index ad5155ac6..d4946bab1 100644
--- a/src/script/lua_api/l_mainmenu.h
+++ b/src/script/lua_api/l_mainmenu.h
@@ -25,7 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class AsyncEngine;
/** Implementation of lua api support for mainmenu */
-class ModApiMainMenu : public ModApiBase {
+class ModApiMainMenu: public ModApiBase
+{
private:
/**
@@ -79,10 +80,6 @@ private:
static int l_delete_favorite(lua_State *L);
- static int l_sound_play(lua_State *L);
-
- static int l_sound_stop(lua_State *L);
-
static int l_gettext(lua_State *L);
//gui
@@ -145,6 +142,7 @@ private:
static int l_do_async_callback(lua_State *L);
public:
+
/**
* initialize this API module
* @param L lua stack to initialize
@@ -152,7 +150,7 @@ public:
*/
static void Initialize(lua_State *L, int top);
- static void InitializeAsync(AsyncEngine& engine);
+ static void InitializeAsync(lua_State *L, int top);
};
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp
index bc1c32f03..32eb7af84 100644
--- a/src/script/lua_api/l_mapgen.cpp
+++ b/src/script/lua_api/l_mapgen.cpp
@@ -325,14 +325,22 @@ void read_schematic_replacements(lua_State *L, int index, StringMap *replace_nam
if (lua_istable(L, -1)) { // Old {{"x", "y"}, ...} format
lua_rawgeti(L, -1, 1);
+ if (!lua_isstring(L, -1))
+ throw LuaError("schematics: replace_from field is not a string");
replace_from = lua_tostring(L, -1);
lua_pop(L, 1);
lua_rawgeti(L, -1, 2);
+ if (!lua_isstring(L, -1))
+ throw LuaError("schematics: replace_to field is not a string");
replace_to = lua_tostring(L, -1);
lua_pop(L, 1);
} else { // New {x = "y", ...} format
+ if (!lua_isstring(L, -2))
+ throw LuaError("schematics: replace_from field is not a string");
replace_from = lua_tostring(L, -2);
+ if (!lua_isstring(L, -1))
+ throw LuaError("schematics: replace_to field is not a string");
replace_to = lua_tostring(L, -1);
}
@@ -419,7 +427,7 @@ size_t get_biome_list(lua_State *L, int index,
if (is_single) {
Biome *biome = get_or_load_biome(L, index, biomemgr);
if (!biome) {
- errorstream << "get_biome_list: failed to get biome '"
+ infostream << "get_biome_list: failed to get biome '"
<< (lua_isstring(L, index) ? lua_tostring(L, index) : "")
<< "'." << std::endl;
return 1;
@@ -438,7 +446,7 @@ size_t get_biome_list(lua_State *L, int index,
Biome *biome = get_or_load_biome(L, -1, biomemgr);
if (!biome) {
fail_count++;
- errorstream << "get_biome_list: failed to get biome '"
+ infostream << "get_biome_list: failed to get biome '"
<< (lua_isstring(L, -1) ? lua_tostring(L, -1) : "")
<< "'" << std::endl;
continue;
@@ -927,7 +935,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
//// Get biomes associated with this decoration (if any)
lua_getfield(L, index, "biomes");
if (get_biome_list(L, -1, biomemgr, &deco->biomes))
- errorstream << "register_decoration: couldn't get all biomes " << std::endl;
+ infostream << "register_decoration: couldn't get all biomes " << std::endl;
lua_pop(L, 1);
//// Get node name(s) to 'spawn by'
@@ -1092,7 +1100,7 @@ int ModApiMapgen::l_register_ore(lua_State *L)
//// Get biomes associated with this decoration (if any)
lua_getfield(L, index, "biomes");
if (get_biome_list(L, -1, bmgr, &ore->biomes))
- errorstream << "register_ore: couldn't get all biomes " << std::endl;
+ infostream << "register_ore: couldn't get all biomes " << std::endl;
lua_pop(L, 1);
//// Get noise parameters if needed
@@ -1357,7 +1365,9 @@ int ModApiMapgen::l_place_schematic(lua_State *L)
{
MAP_LOCK_REQUIRED;
- Map *map = &(getEnv(L)->getMap());
+ GET_ENV_PTR;
+
+ ServerMap *map = &(env->getServerMap());
SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
//// Read position
diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h
index bb94575c7..a26c8b950 100644
--- a/src/script/lua_api/l_mapgen.h
+++ b/src/script/lua_api/l_mapgen.h
@@ -22,7 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_base.h"
-class ModApiMapgen : public ModApiBase {
+class ModApiMapgen : public ModApiBase
+{
private:
// get_biome_id(biomename)
// returns the biome id used in biomemap
diff --git a/src/script/lua_api/l_metadata.cpp b/src/script/lua_api/l_metadata.cpp
new file mode 100644
index 000000000..5f4e984cb
--- /dev/null
+++ b/src/script/lua_api/l_metadata.cpp
@@ -0,0 +1,266 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "lua_api/l_metadata.h"
+#include "lua_api/l_internal.h"
+#include "common/c_content.h"
+#include "serverenvironment.h"
+#include "map.h"
+#include "server.h"
+
+// LUALIB_API
+void *luaL_checkudata_is_metadataref(lua_State *L, int ud) {
+ void *p = lua_touserdata(L, ud);
+ if (p != NULL && // value is a userdata?
+ lua_getmetatable(L, ud)) { // does it have a metatable?
+ lua_getfield(L, -1, "metadata_class");
+ if (lua_type(L, -1) == LUA_TSTRING) { // does it have a metadata_class field?
+ return p;
+ }
+ }
+ luaL_typerror(L, ud, "MetaDataRef");
+ return NULL;
+}
+
+MetaDataRef* MetaDataRef::checkobject(lua_State *L, int narg)
+{
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+ void *ud = luaL_checkudata_is_metadataref(L, narg);
+ if (!ud)
+ luaL_typerror(L, narg, "MetaDataRef");
+
+ return *(MetaDataRef**)ud; // unbox pointer
+}
+
+// Exported functions
+
+// get_string(self, name)
+int MetaDataRef::l_get_string(lua_State *L)
+{
+ MAP_LOCK_REQUIRED;
+
+ MetaDataRef *ref = checkobject(L, 1);
+ std::string name = luaL_checkstring(L, 2);
+
+ Metadata *meta = ref->getmeta(false);
+ if (meta == NULL) {
+ lua_pushlstring(L, "", 0);
+ return 1;
+ }
+
+ const std::string &str = meta->getString(name);
+ lua_pushlstring(L, str.c_str(), str.size());
+ return 1;
+}
+
+// set_string(self, name, var)
+int MetaDataRef::l_set_string(lua_State *L)
+{
+ MAP_LOCK_REQUIRED;
+
+ MetaDataRef *ref = checkobject(L, 1);
+ std::string name = luaL_checkstring(L, 2);
+ size_t len = 0;
+ const char *s = lua_tolstring(L, 3, &len);
+ std::string str(s, len);
+
+ Metadata *meta = ref->getmeta(!str.empty());
+ if (meta == NULL || str == meta->getString(name))
+ return 0;
+
+ meta->setString(name, str);
+ ref->reportMetadataChange();
+ return 0;
+}
+
+// get_int(self, name)
+int MetaDataRef::l_get_int(lua_State *L)
+{
+ MAP_LOCK_REQUIRED;
+
+ MetaDataRef *ref = checkobject(L, 1);
+ std::string name = lua_tostring(L, 2);
+
+ Metadata *meta = ref->getmeta(false);
+ if (meta == NULL) {
+ lua_pushnumber(L, 0);
+ return 1;
+ }
+
+ const std::string &str = meta->getString(name);
+ lua_pushnumber(L, stoi(str));
+ return 1;
+}
+
+// set_int(self, name, var)
+int MetaDataRef::l_set_int(lua_State *L)
+{
+ MAP_LOCK_REQUIRED;
+
+ MetaDataRef *ref = checkobject(L, 1);
+ std::string name = lua_tostring(L, 2);
+ int a = lua_tointeger(L, 3);
+ std::string str = itos(a);
+
+ Metadata *meta = ref->getmeta(true);
+ if (meta == NULL || str == meta->getString(name))
+ return 0;
+
+ meta->setString(name, str);
+ ref->reportMetadataChange();
+ return 0;
+}
+
+// get_float(self, name)
+int MetaDataRef::l_get_float(lua_State *L)
+{
+ MAP_LOCK_REQUIRED;
+
+ MetaDataRef *ref = checkobject(L, 1);
+ std::string name = lua_tostring(L, 2);
+
+ Metadata *meta = ref->getmeta(false);
+ if (meta == NULL) {
+ lua_pushnumber(L, 0);
+ return 1;
+ }
+
+ const std::string &str = meta->getString(name);
+ lua_pushnumber(L, stof(str));
+ return 1;
+}
+
+// set_float(self, name, var)
+int MetaDataRef::l_set_float(lua_State *L)
+{
+ MAP_LOCK_REQUIRED;
+
+ MetaDataRef *ref = checkobject(L, 1);
+ std::string name = lua_tostring(L, 2);
+ float a = lua_tonumber(L, 3);
+ std::string str = ftos(a);
+
+ Metadata *meta = ref->getmeta(true);
+ if (meta == NULL || str == meta->getString(name))
+ return 0;
+
+ meta->setString(name, str);
+ ref->reportMetadataChange();
+ return 0;
+}
+
+// to_table(self)
+int MetaDataRef::l_to_table(lua_State *L)
+{
+ MAP_LOCK_REQUIRED;
+
+ MetaDataRef *ref = checkobject(L, 1);
+
+ Metadata *meta = ref->getmeta(true);
+ if (meta == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ lua_newtable(L);
+
+ ref->handleToTable(L, meta);
+
+ return 1;
+}
+
+// from_table(self, table)
+int MetaDataRef::l_from_table(lua_State *L)
+{
+ MAP_LOCK_REQUIRED;
+
+ MetaDataRef *ref = checkobject(L, 1);
+ int base = 2;
+
+ ref->clearMeta();
+
+ if (!lua_istable(L, base)) {
+ // No metadata
+ lua_pushboolean(L, true);
+ return 1;
+ }
+
+ // Create new metadata
+ Metadata *meta = ref->getmeta(true);
+ if (meta == NULL) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
+
+ bool was_successful = ref->handleFromTable(L, base, meta);
+ ref->reportMetadataChange();
+ lua_pushboolean(L, was_successful);
+ return 1;
+}
+
+void MetaDataRef::handleToTable(lua_State *L, Metadata *meta)
+{
+ lua_newtable(L);
+ {
+ const StringMap &fields = meta->getStrings();
+ for (StringMap::const_iterator
+ it = fields.begin(); it != fields.end(); ++it) {
+ const std::string &name = it->first;
+ const std::string &value = it->second;
+ lua_pushlstring(L, name.c_str(), name.size());
+ lua_pushlstring(L, value.c_str(), value.size());
+ lua_settable(L, -3);
+ }
+ }
+ lua_setfield(L, -2, "fields");
+}
+
+bool MetaDataRef::handleFromTable(lua_State *L, int table, Metadata *meta)
+{
+ // Set fields
+ lua_getfield(L, table, "fields");
+ if (lua_istable(L, -1)) {
+ int fieldstable = lua_gettop(L);
+ lua_pushnil(L);
+ while (lua_next(L, fieldstable) != 0) {
+ // key at index -2 and value at index -1
+ std::string name = lua_tostring(L, -2);
+ size_t cl;
+ const char *cs = lua_tolstring(L, -1, &cl);
+ meta->setString(name, std::string(cs, cl));
+ lua_pop(L, 1); // Remove value, keep key for next iteration
+ }
+ lua_pop(L, 1);
+ }
+
+ return true;
+}
+
+// equals(self, other)
+int MetaDataRef::l_equals(lua_State *L)
+{
+ MetaDataRef *ref1 = checkobject(L, 1);
+ Metadata *data1 = ref1->getmeta(false);
+ MetaDataRef *ref2 = checkobject(L, 2);
+ Metadata *data2 = ref2->getmeta(false);
+ if (data1 == NULL || data2 == NULL)
+ lua_pushboolean(L, data1 == data2);
+ else
+ lua_pushboolean(L, *data1 == *data2);
+ return 1;
+}
diff --git a/src/script/lua_api/l_metadata.h b/src/script/lua_api/l_metadata.h
new file mode 100644
index 000000000..a4d8214d3
--- /dev/null
+++ b/src/script/lua_api/l_metadata.h
@@ -0,0 +1,75 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef L_METADATA_H_
+#define L_METADATA_H_
+
+#include "irrlichttypes_bloated.h"
+#include "lua_api/l_base.h"
+
+class Metadata;
+
+/*
+ NodeMetaRef
+*/
+
+class MetaDataRef : public ModApiBase
+{
+public:
+ virtual ~MetaDataRef() {}
+protected:
+ static MetaDataRef *checkobject(lua_State *L, int narg);
+
+ virtual void reportMetadataChange() {}
+ virtual Metadata *getmeta(bool auto_create) = 0;
+ virtual void clearMeta() = 0;
+
+ virtual void handleToTable(lua_State *L, Metadata *meta);
+ virtual bool handleFromTable(lua_State *L, int table, Metadata *meta);
+
+ // Exported functions
+
+ // get_string(self, name)
+ static int l_get_string(lua_State *L);
+
+ // set_string(self, name, var)
+ static int l_set_string(lua_State *L);
+
+ // get_int(self, name)
+ static int l_get_int(lua_State *L);
+
+ // set_int(self, name, var)
+ static int l_set_int(lua_State *L);
+
+ // get_float(self, name)
+ static int l_get_float(lua_State *L);
+
+ // set_float(self, name, var)
+ static int l_set_float(lua_State *L);
+
+ // to_table(self)
+ static int l_to_table(lua_State *L);
+
+ // from_table(self, table)
+ static int l_from_table(lua_State *L);
+
+ // equals(self, other)
+ static int l_equals(lua_State *L);
+};
+
+#endif /* L_NODEMETA_H_ */
diff --git a/src/script/lua_api/l_minimap.cpp b/src/script/lua_api/l_minimap.cpp
new file mode 100644
index 000000000..afb3766fb
--- /dev/null
+++ b/src/script/lua_api/l_minimap.cpp
@@ -0,0 +1,227 @@
+/*
+Minetest
+Copyright (C) 2017 Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+
+#include "lua_api/l_minimap.h"
+#include "lua_api/l_internal.h"
+#include "common/c_converter.h"
+#include "minimap.h"
+#include "settings.h"
+
+LuaMinimap::LuaMinimap(Minimap *m)
+{
+ m_minimap = m;
+}
+
+void LuaMinimap::create(lua_State *L, Minimap *m)
+{
+ LuaMinimap *o = new LuaMinimap(m);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+
+ // Keep minimap object stack id
+ int minimap_object = lua_gettop(L);
+
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "ui");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int uitable = lua_gettop(L);
+
+ lua_pushvalue(L, minimap_object); // Copy object to top of stack
+ lua_setfield(L, uitable, "minimap");
+}
+
+int LuaMinimap::l_get_pos(lua_State *L)
+{
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+
+ push_v3s16(L, m->getPos());
+ return 1;
+}
+
+int LuaMinimap::l_set_pos(lua_State *L)
+{
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+
+ m->setPos(read_v3s16(L, 2));
+ return 1;
+}
+
+int LuaMinimap::l_get_angle(lua_State *L)
+{
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+
+ lua_pushinteger(L, m->getAngle());
+ return 1;
+}
+
+int LuaMinimap::l_set_angle(lua_State *L)
+{
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+
+ m->setAngle(lua_tointeger(L, 2));
+ return 1;
+}
+
+int LuaMinimap::l_get_mode(lua_State *L)
+{
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+
+ lua_pushinteger(L, m->getMinimapMode());
+ return 1;
+}
+
+int LuaMinimap::l_set_mode(lua_State *L)
+{
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+
+ s32 mode = lua_tointeger(L, 2);
+ if (mode < MINIMAP_MODE_OFF ||
+ mode >= MINIMAP_MODE_COUNT) {
+ return 0;
+ }
+
+ m->setMinimapMode((MinimapMode) mode);
+ return 1;
+}
+
+int LuaMinimap::l_set_shape(lua_State *L)
+{
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+ if (!lua_isnumber(L, 2))
+ return 0;
+
+ m->setMinimapShape((MinimapShape)((int)lua_tonumber(L, 2)));
+ return 0;
+}
+
+int LuaMinimap::l_get_shape(lua_State *L)
+{
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+
+ lua_pushnumber(L, (int)m->getMinimapShape());
+ return 1;
+}
+
+int LuaMinimap::l_show(lua_State *L)
+{
+ // If minimap is disabled by config, don't show it.
+ if (!g_settings->getBool("enable_minimap"))
+ return 1;
+
+ Client *client = getClient(L);
+ assert(client);
+
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+
+ if (m->getMinimapMode() == MINIMAP_MODE_OFF)
+ m->setMinimapMode(MINIMAP_MODE_SURFACEx1);
+
+ client->showMinimap(true);
+ return 1;
+}
+
+int LuaMinimap::l_hide(lua_State *L)
+{
+ Client *client = getClient(L);
+ assert(client);
+
+ LuaMinimap *ref = checkobject(L, 1);
+ Minimap *m = getobject(ref);
+
+ if (m->getMinimapMode() != MINIMAP_MODE_OFF)
+ m->setMinimapMode(MINIMAP_MODE_OFF);
+
+ client->showMinimap(false);
+ return 1;
+}
+
+LuaMinimap *LuaMinimap::checkobject(lua_State *L, int narg)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+
+ void *ud = luaL_checkudata(L, narg, className);
+ if (!ud)
+ luaL_typerror(L, narg, className);
+
+ return *(LuaMinimap **)ud; // unbox pointer
+}
+
+Minimap* LuaMinimap::getobject(LuaMinimap *ref)
+{
+ return ref->m_minimap;
+}
+
+int LuaMinimap::gc_object(lua_State *L) {
+ LuaMinimap *o = *(LuaMinimap **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+void LuaMinimap::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+}
+
+const char LuaMinimap::className[] = "Minimap";
+const luaL_Reg LuaMinimap::methods[] = {
+ luamethod(LuaMinimap, show),
+ luamethod(LuaMinimap, hide),
+ luamethod(LuaMinimap, get_pos),
+ luamethod(LuaMinimap, set_pos),
+ luamethod(LuaMinimap, get_angle),
+ luamethod(LuaMinimap, set_angle),
+ luamethod(LuaMinimap, get_mode),
+ luamethod(LuaMinimap, set_mode),
+ luamethod(LuaMinimap, set_shape),
+ luamethod(LuaMinimap, get_shape),
+ {0,0}
+};
diff --git a/src/script/lua_api/l_minimap.h b/src/script/lua_api/l_minimap.h
new file mode 100644
index 000000000..ba702b0b1
--- /dev/null
+++ b/src/script/lua_api/l_minimap.h
@@ -0,0 +1,65 @@
+/*
+Minetest
+Copyright (C) 2017 Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef L_MINIMAP_H_
+#define L_MINIMAP_H_
+
+#include "l_base.h"
+
+class Minimap;
+
+class LuaMinimap : public ModApiBase
+{
+private:
+ static const char className[];
+ static const luaL_Reg methods[];
+
+ // garbage collector
+ static int gc_object(lua_State *L);
+
+ static int l_get_pos(lua_State *L);
+ static int l_set_pos(lua_State *L);
+
+ static int l_get_angle(lua_State *L);
+ static int l_set_angle(lua_State *L);
+
+ static int l_get_mode(lua_State *L);
+ static int l_set_mode(lua_State *L);
+
+ static int l_show(lua_State *L);
+ static int l_hide(lua_State *L);
+
+ static int l_set_shape(lua_State *L);
+ static int l_get_shape(lua_State *L);
+
+ Minimap *m_minimap;
+
+public:
+ LuaMinimap(Minimap *m);
+ ~LuaMinimap() {}
+
+ static void create(lua_State *L, Minimap *object);
+
+ static LuaMinimap *checkobject(lua_State *L, int narg);
+ static Minimap *getobject(LuaMinimap *ref);
+
+ static void Register(lua_State *L);
+};
+
+#endif // L_MINIMAP_H_
diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp
index c8bc7d558..5dfa6d52e 100644
--- a/src/script/lua_api/l_nodemeta.cpp
+++ b/src/script/lua_api/l_nodemeta.cpp
@@ -20,14 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_nodemeta.h"
#include "lua_api/l_internal.h"
#include "lua_api/l_inventory.h"
-#include "common/c_converter.h"
#include "common/c_content.h"
-#include "environment.h"
+#include "serverenvironment.h"
#include "map.h"
-#include "gamedef.h"
-#include "nodemetadata.h"
-
-
+#include "server.h"
/*
NodeMetaRef
@@ -40,12 +36,15 @@ NodeMetaRef* NodeMetaRef::checkobject(lua_State *L, int narg)
return *(NodeMetaRef**)ud; // unbox pointer
}
-NodeMetadata* NodeMetaRef::getmeta(NodeMetaRef *ref, bool auto_create)
+Metadata* NodeMetaRef::getmeta(bool auto_create)
{
- NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
- if(meta == NULL && auto_create) {
- meta = new NodeMetadata(ref->m_env->getGameDef()->idef());
- if(!ref->m_env->getMap().setNodeMetadata(ref->m_p, meta)) {
+ if (m_is_local)
+ return m_meta;
+
+ NodeMetadata *meta = m_env->getMap().getNodeMetadata(m_p);
+ if (meta == NULL && auto_create) {
+ meta = new NodeMetadata(m_env->getGameDef()->idef());
+ if (!m_env->getMap().setNodeMetadata(m_p, meta)) {
delete meta;
return NULL;
}
@@ -53,17 +52,22 @@ NodeMetadata* NodeMetaRef::getmeta(NodeMetaRef *ref, bool auto_create)
return meta;
}
-void NodeMetaRef::reportMetadataChange(NodeMetaRef *ref)
+void NodeMetaRef::clearMeta()
+{
+ m_env->getMap().removeNodeMetadata(m_p);
+}
+
+void NodeMetaRef::reportMetadataChange()
{
// NOTE: This same code is in rollback_interface.cpp
// Inform other things that the metadata has changed
- v3s16 blockpos = getNodeBlockPos(ref->m_p);
+ v3s16 blockpos = getNodeBlockPos(m_p);
MapEditEvent event;
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
event.p = blockpos;
- ref->m_env->getMap().dispatchEvent(&event);
+ m_env->getMap().dispatchEvent(&event);
// Set the block to be saved
- MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
+ MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
if (block) {
block->raiseModified(MOD_STATE_WRITE_NEEDED,
MOD_REASON_REPORT_META_CHANGE);
@@ -79,154 +83,49 @@ int NodeMetaRef::gc_object(lua_State *L) {
return 0;
}
-// get_string(self, name)
-int NodeMetaRef::l_get_string(lua_State *L)
-{
- MAP_LOCK_REQUIRED;
-
- NodeMetaRef *ref = checkobject(L, 1);
- std::string name = luaL_checkstring(L, 2);
-
- NodeMetadata *meta = getmeta(ref, false);
- if(meta == NULL){
- lua_pushlstring(L, "", 0);
- return 1;
- }
- std::string str = meta->getString(name);
- lua_pushlstring(L, str.c_str(), str.size());
- return 1;
-}
-
-// set_string(self, name, var)
-int NodeMetaRef::l_set_string(lua_State *L)
-{
- MAP_LOCK_REQUIRED;
-
- NodeMetaRef *ref = checkobject(L, 1);
- std::string name = luaL_checkstring(L, 2);
- size_t len = 0;
- const char *s = lua_tolstring(L, 3, &len);
- std::string str(s, len);
-
- NodeMetadata *meta = getmeta(ref, !str.empty());
- if(meta == NULL || str == meta->getString(name))
- return 0;
- meta->setString(name, str);
- reportMetadataChange(ref);
- return 0;
-}
-
-// get_int(self, name)
-int NodeMetaRef::l_get_int(lua_State *L)
-{
- MAP_LOCK_REQUIRED;
-
- NodeMetaRef *ref = checkobject(L, 1);
- std::string name = lua_tostring(L, 2);
-
- NodeMetadata *meta = getmeta(ref, false);
- if(meta == NULL){
- lua_pushnumber(L, 0);
- return 1;
- }
- std::string str = meta->getString(name);
- lua_pushnumber(L, stoi(str));
- return 1;
-}
-
-// set_int(self, name, var)
-int NodeMetaRef::l_set_int(lua_State *L)
-{
- MAP_LOCK_REQUIRED;
-
- NodeMetaRef *ref = checkobject(L, 1);
- std::string name = lua_tostring(L, 2);
- int a = lua_tointeger(L, 3);
- std::string str = itos(a);
-
- NodeMetadata *meta = getmeta(ref, true);
- if(meta == NULL || str == meta->getString(name))
- return 0;
- meta->setString(name, str);
- reportMetadataChange(ref);
- return 0;
-}
-
-// get_float(self, name)
-int NodeMetaRef::l_get_float(lua_State *L)
-{
- MAP_LOCK_REQUIRED;
-
- NodeMetaRef *ref = checkobject(L, 1);
- std::string name = lua_tostring(L, 2);
-
- NodeMetadata *meta = getmeta(ref, false);
- if(meta == NULL){
- lua_pushnumber(L, 0);
- return 1;
- }
- std::string str = meta->getString(name);
- lua_pushnumber(L, stof(str));
- return 1;
-}
-
-// set_float(self, name, var)
-int NodeMetaRef::l_set_float(lua_State *L)
-{
- MAP_LOCK_REQUIRED;
-
- NodeMetaRef *ref = checkobject(L, 1);
- std::string name = lua_tostring(L, 2);
- float a = lua_tonumber(L, 3);
- std::string str = ftos(a);
-
- NodeMetadata *meta = getmeta(ref, true);
- if(meta == NULL || str == meta->getString(name))
- return 0;
- meta->setString(name, str);
- reportMetadataChange(ref);
- return 0;
-}
-
// get_inventory(self)
int NodeMetaRef::l_get_inventory(lua_State *L)
{
MAP_LOCK_REQUIRED;
NodeMetaRef *ref = checkobject(L, 1);
- getmeta(ref, true); // try to ensure the metadata exists
+ ref->getmeta(true); // try to ensure the metadata exists
InvRef::createNodeMeta(L, ref->m_p);
return 1;
}
-// to_table(self)
-int NodeMetaRef::l_to_table(lua_State *L)
+// mark_as_private(self, <string> or {<string>, <string>, ...})
+int NodeMetaRef::l_mark_as_private(lua_State *L)
{
MAP_LOCK_REQUIRED;
NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = dynamic_cast<NodeMetadata*>(ref->getmeta(true));
+ assert(meta);
- NodeMetadata *meta = getmeta(ref, true);
- if (meta == NULL) {
+ if (lua_istable(L, 2)) {
lua_pushnil(L);
- return 1;
+ while (lua_next(L, 2) != 0) {
+ // key at index -2 and value at index -1
+ luaL_checktype(L, -1, LUA_TSTRING);
+ meta->markPrivate(lua_tostring(L, -1), true);
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ }
+ } else if (lua_isstring(L, 2)) {
+ meta->markPrivate(lua_tostring(L, 2), true);
}
- lua_newtable(L);
+ ref->reportMetadataChange();
+ return 0;
+}
+
+void NodeMetaRef::handleToTable(lua_State *L, Metadata *_meta)
+{
// fields
- lua_newtable(L);
- {
- StringMap fields = meta->getStrings();
- for (StringMap::const_iterator
- it = fields.begin(); it != fields.end(); ++it) {
- const std::string &name = it->first;
- const std::string &value = it->second;
- lua_pushlstring(L, name.c_str(), name.size());
- lua_pushlstring(L, value.c_str(), value.size());
- lua_settable(L, -3);
- }
- }
- lua_setfield(L, -2, "fields");
+ MetaDataRef::handleToTable(L, _meta);
+
+ NodeMetadata *meta = (NodeMetadata*) _meta;
// inventory
lua_newtable(L);
@@ -234,71 +133,52 @@ int NodeMetaRef::l_to_table(lua_State *L)
if (inv) {
std::vector<const InventoryList *> lists = inv->getLists();
for(std::vector<const InventoryList *>::const_iterator
- i = lists.begin(); i != lists.end(); i++) {
+ i = lists.begin(); i != lists.end(); ++i) {
push_inventory_list(L, inv, (*i)->getName().c_str());
lua_setfield(L, -2, (*i)->getName().c_str());
}
}
lua_setfield(L, -2, "inventory");
- return 1;
}
// from_table(self, table)
-int NodeMetaRef::l_from_table(lua_State *L)
+bool NodeMetaRef::handleFromTable(lua_State *L, int table, Metadata *_meta)
{
- MAP_LOCK_REQUIRED;
-
- NodeMetaRef *ref = checkobject(L, 1);
- int base = 2;
-
- // clear old metadata first
- ref->m_env->getMap().removeNodeMetadata(ref->m_p);
+ // fields
+ if (!MetaDataRef::handleFromTable(L, table, _meta))
+ return false;
- if(lua_isnil(L, base)){
- // No metadata
- lua_pushboolean(L, true);
- return 1;
- }
+ NodeMetadata *meta = (NodeMetadata*) _meta;
- // Create new metadata
- NodeMetadata *meta = getmeta(ref, true);
- if(meta == NULL){
- lua_pushboolean(L, false);
- return 1;
- }
- // Set fields
- lua_getfield(L, base, "fields");
- int fieldstable = lua_gettop(L);
- lua_pushnil(L);
- while(lua_next(L, fieldstable) != 0){
- // key at index -2 and value at index -1
- std::string name = lua_tostring(L, -2);
- size_t cl;
- const char *cs = lua_tolstring(L, -1, &cl);
- std::string value(cs, cl);
- meta->setString(name, value);
- lua_pop(L, 1); // removes value, keeps key for next iteration
- }
- // Set inventory
+ // inventory
Inventory *inv = meta->getInventory();
- lua_getfield(L, base, "inventory");
- int inventorytable = lua_gettop(L);
- lua_pushnil(L);
- while(lua_next(L, inventorytable) != 0){
- // key at index -2 and value at index -1
- std::string name = lua_tostring(L, -2);
- read_inventory_list(L, -1, inv, name.c_str(), getServer(L));
- lua_pop(L, 1); // removes value, keeps key for next iteration
+ lua_getfield(L, table, "inventory");
+ if (lua_istable(L, -1)) {
+ int inventorytable = lua_gettop(L);
+ lua_pushnil(L);
+ while (lua_next(L, inventorytable) != 0) {
+ // key at index -2 and value at index -1
+ std::string name = lua_tostring(L, -2);
+ read_inventory_list(L, -1, inv, name.c_str(), getServer(L));
+ lua_pop(L, 1); // Remove value, keep key for next iteration
+ }
+ lua_pop(L, 1);
}
- reportMetadataChange(ref);
- lua_pushboolean(L, true);
- return 1;
+
+ return true;
}
NodeMetaRef::NodeMetaRef(v3s16 p, ServerEnvironment *env):
m_p(p),
- m_env(env)
+ m_env(env),
+ m_is_local(false)
+{
+}
+
+NodeMetaRef::NodeMetaRef(Metadata *meta):
+ m_meta(meta),
+ m_is_local(true)
{
}
@@ -317,7 +197,17 @@ void NodeMetaRef::create(lua_State *L, v3s16 p, ServerEnvironment *env)
lua_setmetatable(L, -2);
}
-void NodeMetaRef::Register(lua_State *L)
+// Client-sided version of the above
+void NodeMetaRef::createClient(lua_State *L, Metadata *meta)
+{
+ NodeMetaRef *o = new NodeMetaRef(meta);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+}
+
+const char NodeMetaRef::className[] = "NodeMetaRef";
+void NodeMetaRef::RegisterCommon(lua_State *L)
{
lua_newtable(L);
int methodtable = lua_gettop(L);
@@ -328,6 +218,10 @@ void NodeMetaRef::Register(lua_State *L)
lua_pushvalue(L, methodtable);
lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+ lua_pushliteral(L, "metadata_class");
+ lua_pushlstring(L, className, strlen(className));
+ lua_settable(L, metatable);
+
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
lua_settable(L, metatable);
@@ -336,25 +230,49 @@ void NodeMetaRef::Register(lua_State *L)
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
+ lua_pushliteral(L, "__eq");
+ lua_pushcfunction(L, l_equals);
+ lua_settable(L, metatable);
+
lua_pop(L, 1); // drop metatable
+}
- luaL_openlib(L, 0, methods, 0); // fill methodtable
+void NodeMetaRef::Register(lua_State *L)
+{
+ RegisterCommon(L);
+ luaL_openlib(L, 0, methodsServer, 0); // fill methodtable
lua_pop(L, 1); // drop methodtable
-
- // Cannot be created from Lua
- //lua_register(L, className, create_object);
}
-const char NodeMetaRef::className[] = "NodeMetaRef";
-const luaL_reg NodeMetaRef::methods[] = {
- luamethod(NodeMetaRef, get_string),
- luamethod(NodeMetaRef, set_string),
- luamethod(NodeMetaRef, get_int),
- luamethod(NodeMetaRef, set_int),
- luamethod(NodeMetaRef, get_float),
- luamethod(NodeMetaRef, set_float),
+
+const luaL_Reg NodeMetaRef::methodsServer[] = {
+ luamethod(MetaDataRef, get_string),
+ luamethod(MetaDataRef, set_string),
+ luamethod(MetaDataRef, get_int),
+ luamethod(MetaDataRef, set_int),
+ luamethod(MetaDataRef, get_float),
+ luamethod(MetaDataRef, set_float),
+ luamethod(MetaDataRef, to_table),
+ luamethod(MetaDataRef, from_table),
luamethod(NodeMetaRef, get_inventory),
- luamethod(NodeMetaRef, to_table),
- luamethod(NodeMetaRef, from_table),
+ luamethod(NodeMetaRef, mark_as_private),
+ luamethod(MetaDataRef, equals),
+ {0,0}
+};
+
+
+void NodeMetaRef::RegisterClient(lua_State *L)
+{
+ RegisterCommon(L);
+ luaL_openlib(L, 0, methodsClient, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+}
+
+
+const luaL_Reg NodeMetaRef::methodsClient[] = {
+ luamethod(MetaDataRef, get_string),
+ luamethod(MetaDataRef, get_int),
+ luamethod(MetaDataRef, get_float),
+ luamethod(MetaDataRef, to_table),
{0,0}
};
diff --git a/src/script/lua_api/l_nodemeta.h b/src/script/lua_api/l_nodemeta.h
index e39ac3931..dd4260ff9 100644
--- a/src/script/lua_api/l_nodemeta.h
+++ b/src/script/lua_api/l_nodemeta.h
@@ -20,7 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define L_NODEMETA_H_
#include "lua_api/l_base.h"
+#include "lua_api/l_metadata.h"
#include "irrlichttypes_bloated.h"
+#include "nodemetadata.h"
class ServerEnvironment;
class NodeMetadata;
@@ -29,13 +31,16 @@ class NodeMetadata;
NodeMetaRef
*/
-class NodeMetaRef : public ModApiBase {
+class NodeMetaRef : public MetaDataRef {
private:
v3s16 m_p;
ServerEnvironment *m_env;
+ Metadata *m_meta;
+ bool m_is_local;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methodsServer[];
+ static const luaL_Reg methodsClient[];
static NodeMetaRef *checkobject(lua_State *L, int narg);
@@ -52,44 +57,28 @@ private:
* @param auto_create when true, try to create metadata information for the node if it has none.
* @return pointer to a @c NodeMetadata object or @c NULL in case of error.
*/
- static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create);
+ virtual Metadata* getmeta(bool auto_create);
+ virtual void clearMeta();
- static void reportMetadataChange(NodeMetaRef *ref);
+ virtual void reportMetadataChange();
+
+ virtual void handleToTable(lua_State *L, Metadata *_meta);
+ virtual bool handleFromTable(lua_State *L, int table, Metadata *_meta);
// Exported functions
// garbage collector
static int gc_object(lua_State *L);
- // get_string(self, name)
- static int l_get_string(lua_State *L);
-
- // set_string(self, name, var)
- static int l_set_string(lua_State *L);
-
- // get_int(self, name)
- static int l_get_int(lua_State *L);
-
- // set_int(self, name, var)
- static int l_set_int(lua_State *L);
-
- // get_float(self, name)
- static int l_get_float(lua_State *L);
-
- // set_float(self, name, var)
- static int l_set_float(lua_State *L);
-
// get_inventory(self)
static int l_get_inventory(lua_State *L);
- // to_table(self)
- static int l_to_table(lua_State *L);
-
- // from_table(self, table)
- static int l_from_table(lua_State *L);
+ // mark_as_private(self, <string> or {<string>, <string>, ...})
+ static int l_mark_as_private(lua_State *L);
public:
NodeMetaRef(v3s16 p, ServerEnvironment *env);
+ NodeMetaRef(Metadata *meta);
~NodeMetaRef();
@@ -97,7 +86,12 @@ public:
// Not callable from Lua; all references are created on the C side.
static void create(lua_State *L, v3s16 p, ServerEnvironment *env);
+ // Client-sided version of the above
+ static void createClient(lua_State *L, Metadata *meta);
+
+ static void RegisterCommon(lua_State *L);
static void Register(lua_State *L);
+ static void RegisterClient(lua_State *L);
};
#endif /* L_NODEMETA_H_ */
diff --git a/src/script/lua_api/l_nodetimer.cpp b/src/script/lua_api/l_nodetimer.cpp
index 3242d6ea5..17b275c46 100644
--- a/src/script/lua_api/l_nodetimer.cpp
+++ b/src/script/lua_api/l_nodetimer.cpp
@@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_nodetimer.h"
#include "lua_api/l_internal.h"
-#include "environment.h"
+#include "serverenvironment.h"
#include "map.h"
@@ -162,7 +162,7 @@ void NodeTimerRef::Register(lua_State *L)
}
const char NodeTimerRef::className[] = "NodeTimerRef";
-const luaL_reg NodeTimerRef::methods[] = {
+const luaL_Reg NodeTimerRef::methods[] = {
luamethod(NodeTimerRef, start),
luamethod(NodeTimerRef, set),
luamethod(NodeTimerRef, stop),
diff --git a/src/script/lua_api/l_nodetimer.h b/src/script/lua_api/l_nodetimer.h
index 9f8dd21c8..ae362d8b3 100644
--- a/src/script/lua_api/l_nodetimer.h
+++ b/src/script/lua_api/l_nodetimer.h
@@ -20,18 +20,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef L_NODETIMER_H_
#define L_NODETIMER_H_
-#include "lua_api/l_base.h"
#include "irr_v3d.h"
+#include "lua_api/l_base.h"
class ServerEnvironment;
-class NodeTimerRef : public ModApiBase {
+class NodeTimerRef : public ModApiBase
+{
private:
v3s16 m_p;
ServerEnvironment *m_env;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
static int gc_object(lua_State *L);
@@ -62,6 +63,4 @@ public:
static void Register(lua_State *L);
};
-
-
#endif /* L_NODETIMER_H_ */
diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp
index e0039371f..e3e76191f 100644
--- a/src/script/lua_api/l_noise.cpp
+++ b/src/script/lua_api/l_noise.cpp
@@ -135,7 +135,7 @@ void LuaPerlinNoise::Register(lua_State *L)
const char LuaPerlinNoise::className[] = "PerlinNoise";
-const luaL_reg LuaPerlinNoise::methods[] = {
+const luaL_Reg LuaPerlinNoise::methods[] = {
luamethod(LuaPerlinNoise, get2d),
luamethod(LuaPerlinNoise, get3d),
{0,0}
@@ -393,7 +393,7 @@ void LuaPerlinNoiseMap::Register(lua_State *L)
const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
-const luaL_reg LuaPerlinNoiseMap::methods[] = {
+const luaL_Reg LuaPerlinNoiseMap::methods[] = {
luamethod(LuaPerlinNoiseMap, get2dMap),
luamethod(LuaPerlinNoiseMap, get2dMap_flat),
luamethod(LuaPerlinNoiseMap, calc2dMap),
@@ -498,7 +498,7 @@ void LuaPseudoRandom::Register(lua_State *L)
const char LuaPseudoRandom::className[] = "PseudoRandom";
-const luaL_reg LuaPseudoRandom::methods[] = {
+const luaL_Reg LuaPseudoRandom::methods[] = {
luamethod(LuaPseudoRandom, next),
{0,0}
};
@@ -597,7 +597,7 @@ void LuaPcgRandom::Register(lua_State *L)
const char LuaPcgRandom::className[] = "PcgRandom";
-const luaL_reg LuaPcgRandom::methods[] = {
+const luaL_Reg LuaPcgRandom::methods[] = {
luamethod(LuaPcgRandom, next),
luamethod(LuaPcgRandom, rand_normal_dist),
{0,0}
@@ -711,7 +711,7 @@ void LuaSecureRandom::Register(lua_State *L)
}
const char LuaSecureRandom::className[] = "SecureRandom";
-const luaL_reg LuaSecureRandom::methods[] = {
+const luaL_Reg LuaSecureRandom::methods[] = {
luamethod(LuaSecureRandom, next_bytes),
{0,0}
};
diff --git a/src/script/lua_api/l_noise.h b/src/script/lua_api/l_noise.h
index 40bfd1315..f252b5ba2 100644
--- a/src/script/lua_api/l_noise.h
+++ b/src/script/lua_api/l_noise.h
@@ -20,18 +20,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef L_NOISE_H_
#define L_NOISE_H_
-#include "lua_api/l_base.h"
#include "irr_v3d.h"
+#include "lua_api/l_base.h"
#include "noise.h"
/*
LuaPerlinNoise
*/
-class LuaPerlinNoise : public ModApiBase {
+class LuaPerlinNoise : public ModApiBase
+{
private:
NoiseParams np;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
// Exported functions
@@ -57,12 +58,13 @@ public:
/*
LuaPerlinNoiseMap
*/
-class LuaPerlinNoiseMap : public ModApiBase {
+class LuaPerlinNoiseMap : public ModApiBase
+{
NoiseParams np;
Noise *noise;
bool m_is3d;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
// Exported functions
@@ -95,12 +97,13 @@ public:
/*
LuaPseudoRandom
*/
-class LuaPseudoRandom : public ModApiBase {
+class LuaPseudoRandom : public ModApiBase
+{
private:
PseudoRandom m_pseudo;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
// Exported functions
@@ -111,8 +114,7 @@ private:
static int l_next(lua_State *L);
public:
- LuaPseudoRandom(s32 seed) :
- m_pseudo(seed) {}
+ LuaPseudoRandom(s32 seed) : m_pseudo(seed) {}
// LuaPseudoRandom(seed)
// Creates an LuaPseudoRandom and leaves it on top of stack
@@ -126,12 +128,13 @@ public:
/*
LuaPcgRandom
*/
-class LuaPcgRandom : public ModApiBase {
+class LuaPcgRandom : public ModApiBase
+{
private:
PcgRandom m_rnd;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
// Exported functions
@@ -146,10 +149,8 @@ private:
static int l_rand_normal_dist(lua_State *L);
public:
- LuaPcgRandom(u64 seed) :
- m_rnd(seed) {}
- LuaPcgRandom(u64 seed, u64 seq) :
- m_rnd(seed, seq) {}
+ LuaPcgRandom(u64 seed) : m_rnd(seed) {}
+ LuaPcgRandom(u64 seed, u64 seq) : m_rnd(seed, seq) {}
// LuaPcgRandom(seed)
// Creates an LuaPcgRandom and leaves it on top of stack
@@ -160,15 +161,15 @@ public:
static void Register(lua_State *L);
};
-
/*
LuaSecureRandom
*/
-class LuaSecureRandom : public ModApiBase {
+class LuaSecureRandom : public ModApiBase
+{
private:
static const size_t RAND_BUF_SIZE = 2048;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
u32 m_rand_idx;
char m_rand_buf[RAND_BUF_SIZE];
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 2a8b8a64e..aaab0d98e 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_sao.h"
#include "server.h"
#include "hud.h"
-#include "scripting_game.h"
+#include "scripting_server.h"
struct EnumString es_HudElementType[] =
{
@@ -137,8 +137,8 @@ int ObjectRef::l_remove(lua_State *L)
if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
return 0;
- UNORDERED_SET<int> child_ids = co->getAttachmentChildIds();
- UNORDERED_SET<int>::iterator it;
+ const UNORDERED_SET<int> &child_ids = co->getAttachmentChildIds();
+ UNORDERED_SET<int>::const_iterator it;
for (it = child_ids.begin(); it != child_ids.end(); ++it) {
// Child can be NULL if it was deleted earlier
if (ServerActiveObject *child = env->getActiveObject(*it))
@@ -150,9 +150,9 @@ int ObjectRef::l_remove(lua_State *L)
return 0;
}
-// getpos(self)
+// get_pos(self)
// returns: {x=num, y=num, z=num}
-int ObjectRef::l_getpos(lua_State *L)
+int ObjectRef::l_get_pos(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -169,8 +169,8 @@ int ObjectRef::l_getpos(lua_State *L)
return 1;
}
-// setpos(self, pos)
-int ObjectRef::l_setpos(lua_State *L)
+// set_pos(self, pos)
+int ObjectRef::l_set_pos(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -184,8 +184,8 @@ int ObjectRef::l_setpos(lua_State *L)
return 0;
}
-// moveto(self, pos, continuous=false)
-int ObjectRef::l_moveto(lua_State *L)
+// move_to(self, pos, continuous=false)
+int ObjectRef::l_move_to(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -364,7 +364,7 @@ int ObjectRef::l_set_wielded_item(lua_State *L)
ServerActiveObject *co = getobject(ref);
if (co == NULL) return 0;
// Do it
- ItemStack item = read_item(L, 2, getServer(L));
+ ItemStack item = read_item(L, 2, getServer(L)->idef());
bool success = co->setWieldedItem(item);
if (success && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
getServer(L)->SendInventory(((PlayerSAO*)co));
@@ -396,13 +396,12 @@ int ObjectRef::l_get_armor_groups(lua_State *L)
if (co == NULL)
return 0;
// Do it
- ItemGroupList groups = co->getArmorGroups();
- push_groups(L, groups);
+ push_groups(L, co->getArmorGroups());
return 1;
}
// set_physics_override(self, physics_override_speed, physics_override_jump,
-// physics_override_gravity, sneak, sneak_glitch)
+// physics_override_gravity, sneak, sneak_glitch, new_move)
int ObjectRef::l_set_physics_override(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@@ -411,11 +410,18 @@ int ObjectRef::l_set_physics_override(lua_State *L)
if (co == NULL) return 0;
// Do it
if (lua_istable(L, 2)) {
- co->m_physics_override_speed = getfloatfield_default(L, 2, "speed", co->m_physics_override_speed);
- co->m_physics_override_jump = getfloatfield_default(L, 2, "jump", co->m_physics_override_jump);
- co->m_physics_override_gravity = getfloatfield_default(L, 2, "gravity", co->m_physics_override_gravity);
- co->m_physics_override_sneak = getboolfield_default(L, 2, "sneak", co->m_physics_override_sneak);
- co->m_physics_override_sneak_glitch = getboolfield_default(L, 2, "sneak_glitch", co->m_physics_override_sneak_glitch);
+ co->m_physics_override_speed = getfloatfield_default(
+ L, 2, "speed", co->m_physics_override_speed);
+ co->m_physics_override_jump = getfloatfield_default(
+ L, 2, "jump", co->m_physics_override_jump);
+ co->m_physics_override_gravity = getfloatfield_default(
+ L, 2, "gravity", co->m_physics_override_gravity);
+ co->m_physics_override_sneak = getboolfield_default(
+ L, 2, "sneak", co->m_physics_override_sneak);
+ co->m_physics_override_sneak_glitch = getboolfield_default(
+ L, 2, "sneak_glitch", co->m_physics_override_sneak_glitch);
+ co->m_physics_override_new_move = getboolfield_default(
+ L, 2, "new_move", co->m_physics_override_new_move);
co->m_physics_override_sent = false;
} else {
// old, non-table format
@@ -455,6 +461,8 @@ int ObjectRef::l_get_physics_override(lua_State *L)
lua_setfield(L, -2, "sneak");
lua_pushboolean(L, co->m_physics_override_sneak_glitch);
lua_setfield(L, -2, "sneak_glitch");
+ lua_pushboolean(L, co->m_physics_override_new_move);
+ lua_setfield(L, -2, "new_move");
return 1;
}
@@ -718,11 +726,13 @@ int ObjectRef::l_set_detach(lua_State *L)
v3f rotation;
co->getAttachment(&parent_id, &bone, &position, &rotation);
ServerActiveObject *parent = NULL;
- if (parent_id)
+ if (parent_id) {
parent = env->getActiveObject(parent_id);
-
+ co->setAttachment(0, "", position, rotation);
+ } else {
+ co->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0));
+ }
// Do it
- co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
if (parent != NULL)
parent->removeAttachmentChild(co->getId());
return 0;
@@ -738,7 +748,7 @@ int ObjectRef::l_set_properties(lua_State *L)
ObjectProperties *prop = co->accessObjectProperties();
if (!prop)
return 0;
- read_object_properties(L, 2, prop);
+ read_object_properties(L, 2, prop, getServer(L)->idef());
co->notifyObjectPropertiesModified();
return 0;
}
@@ -790,8 +800,7 @@ int ObjectRef::l_set_nametag_attributes(lua_State *L)
lua_pop(L, 1);
std::string nametag = getstringfield_default(L, 2, "text", "");
- if (nametag != "")
- prop->nametag = nametag;
+ prop->nametag = nametag;
co->notifyObjectPropertiesModified();
lua_pushboolean(L, true);
@@ -823,8 +832,8 @@ int ObjectRef::l_get_nametag_attributes(lua_State *L)
/* LuaEntitySAO-only */
-// setvelocity(self, {x=num, y=num, z=num})
-int ObjectRef::l_setvelocity(lua_State *L)
+// set_velocity(self, {x=num, y=num, z=num})
+int ObjectRef::l_set_velocity(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -836,8 +845,8 @@ int ObjectRef::l_setvelocity(lua_State *L)
return 0;
}
-// getvelocity(self)
-int ObjectRef::l_getvelocity(lua_State *L)
+// get_velocity(self)
+int ObjectRef::l_get_velocity(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -849,8 +858,8 @@ int ObjectRef::l_getvelocity(lua_State *L)
return 1;
}
-// setacceleration(self, {x=num, y=num, z=num})
-int ObjectRef::l_setacceleration(lua_State *L)
+// set_acceleration(self, {x=num, y=num, z=num})
+int ObjectRef::l_set_acceleration(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -863,8 +872,8 @@ int ObjectRef::l_setacceleration(lua_State *L)
return 0;
}
-// getacceleration(self)
-int ObjectRef::l_getacceleration(lua_State *L)
+// get_acceleration(self)
+int ObjectRef::l_get_acceleration(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -876,8 +885,8 @@ int ObjectRef::l_getacceleration(lua_State *L)
return 1;
}
-// setyaw(self, radians)
-int ObjectRef::l_setyaw(lua_State *L)
+// set_yaw(self, radians)
+int ObjectRef::l_set_yaw(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -889,8 +898,8 @@ int ObjectRef::l_setyaw(lua_State *L)
return 0;
}
-// getyaw(self)
-int ObjectRef::l_getyaw(lua_State *L)
+// get_yaw(self)
+int ObjectRef::l_get_yaw(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -902,8 +911,8 @@ int ObjectRef::l_getyaw(lua_State *L)
return 1;
}
-// settexturemod(self, mod)
-int ObjectRef::l_settexturemod(lua_State *L)
+// set_texture_mod(self, mod)
+int ObjectRef::l_set_texture_mod(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -915,9 +924,22 @@ int ObjectRef::l_settexturemod(lua_State *L)
return 0;
}
-// setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
+// get_texture_mod(self)
+int ObjectRef::l_get_texture_mod(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ LuaEntitySAO *co = getluaobject(ref);
+ if (co == NULL) return 0;
+ // Do it
+ std::string mod = co->getTextureMod();
+ lua_pushstring(L, mod.c_str());
+ return 1;
+}
+
+// set_sprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
// select_horiz_by_yawpitch=false)
-int ObjectRef::l_setsprite(lua_State *L)
+int ObjectRef::l_set_sprite(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
@@ -1152,13 +1174,8 @@ int ObjectRef::l_set_breath(lua_State *L)
PlayerSAO* co = getplayersao(ref);
if (co == NULL) return 0;
u16 breath = luaL_checknumber(L, 2);
- // Do it
co->setBreath(breath);
- // If the object is a player sent the breath to client
- if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
- getServer(L)->SendPlayerBreath(((PlayerSAO*)co)->getPeerID());
-
return 0;
}
@@ -1175,6 +1192,46 @@ int ObjectRef::l_get_breath(lua_State *L)
return 1;
}
+// set_attribute(self, attribute, value)
+int ObjectRef::l_set_attribute(lua_State *L)
+{
+ ObjectRef *ref = checkobject(L, 1);
+ PlayerSAO* co = getplayersao(ref);
+ if (co == NULL) {
+ return 0;
+ }
+
+ std::string attr = luaL_checkstring(L, 2);
+ if (lua_isnil(L, 3)) {
+ co->removeExtendedAttribute(attr);
+ } else {
+ std::string value = luaL_checkstring(L, 3);
+ co->setExtendedAttribute(attr, value);
+ }
+ return 1;
+}
+
+// get_attribute(self, attribute)
+int ObjectRef::l_get_attribute(lua_State *L)
+{
+ ObjectRef *ref = checkobject(L, 1);
+ PlayerSAO* co = getplayersao(ref);
+ if (co == NULL) {
+ return 0;
+ }
+
+ std::string attr = luaL_checkstring(L, 2);
+
+ std::string value = "";
+ if (co->getExtendedAttribute(attr, &value)) {
+ lua_pushstring(L, value.c_str());
+ return 1;
+ }
+
+ return 0;
+}
+
+
// set_inventory_formspec(self, formspec)
int ObjectRef::l_set_inventory_formspec(lua_State *L)
{
@@ -1606,7 +1663,7 @@ int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
return 1;
}
-// set_sky(self, bgcolor, type, list)
+// set_sky(self, bgcolor, type, list, clouds = true)
int ObjectRef::l_set_sky(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@@ -1622,9 +1679,8 @@ int ObjectRef::l_set_sky(lua_State *L)
std::vector<std::string> params;
if (lua_istable(L, 4)) {
- int table = lua_gettop(L);
lua_pushnil(L);
- while (lua_next(L, table) != 0) {
+ while (lua_next(L, 4) != 0) {
// key at index -2 and value at index -1
if (lua_isstring(L, -1))
params.push_back(lua_tostring(L, -1));
@@ -1638,7 +1694,11 @@ int ObjectRef::l_set_sky(lua_State *L)
if (type == "skybox" && params.size() != 6)
throw LuaError("skybox expects 6 textures");
- if (!getServer(L)->setSky(player, bgcolor, type, params))
+ bool clouds = true;
+ if (lua_isboolean(L, 5))
+ clouds = lua_toboolean(L, 5);
+
+ if (!getServer(L)->setSky(player, bgcolor, type, params, clouds))
return 0;
lua_pushboolean(L, true);
@@ -1656,8 +1716,9 @@ int ObjectRef::l_get_sky(lua_State *L)
video::SColor bgcolor(255, 255, 255, 255);
std::string type;
std::vector<std::string> params;
+ bool clouds;
- player->getSky(&bgcolor, &type, &params);
+ player->getSky(&bgcolor, &type, &params, &clouds);
type = type == "" ? "regular" : type;
push_ARGB8(L, bgcolor);
@@ -1670,9 +1731,89 @@ int ObjectRef::l_get_sky(lua_State *L)
lua_rawseti(L, -2, i);
i++;
}
- return 3;
+ lua_pushboolean(L, clouds);
+ return 4;
}
+// set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=})
+int ObjectRef::l_set_clouds(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ RemotePlayer *player = getplayer(ref);
+ if (!player)
+ return 0;
+ if (!lua_istable(L, 2))
+ return 0;
+
+ CloudParams cloud_params = player->getCloudParams();
+
+ cloud_params.density = getfloatfield_default(L, 2, "density", cloud_params.density);
+
+ lua_getfield(L, 2, "color");
+ if (!lua_isnil(L, -1))
+ read_color(L, -1, &cloud_params.color_bright);
+ lua_pop(L, 1);
+ lua_getfield(L, 2, "ambient");
+ if (!lua_isnil(L, -1))
+ read_color(L, -1, &cloud_params.color_ambient);
+ lua_pop(L, 1);
+
+ cloud_params.height = getfloatfield_default(L, 2, "height", cloud_params.height );
+ cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
+
+ lua_getfield(L, 2, "speed");
+ if (lua_istable(L, -1)) {
+ v2f new_speed;
+ new_speed.X = getfloatfield_default(L, -1, "x", 0);
+ new_speed.Y = getfloatfield_default(L, -1, "y", 0);
+ cloud_params.speed = new_speed;
+ }
+ lua_pop(L, 1);
+
+ if (!getServer(L)->setClouds(player, cloud_params.density,
+ cloud_params.color_bright, cloud_params.color_ambient,
+ cloud_params.height, cloud_params.thickness,
+ cloud_params.speed))
+ return 0;
+
+ player->setCloudParams(cloud_params);
+
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+int ObjectRef::l_get_clouds(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ RemotePlayer *player = getplayer(ref);
+ if (!player)
+ return 0;
+ const CloudParams &cloud_params = player->getCloudParams();
+
+ lua_newtable(L);
+ lua_pushnumber(L, cloud_params.density);
+ lua_setfield(L, -2, "density");
+ push_ARGB8(L, cloud_params.color_bright);
+ lua_setfield(L, -2, "color");
+ push_ARGB8(L, cloud_params.color_ambient);
+ lua_setfield(L, -2, "ambient");
+ lua_pushnumber(L, cloud_params.height);
+ lua_setfield(L, -2, "height");
+ lua_pushnumber(L, cloud_params.thickness);
+ lua_setfield(L, -2, "thickness");
+ lua_newtable(L);
+ lua_pushnumber(L, cloud_params.speed.X);
+ lua_setfield(L, -2, "x");
+ lua_pushnumber(L, cloud_params.speed.Y);
+ lua_setfield(L, -2, "y");
+ lua_setfield(L, -2, "speed");
+
+ return 1;
+}
+
+
// override_day_night_ratio(self, brightness=0...1)
int ObjectRef::l_override_day_night_ratio(lua_State *L)
{
@@ -1778,12 +1919,12 @@ void ObjectRef::Register(lua_State *L)
}
const char ObjectRef::className[] = "ObjectRef";
-const luaL_reg ObjectRef::methods[] = {
+const luaL_Reg ObjectRef::methods[] = {
// ServerActiveObject
luamethod(ObjectRef, remove),
- luamethod(ObjectRef, getpos),
- luamethod(ObjectRef, setpos),
- luamethod(ObjectRef, moveto),
+ luamethod_aliased(ObjectRef, get_pos, getpos),
+ luamethod_aliased(ObjectRef, set_pos, setpos),
+ luamethod_aliased(ObjectRef, move_to, moveto),
luamethod(ObjectRef, punch),
luamethod(ObjectRef, right_click),
luamethod(ObjectRef, set_hp),
@@ -1807,14 +1948,14 @@ const luaL_reg ObjectRef::methods[] = {
luamethod(ObjectRef, set_nametag_attributes),
luamethod(ObjectRef, get_nametag_attributes),
// LuaEntitySAO-only
- luamethod(ObjectRef, setvelocity),
- luamethod(ObjectRef, getvelocity),
- luamethod(ObjectRef, setacceleration),
- luamethod(ObjectRef, getacceleration),
- luamethod(ObjectRef, setyaw),
- luamethod(ObjectRef, getyaw),
- luamethod(ObjectRef, settexturemod),
- luamethod(ObjectRef, setsprite),
+ luamethod_aliased(ObjectRef, set_velocity, setvelocity),
+ luamethod_aliased(ObjectRef, get_velocity, getvelocity),
+ luamethod_aliased(ObjectRef, set_acceleration, setacceleration),
+ luamethod_aliased(ObjectRef, get_acceleration, getacceleration),
+ luamethod_aliased(ObjectRef, set_yaw, setyaw),
+ luamethod_aliased(ObjectRef, get_yaw, getyaw),
+ luamethod_aliased(ObjectRef, set_texture_mod, settexturemod),
+ luamethod_aliased(ObjectRef, set_sprite, setsprite),
luamethod(ObjectRef, get_entity_name),
luamethod(ObjectRef, get_luaentity),
// Player-only
@@ -1833,6 +1974,8 @@ const luaL_reg ObjectRef::methods[] = {
luamethod(ObjectRef, set_look_pitch),
luamethod(ObjectRef, get_breath),
luamethod(ObjectRef, set_breath),
+ luamethod(ObjectRef, get_attribute),
+ luamethod(ObjectRef, set_attribute),
luamethod(ObjectRef, set_inventory_formspec),
luamethod(ObjectRef, get_inventory_formspec),
luamethod(ObjectRef, get_player_control),
@@ -1853,6 +1996,8 @@ const luaL_reg ObjectRef::methods[] = {
luamethod(ObjectRef, hud_get_hotbar_selected_image),
luamethod(ObjectRef, set_sky),
luamethod(ObjectRef, get_sky),
+ luamethod(ObjectRef, set_clouds),
+ luamethod(ObjectRef, get_clouds),
luamethod(ObjectRef, override_day_night_ratio),
luamethod(ObjectRef, get_day_night_ratio),
luamethod(ObjectRef, set_local_animation),
diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h
index 09f10e417..9801ce02b 100644
--- a/src/script/lua_api/l_object.h
+++ b/src/script/lua_api/l_object.h
@@ -37,7 +37,7 @@ private:
ServerActiveObject *m_object;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
public:
static ObjectRef *checkobject(lua_State *L, int narg);
@@ -57,15 +57,15 @@ private:
// remove(self)
static int l_remove(lua_State *L);
- // getpos(self)
+ // get_pos(self)
// returns: {x=num, y=num, z=num}
- static int l_getpos(lua_State *L);
+ static int l_get_pos(lua_State *L);
- // setpos(self, pos)
- static int l_setpos(lua_State *L);
+ // set_pos(self, pos)
+ static int l_set_pos(lua_State *L);
- // moveto(self, pos, continuous=false)
- static int l_moveto(lua_State *L);
+ // move_to(self, pos, continuous=false)
+ static int l_move_to(lua_State *L);
// punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
static int l_punch(lua_State *L);
@@ -105,7 +105,7 @@ private:
static int l_get_armor_groups(lua_State *L);
// set_physics_override(self, physics_override_speed, physics_override_jump,
- // physics_override_gravity, sneak, sneak_glitch)
+ // physics_override_gravity, sneak, sneak_glitch, new_move)
static int l_set_physics_override(lua_State *L);
// get_physics_override(self)
@@ -143,30 +143,33 @@ private:
/* LuaEntitySAO-only */
- // setvelocity(self, {x=num, y=num, z=num})
- static int l_setvelocity(lua_State *L);
+ // set_velocity(self, {x=num, y=num, z=num})
+ static int l_set_velocity(lua_State *L);
- // getvelocity(self)
- static int l_getvelocity(lua_State *L);
+ // get_velocity(self)
+ static int l_get_velocity(lua_State *L);
- // setacceleration(self, {x=num, y=num, z=num})
- static int l_setacceleration(lua_State *L);
+ // set_acceleration(self, {x=num, y=num, z=num})
+ static int l_set_acceleration(lua_State *L);
- // getacceleration(self)
- static int l_getacceleration(lua_State *L);
+ // get_acceleration(self)
+ static int l_get_acceleration(lua_State *L);
- // setyaw(self, radians)
- static int l_setyaw(lua_State *L);
+ // set_yaw(self, radians)
+ static int l_set_yaw(lua_State *L);
- // getyaw(self)
- static int l_getyaw(lua_State *L);
+ // get_yaw(self)
+ static int l_get_yaw(lua_State *L);
- // settexturemod(self, mod)
- static int l_settexturemod(lua_State *L);
+ // set_texture_mod(self, mod)
+ static int l_set_texture_mod(lua_State *L);
- // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
+ // l_get_texture_mod(self)
+ static int l_get_texture_mod(lua_State *L);
+
+ // set_sprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
// select_horiz_by_yawpitch=false)
- static int l_setsprite(lua_State *L);
+ static int l_set_sprite(lua_State *L);
// DEPRECATED
// get_entity_name(self)
@@ -223,6 +226,12 @@ private:
// get_breath(self, breath)
static int l_get_breath(lua_State *L);
+ // set_attribute(self, attribute, value)
+ static int l_set_attribute(lua_State *L);
+
+ // get_attribute(self, attribute)
+ static int l_get_attribute(lua_State *L);
+
// set_inventory_formspec(self, formspec)
static int l_set_inventory_formspec(lua_State *L);
@@ -274,12 +283,18 @@ private:
// hud_get_hotbar_selected_image(self)
static int l_hud_get_hotbar_selected_image(lua_State *L);
- // set_sky(self, type, list)
+ // set_sky(self, bgcolor, type, list, clouds = true)
static int l_set_sky(lua_State *L);
- // get_sky(self, type, list)
+ // get_sky(self)
static int l_get_sky(lua_State *L);
+ // set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=})
+ static int l_set_clouds(lua_State *L);
+
+ // get_clouds(self)
+ static int l_get_clouds(lua_State *L);
+
// override_day_night_ratio(self, type)
static int l_override_day_night_ratio(lua_State *L);
diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp
index 667ac7272..2f3e9a58d 100644
--- a/src/script/lua_api/l_particles.cpp
+++ b/src/script/lua_api/l_particles.cpp
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_object.h"
#include "lua_api/l_internal.h"
#include "common/c_converter.h"
+#include "common/c_content.h"
#include "server.h"
#include "particles.h"
@@ -34,6 +35,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
// collision_removal = bool
// vertical = bool
// texture = e.g."default_wood.png"
+// animation = TileAnimation definition
+// glow = num
int ModApiParticles::l_add_particle(lua_State *L)
{
MAP_LOCK_REQUIRED;
@@ -47,10 +50,14 @@ int ModApiParticles::l_add_particle(lua_State *L)
bool collisiondetection, vertical, collision_removal;
collisiondetection = vertical = collision_removal = false;
+ struct TileAnimationParams animation;
+ animation.type = TAT_NONE;
std::string texture = "";
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");
@@ -101,11 +108,18 @@ int ModApiParticles::l_add_particle(lua_State *L)
collision_removal = getboolfield_default(L, 1,
"collision_removal", collision_removal);
vertical = getboolfield_default(L, 1, "vertical", vertical);
+
+ lua_getfield(L, 1, "animation");
+ animation = read_animation_definition(L, -1);
+ lua_pop(L, 1);
+
texture = getstringfield_default(L, 1, "texture", "");
playername = getstringfield_default(L, 1, "playername", "");
+
+ glow = getintfield_default(L, 1, "glow", 0);
}
getServer(L)->spawnParticle(playername, pos, vel, acc, expirationtime, size,
- collisiondetection, collision_removal, vertical, texture);
+ collisiondetection, collision_removal, vertical, texture, animation, glow);
return 1;
}
@@ -127,6 +141,8 @@ int ModApiParticles::l_add_particle(lua_State *L)
// collision_removal = bool
// vertical = bool
// texture = e.g."default_wood.png"
+// animation = TileAnimation definition
+// glow = num
int ModApiParticles::l_add_particlespawner(lua_State *L)
{
MAP_LOCK_REQUIRED;
@@ -139,9 +155,12 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
time= minexptime= maxexptime= minsize= maxsize= 1;
bool collisiondetection, vertical, collision_removal;
collisiondetection = vertical = collision_removal = false;
+ struct TileAnimationParams animation;
+ animation.type = TAT_NONE;
ServerActiveObject *attached = NULL;
std::string texture = "";
std::string playername = "";
+ u8 glow = 0;
if (lua_gettop(L) > 1) //deprecated
{
@@ -201,6 +220,10 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
collision_removal = getboolfield_default(L, 1,
"collision_removal", collision_removal);
+ lua_getfield(L, 1, "animation");
+ animation = read_animation_definition(L, -1);
+ lua_pop(L, 1);
+
lua_getfield(L, 1, "attached");
if (!lua_isnil(L, -1)) {
ObjectRef *ref = ObjectRef::checkobject(L, -1);
@@ -211,6 +234,7 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
vertical = getboolfield_default(L, 1, "vertical", vertical);
texture = getstringfield_default(L, 1, "texture", "");
playername = getstringfield_default(L, 1, "playername", "");
+ glow = getintfield_default(L, 1, "glow", 0);
}
u32 id = getServer(L)->addParticleSpawner(amount, time,
@@ -223,7 +247,8 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
collision_removal,
attached,
vertical,
- texture, playername);
+ texture, playername,
+ animation, glow);
lua_pushnumber(L, id);
return 1;
diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp
index b6d44e0ff..a0e475dec 100644
--- a/src/script/lua_api/l_server.cpp
+++ b/src/script/lua_api/l_server.cpp
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "environment.h"
#include "player.h"
#include "log.h"
+#include <algorithm>
// request_shutdown()
int ModApiServer::l_request_shutdown(lua_State *L)
@@ -33,7 +34,8 @@ int ModApiServer::l_request_shutdown(lua_State *L)
NO_MAP_LOCK_REQUIRED;
const char *msg = lua_tolstring(L, 1, NULL);
bool reconnect = lua_toboolean(L, 2);
- getServer(L)->requestShutdown(msg ? msg : "", reconnect);
+ float seconds_before_shutdown = lua_tonumber(L, 3);
+ getServer(L)->requestShutdown(msg ? msg : "", reconnect, seconds_before_shutdown);
return 0;
}
@@ -102,7 +104,7 @@ int ModApiServer::l_get_player_privs(lua_State *L)
int table = lua_gettop(L);
std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
for(std::set<std::string>::const_iterator
- i = privs_s.begin(); i != privs_s.end(); i++){
+ i = privs_s.begin(); i != privs_s.end(); ++i){
lua_pushboolean(L, true);
lua_setfield(L, table, i->c_str());
}
@@ -136,7 +138,7 @@ int ModApiServer::l_get_player_ip(lua_State *L)
}
}
-// get_player_information()
+// get_player_information(name)
int ModApiServer::l_get_player_information(lua_State *L)
{
@@ -230,15 +232,15 @@ int ModApiServer::l_get_player_information(lua_State *L)
lua_pushnumber(L, uptime);
lua_settable(L, table);
+ lua_pushstring(L,"protocol_version");
+ lua_pushnumber(L, prot_vers);
+ lua_settable(L, table);
+
#ifndef NDEBUG
lua_pushstring(L,"serialization_version");
lua_pushnumber(L, ser_vers);
lua_settable(L, table);
- lua_pushstring(L,"protocol_version");
- lua_pushnumber(L, prot_vers);
- lua_settable(L, table);
-
lua_pushstring(L,"major");
lua_pushnumber(L, major);
lua_settable(L, table);
@@ -333,6 +335,22 @@ int ModApiServer::l_kick_player(lua_State *L)
return 1;
}
+int ModApiServer::l_remove_player(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ std::string name = luaL_checkstring(L, 1);
+ ServerEnvironment *s_env = dynamic_cast<ServerEnvironment *>(getEnv(L));
+ assert(s_env);
+
+ RemotePlayer *player = s_env->getPlayer(name.c_str());
+ if (!player)
+ lua_pushinteger(L, s_env->removePlayerFromDatabase(name) ? 0 : 1);
+ else
+ lua_pushinteger(L, 2);
+
+ return 1;
+}
+
// unban_player_or_ip()
int ModApiServer::l_unban_player_or_ip(lua_State *L)
{
@@ -400,7 +418,7 @@ int ModApiServer::l_get_modnames(lua_State *L)
// Package them up for Lua
lua_createtable(L, modlist.size(), 0);
std::vector<std::string>::iterator iter = modlist.begin();
- for (u16 i = 0; iter != modlist.end(); iter++) {
+ for (u16 i = 0; iter != modlist.end(); ++iter) {
lua_pushstring(L, iter->c_str());
lua_rawseti(L, -2, ++i);
}
@@ -438,6 +456,16 @@ int ModApiServer::l_sound_stop(lua_State *L)
return 0;
}
+int ModApiServer::l_sound_fade(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ s32 handle = luaL_checkinteger(L, 1);
+ float step = luaL_checknumber(L, 2);
+ float gain = luaL_checknumber(L, 3);
+ getServer(L)->fadeSound(handle, step, gain);
+ return 0;
+}
+
// is_singleplayer()
int ModApiServer::l_is_singleplayer(lua_State *L)
{
@@ -482,36 +510,6 @@ int ModApiServer::l_set_last_run_mod(lua_State *L)
return 0;
}
-#ifndef NDEBUG
-// cause_error(type_of_error)
-int ModApiServer::l_cause_error(lua_State *L)
-{
- NO_MAP_LOCK_REQUIRED;
- std::string type_of_error = "none";
- if(lua_isstring(L, 1))
- type_of_error = lua_tostring(L, 1);
-
- errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;
-
- if(type_of_error == "segv") {
- volatile int* some_pointer = 0;
- errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;
-
- } else if (type_of_error == "zerodivision") {
-
- unsigned int some_number = porting::getTimeS();
- unsigned int zerovalue = 0;
- unsigned int result = some_number / zerovalue;
- errorstream << "Well this shouldn't ever be shown: " << result << std::endl;
-
- } else if (type_of_error == "exception") {
- throw BaseException("Errorhandler test fct called");
- }
-
- return 0;
-}
-#endif
-
void ModApiServer::Initialize(lua_State *L, int top)
{
API_FCT(request_shutdown);
@@ -531,6 +529,7 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(show_formspec);
API_FCT(sound_play);
API_FCT(sound_stop);
+ API_FCT(sound_fade);
API_FCT(get_player_information);
API_FCT(get_player_privs);
@@ -539,12 +538,10 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(get_ban_description);
API_FCT(ban_player);
API_FCT(kick_player);
+ API_FCT(remove_player);
API_FCT(unban_player_or_ip);
API_FCT(notify_authentication_modified);
API_FCT(get_last_run_mod);
API_FCT(set_last_run_mod);
-#ifndef NDEBUG
- API_FCT(cause_error);
-#endif
}
diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h
index 1ad46d440..251a0ce89 100644
--- a/src/script/lua_api/l_server.h
+++ b/src/script/lua_api/l_server.h
@@ -22,7 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_base.h"
-class ModApiServer : public ModApiBase {
+class ModApiServer : public ModApiBase
+{
private:
// request_shutdown([message], [reconnect])
static int l_request_shutdown(lua_State *L);
@@ -67,13 +68,16 @@ private:
// 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_player_privs(name, text)
static int l_get_player_privs(lua_State *L);
// get_player_ip()
static int l_get_player_ip(lua_State *L);
- // get_player_information()
+ // get_player_information(name)
static int l_get_player_information(lua_State *L);
// get_ban_list()
@@ -91,6 +95,9 @@ private:
// kick_player(name, [message]) -> success
static int l_kick_player(lua_State *L);
+ // remove_player(name)
+ static int l_remove_player(lua_State *L);
+
// notify_authentication_modified(name)
static int l_notify_authentication_modified(lua_State *L);
@@ -100,14 +107,8 @@ private:
// set_last_run_mod(modname)
static int l_set_last_run_mod(lua_State *L);
-#ifndef NDEBUG
- // cause_error(type_of_error)
- static int l_cause_error(lua_State *L);
-#endif
-
public:
static void Initialize(lua_State *L, int top);
-
};
#endif /* L_SERVER_H_ */
diff --git a/src/script/lua_api/l_settings.cpp b/src/script/lua_api/l_settings.cpp
index d3fe03005..70807f3d2 100644
--- a/src/script/lua_api/l_settings.cpp
+++ b/src/script/lua_api/l_settings.cpp
@@ -23,6 +23,47 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include "log.h"
+
+#define SET_SECURITY_CHECK(L, name) \
+ if (o->m_settings == g_settings && ScriptApiSecurity::isSecure(L) && \
+ name.compare(0, 7, "secure.") == 0) { \
+ throw LuaError("Attempt to set secure setting."); \
+ }
+
+LuaSettings::LuaSettings(Settings *settings, const std::string &filename) :
+ m_settings(settings),
+ m_filename(filename),
+ m_is_own_settings(false),
+ m_write_allowed(true)
+{
+}
+
+LuaSettings::LuaSettings(const std::string &filename, bool write_allowed) :
+ m_filename(filename),
+ m_is_own_settings(true),
+ m_write_allowed(write_allowed)
+{
+ m_settings = new Settings();
+ m_settings->readConfigFile(filename.c_str());
+}
+
+LuaSettings::~LuaSettings()
+{
+ if (m_is_own_settings)
+ delete m_settings;
+}
+
+
+void LuaSettings::create(lua_State *L, Settings *settings,
+ const std::string &filename)
+{
+ LuaSettings *o = new LuaSettings(settings, filename);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+}
+
+
// garbage collector
int LuaSettings::gc_object(lua_State* L)
{
@@ -31,6 +72,7 @@ int LuaSettings::gc_object(lua_State* L)
return 0;
}
+
// get(self, key) -> value
int LuaSettings::l_get(lua_State* L)
{
@@ -74,12 +116,30 @@ int LuaSettings::l_set(lua_State* L)
std::string key = std::string(luaL_checkstring(L, 2));
const char* value = luaL_checkstring(L, 3);
+ SET_SECURITY_CHECK(L, key);
+
if (!o->m_settings->set(key, value))
throw LuaError("Invalid sequence found in setting parameters");
return 0;
}
+// set_bool(self, key, value)
+int LuaSettings::l_set_bool(lua_State* L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ LuaSettings* o = checkobject(L, 1);
+
+ std::string key = std::string(luaL_checkstring(L, 2));
+ bool value = lua_toboolean(L, 3);
+
+ SET_SECURITY_CHECK(L, key);
+
+ o->m_settings->setBool(key, value);
+
+ return 1;
+}
+
// remove(self, key) -> success
int LuaSettings::l_remove(lua_State* L)
{
@@ -88,6 +148,8 @@ int LuaSettings::l_remove(lua_State* L)
std::string key = std::string(luaL_checkstring(L, 2));
+ SET_SECURITY_CHECK(L, key);
+
bool success = o->m_settings->remove(key);
lua_pushboolean(L, success);
@@ -147,19 +209,6 @@ int LuaSettings::l_to_table(lua_State* L)
return 1;
}
-LuaSettings::LuaSettings(const char* filename, bool write_allowed)
-{
- m_write_allowed = write_allowed;
- m_filename = std::string(filename);
-
- m_settings = new Settings();
- m_settings->readConfigFile(m_filename.c_str());
-}
-
-LuaSettings::~LuaSettings()
-{
- delete m_settings;
-}
void LuaSettings::Register(lua_State* L)
{
@@ -190,7 +239,7 @@ void LuaSettings::Register(lua_State* L)
}
// LuaSettings(filename)
-// Creates an LuaSettings and leaves it on top of stack
+// Creates a LuaSettings and leaves it on top of the stack
int LuaSettings::create_object(lua_State* L)
{
NO_MAP_LOCK_REQUIRED;
@@ -209,15 +258,17 @@ LuaSettings* LuaSettings::checkobject(lua_State* L, int narg)
NO_MAP_LOCK_REQUIRED;
luaL_checktype(L, narg, LUA_TUSERDATA);
void *ud = luaL_checkudata(L, narg, className);
- if(!ud) luaL_typerror(L, narg, className);
- return *(LuaSettings**)ud; // unbox pointer
+ if (!ud)
+ luaL_typerror(L, narg, className);
+ return *(LuaSettings**) ud; // unbox pointer
}
const char LuaSettings::className[] = "Settings";
-const luaL_reg LuaSettings::methods[] = {
+const luaL_Reg LuaSettings::methods[] = {
luamethod(LuaSettings, get),
luamethod(LuaSettings, get_bool),
luamethod(LuaSettings, set),
+ luamethod(LuaSettings, set_bool),
luamethod(LuaSettings, remove),
luamethod(LuaSettings, get_names),
luamethod(LuaSettings, write),
diff --git a/src/script/lua_api/l_settings.h b/src/script/lua_api/l_settings.h
index bca333e31..54b003ab3 100644
--- a/src/script/lua_api/l_settings.h
+++ b/src/script/lua_api/l_settings.h
@@ -24,51 +24,58 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class Settings;
-class LuaSettings : public ModApiBase {
+class LuaSettings : public ModApiBase
+{
private:
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
// garbage collector
- static int gc_object(lua_State* L);
+ static int gc_object(lua_State *L);
// get(self, key) -> value
- static int l_get(lua_State* L);
+ static int l_get(lua_State *L);
// get_bool(self, key) -> boolean
- static int l_get_bool(lua_State* L);
+ static int l_get_bool(lua_State *L);
// set(self, key, value)
- static int l_set(lua_State* L);
+ static int l_set(lua_State *L);
+
+ // set_bool(self, key, value)
+ static int l_set_bool(lua_State *L);
// remove(self, key) -> success
- static int l_remove(lua_State* L);
+ static int l_remove(lua_State *L);
// get_names(self) -> {key1, ...}
- static int l_get_names(lua_State* L);
+ static int l_get_names(lua_State *L);
// write(self) -> success
- static int l_write(lua_State* L);
+ static int l_write(lua_State *L);
// to_table(self) -> {[key1]=value1,...}
- static int l_to_table(lua_State* L);
+ static int l_to_table(lua_State *L);
- bool m_write_allowed;
- Settings* m_settings;
+ Settings *m_settings;
std::string m_filename;
+ bool m_is_own_settings;
+ bool m_write_allowed;
public:
- LuaSettings(const char* filename, bool write_allowed);
+ LuaSettings(Settings *settings, const std::string &filename);
+ LuaSettings(const std::string &filename, bool write_allowed);
~LuaSettings();
- // LuaSettings(filename)
- // Creates an LuaSettings and leaves it on top of stack
- static int create_object(lua_State* L);
+ static void create(lua_State *L, Settings *settings, const std::string &filename);
- static LuaSettings* checkobject(lua_State* L, int narg);
+ // LuaSettings(filename)
+ // Creates a LuaSettings and leaves it on top of the stack
+ static int create_object(lua_State *L);
- static void Register(lua_State* L);
+ static LuaSettings *checkobject(lua_State *L, int narg);
+ static void Register(lua_State *L);
};
#endif
diff --git a/src/script/lua_api/l_sound.cpp b/src/script/lua_api/l_sound.cpp
new file mode 100644
index 000000000..07ce36daa
--- /dev/null
+++ b/src/script/lua_api/l_sound.cpp
@@ -0,0 +1,53 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "l_sound.h"
+#include "l_internal.h"
+#include "common/c_content.h"
+#include "guiEngine.h"
+
+
+int ModApiSound::l_sound_play(lua_State *L)
+{
+ SimpleSoundSpec spec;
+ read_soundspec(L, 1, spec);
+ bool looped = lua_toboolean(L, 2);
+
+ s32 handle = getGuiEngine(L)->playSound(spec, looped);
+
+ lua_pushinteger(L, handle);
+
+ return 1;
+}
+
+int ModApiSound::l_sound_stop(lua_State *L)
+{
+ u32 handle = luaL_checkinteger(L, 1);
+
+ getGuiEngine(L)->stopSound(handle);
+
+ return 1;
+}
+
+void ModApiSound::Initialize(lua_State *L, int top)
+{
+ API_FCT(sound_play);
+ API_FCT(sound_stop);
+}
diff --git a/src/script/lua_api/l_sound.h b/src/script/lua_api/l_sound.h
new file mode 100644
index 000000000..1f0c1eba1
--- /dev/null
+++ b/src/script/lua_api/l_sound.h
@@ -0,0 +1,36 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef L_SOUND_H_
+#define L_SOUND_H_
+
+#include "lua_api/l_base.h"
+
+class ModApiSound : public ModApiBase
+{
+private:
+ static int l_sound_play(lua_State *L);
+ static int l_sound_stop(lua_State *L);
+
+public:
+ static void Initialize(lua_State *L, int top);
+};
+
+#endif
diff --git a/src/script/lua_api/l_storage.cpp b/src/script/lua_api/l_storage.cpp
new file mode 100644
index 000000000..4c6b2a182
--- /dev/null
+++ b/src/script/lua_api/l_storage.cpp
@@ -0,0 +1,147 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "lua_api/l_storage.h"
+#include "l_internal.h"
+#include "mods.h"
+#include "server.h"
+
+int ModApiStorage::l_get_mod_storage(lua_State *L)
+{
+ lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
+ if (!lua_isstring(L, -1)) {
+ return 0;
+ }
+
+ std::string mod_name = lua_tostring(L, -1);
+
+ ModMetadata *store = new ModMetadata(mod_name);
+ if (IGameDef *gamedef = getGameDef(L)) {
+ store->load(gamedef->getModStoragePath());
+ gamedef->registerModStorage(store);
+ } else {
+ assert(false); // this should not happen
+ }
+
+ StorageRef::create(L, store);
+ int object = lua_gettop(L);
+
+ lua_pushvalue(L, object);
+ return 1;
+}
+
+void ModApiStorage::Initialize(lua_State *L, int top)
+{
+ API_FCT(get_mod_storage);
+}
+
+StorageRef::StorageRef(ModMetadata *object):
+ m_object(object)
+{
+}
+
+void StorageRef::create(lua_State *L, ModMetadata *object)
+{
+ StorageRef *o = new StorageRef(object);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+}
+
+int StorageRef::gc_object(lua_State *L)
+{
+ StorageRef *o = *(StorageRef **)(lua_touserdata(L, 1));
+ // Server side
+ if (IGameDef *gamedef = getGameDef(L))
+ gamedef->unregisterModStorage(getobject(o)->getModName());
+ delete o;
+ return 0;
+}
+
+void StorageRef::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+
+ lua_pushliteral(L, "metadata_class");
+ lua_pushlstring(L, className, strlen(className));
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__eq");
+ lua_pushcfunction(L, l_equals);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+}
+
+StorageRef* StorageRef::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 *(StorageRef**)ud; // unbox pointer
+}
+
+ModMetadata* StorageRef::getobject(StorageRef *ref)
+{
+ ModMetadata *co = ref->m_object;
+ return co;
+}
+
+Metadata* StorageRef::getmeta(bool auto_create)
+{
+ return m_object;
+}
+
+void StorageRef::clearMeta()
+{
+ m_object->clear();
+}
+
+const char StorageRef::className[] = "StorageRef";
+const luaL_Reg StorageRef::methods[] = {
+ luamethod(MetaDataRef, get_string),
+ luamethod(MetaDataRef, set_string),
+ luamethod(MetaDataRef, get_int),
+ luamethod(MetaDataRef, set_int),
+ luamethod(MetaDataRef, get_float),
+ luamethod(MetaDataRef, set_float),
+ luamethod(MetaDataRef, to_table),
+ luamethod(MetaDataRef, from_table),
+ luamethod(MetaDataRef, equals),
+ {0,0}
+};
diff --git a/src/script/lua_api/l_storage.h b/src/script/lua_api/l_storage.h
new file mode 100644
index 000000000..ec6f8d941
--- /dev/null
+++ b/src/script/lua_api/l_storage.h
@@ -0,0 +1,63 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __L_STORAGE_H__
+#define __L_STORAGE_H__
+
+#include "l_metadata.h"
+#include "lua_api/l_base.h"
+
+class ModMetadata;
+
+class ModApiStorage : public ModApiBase
+{
+protected:
+ static int l_get_mod_storage(lua_State *L);
+
+public:
+ static void Initialize(lua_State *L, int top);
+};
+
+class StorageRef : public MetaDataRef
+{
+private:
+ ModMetadata *m_object;
+
+ static const char className[];
+ static const luaL_Reg methods[];
+
+ virtual Metadata *getmeta(bool auto_create);
+ virtual void clearMeta();
+
+ // garbage collector
+ static int gc_object(lua_State *L);
+
+public:
+ StorageRef(ModMetadata *object);
+ ~StorageRef() {}
+
+ static void Register(lua_State *L);
+ static void create(lua_State *L, ModMetadata *object);
+
+ static StorageRef *checkobject(lua_State *L, int narg);
+ static ModMetadata *getobject(StorageRef *ref);
+};
+
+#endif /* __L_STORAGE_H__ */
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index 26e2b985c..c4a988e07 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_util.h"
#include "lua_api/l_internal.h"
+#include "lua_api/l_settings.h"
#include "common/c_converter.h"
#include "common/c_content.h"
#include "cpp_api/s_async.h"
@@ -77,71 +78,6 @@ int ModApiUtil::l_get_us_time(lua_State *L)
return 1;
}
-#define CHECK_SECURE_SETTING(L, name) \
- if (ScriptApiSecurity::isSecure(L) && \
- name.compare(0, 7, "secure.") == 0) { \
- throw LuaError("Attempt to set secure setting."); \
- }
-
-// setting_set(name, value)
-int ModApiUtil::l_setting_set(lua_State *L)
-{
- NO_MAP_LOCK_REQUIRED;
- std::string name = luaL_checkstring(L, 1);
- std::string value = luaL_checkstring(L, 2);
- CHECK_SECURE_SETTING(L, name);
- g_settings->set(name, value);
- return 0;
-}
-
-// setting_get(name)
-int ModApiUtil::l_setting_get(lua_State *L)
-{
- NO_MAP_LOCK_REQUIRED;
- const char *name = luaL_checkstring(L, 1);
- try{
- std::string value = g_settings->get(name);
- lua_pushstring(L, value.c_str());
- } catch(SettingNotFoundException &e){
- lua_pushnil(L);
- }
- return 1;
-}
-
-// setting_setbool(name)
-int ModApiUtil::l_setting_setbool(lua_State *L)
-{
- NO_MAP_LOCK_REQUIRED;
- std::string name = luaL_checkstring(L, 1);
- bool value = lua_toboolean(L, 2);
- CHECK_SECURE_SETTING(L, name);
- g_settings->setBool(name, value);
- return 0;
-}
-
-// setting_getbool(name)
-int ModApiUtil::l_setting_getbool(lua_State *L)
-{
- NO_MAP_LOCK_REQUIRED;
- const char *name = luaL_checkstring(L, 1);
- try{
- bool value = g_settings->getBool(name);
- lua_pushboolean(L, value);
- } catch(SettingNotFoundException &e){
- lua_pushnil(L);
- }
- return 1;
-}
-
-// setting_save()
-int ModApiUtil::l_setting_save(lua_State *L)
-{
- NO_MAP_LOCK_REQUIRED;
- if(g_settings_path != "")
- g_settings->updateConfigFile(g_settings_path.c_str());
- return 0;
-}
-
// parse_json(str[, nullvalue])
int ModApiUtil::l_parse_json(lua_State *L)
{
@@ -398,7 +334,8 @@ int ModApiUtil::l_get_dir_list(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const char *path = luaL_checkstring(L, 1);
- short is_dir = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : -1;
+ bool list_all = !lua_isboolean(L, 2); // if its not a boolean list all
+ bool list_dirs = lua_toboolean(L, 2); // true: list dirs, false: list files
CHECK_SECURE_PATH(L, path, false);
@@ -408,7 +345,7 @@ int ModApiUtil::l_get_dir_list(lua_State *L)
lua_newtable(L);
for (size_t i = 0; i < list.size(); i++) {
- if (is_dir == -1 || is_dir == list[i].dir) {
+ if (list_all || list_dirs == list[i].dir) {
lua_pushstring(L, list[i].name.c_str());
lua_rawseti(L, -2, ++index);
}
@@ -492,12 +429,6 @@ void ModApiUtil::Initialize(lua_State *L, int top)
API_FCT(get_us_time);
- API_FCT(setting_set);
- API_FCT(setting_get);
- API_FCT(setting_setbool);
- API_FCT(setting_getbool);
- API_FCT(setting_save);
-
API_FCT(parse_json);
API_FCT(write_json);
@@ -523,36 +454,58 @@ void ModApiUtil::Initialize(lua_State *L, int top)
API_FCT(decode_base64);
API_FCT(get_version);
+
+ LuaSettings::create(L, g_settings, g_settings_path);
+ lua_setfield(L, top, "settings");
}
-void ModApiUtil::InitializeAsync(AsyncEngine& engine)
+void ModApiUtil::InitializeClient(lua_State *L, int top)
{
- ASYNC_API_FCT(log);
+ API_FCT(log);
+
+ API_FCT(get_us_time);
+
+ API_FCT(parse_json);
+ API_FCT(write_json);
+
+ API_FCT(is_yes);
+
+ API_FCT(get_builtin_path);
+
+ API_FCT(compress);
+ API_FCT(decompress);
+
+ API_FCT(encode_base64);
+ API_FCT(decode_base64);
+
+ API_FCT(get_version);
+}
- ASYNC_API_FCT(get_us_time);
+void ModApiUtil::InitializeAsync(lua_State *L, int top)
+{
+ API_FCT(log);
- //ASYNC_API_FCT(setting_set);
- ASYNC_API_FCT(setting_get);
- //ASYNC_API_FCT(setting_setbool);
- ASYNC_API_FCT(setting_getbool);
- //ASYNC_API_FCT(setting_save);
+ API_FCT(get_us_time);
- ASYNC_API_FCT(parse_json);
- ASYNC_API_FCT(write_json);
+ API_FCT(parse_json);
+ API_FCT(write_json);
- ASYNC_API_FCT(is_yes);
+ API_FCT(is_yes);
- ASYNC_API_FCT(get_builtin_path);
+ API_FCT(get_builtin_path);
- ASYNC_API_FCT(compress);
- ASYNC_API_FCT(decompress);
+ API_FCT(compress);
+ API_FCT(decompress);
+
+ API_FCT(mkdir);
+ API_FCT(get_dir_list);
- ASYNC_API_FCT(mkdir);
- ASYNC_API_FCT(get_dir_list);
+ API_FCT(encode_base64);
+ API_FCT(decode_base64);
- ASYNC_API_FCT(encode_base64);
- ASYNC_API_FCT(decode_base64);
+ API_FCT(get_version);
- ASYNC_API_FCT(get_version);
+ LuaSettings::create(L, g_settings, g_settings_path);
+ lua_setfield(L, top, "settings");
}
diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h
index 9910704b3..b75d9db29 100644
--- a/src/script/lua_api/l_util.h
+++ b/src/script/lua_api/l_util.h
@@ -24,7 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class AsyncEngine;
-class ModApiUtil : public ModApiBase {
+class ModApiUtil : public ModApiBase
+{
private:
/*
NOTE:
@@ -44,21 +45,6 @@ private:
// get us precision time
static int l_get_us_time(lua_State *L);
- // setting_set(name, value)
- static int l_setting_set(lua_State *L);
-
- // setting_get(name)
- static int l_setting_get(lua_State *L);
-
- // setting_setbool(name, value)
- static int l_setting_setbool(lua_State *L);
-
- // setting_getbool(name)
- static int l_setting_getbool(lua_State *L);
-
- // setting_save()
- static int l_setting_save(lua_State *L);
-
// parse_json(str[, nullvalue])
static int l_parse_json(lua_State *L);
@@ -109,10 +95,10 @@ private:
public:
static void Initialize(lua_State *L, int top);
+ static void InitializeAsync(lua_State *L, int top);
+ static void InitializeClient(lua_State *L, int top);
- static void InitializeAsync(AsyncEngine& engine);
-
+ static void InitializeAsync(AsyncEngine &engine);
};
#endif /* L_UTIL_H_ */
-
diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp
index bdf720f0a..254a7e5a6 100644
--- a/src/script/lua_api/l_vmanip.cpp
+++ b/src/script/lua_api/l_vmanip.cpp
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "map.h"
#include "server.h"
#include "mapgen.h"
+#include "voxelalgorithms.h"
// garbage collector
int LuaVoxelManip::gc_object(lua_State *L)
@@ -109,10 +110,25 @@ int LuaVoxelManip::l_write_to_map(lua_State *L)
MAP_LOCK_REQUIRED;
LuaVoxelManip *o = checkobject(L, 1);
- MMVManip *vm = o->vm;
+ bool update_light = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : true;
+ GET_ENV_PTR;
+ ServerMap *map = &(env->getServerMap());
+ if (o->is_mapgen_vm || !update_light) {
+ o->vm->blitBackAll(&(o->modified_blocks));
+ } else {
+ voxalgo::blit_back_with_light(map, o->vm,
+ &(o->modified_blocks));
+ }
- vm->blitBackAll(&o->modified_blocks);
+ MapEditEvent event;
+ event.type = MEET_OTHER;
+ for (std::map<v3s16, MapBlock *>::iterator it = o->modified_blocks.begin();
+ it != o->modified_blocks.end(); ++it)
+ event.modified_blocks.insert(it->first);
+ map->dispatchEvent(&event);
+
+ o->modified_blocks.clear();
return 0;
}
@@ -322,33 +338,6 @@ int LuaVoxelManip::l_set_param2_data(lua_State *L)
int LuaVoxelManip::l_update_map(lua_State *L)
{
- GET_ENV_PTR;
-
- LuaVoxelManip *o = checkobject(L, 1);
- if (o->is_mapgen_vm)
- return 0;
-
- Map *map = &(env->getMap());
-
- // TODO: Optimize this by using Mapgen::calcLighting() instead
- std::map<v3s16, MapBlock *> lighting_mblocks;
- std::map<v3s16, MapBlock *> *mblocks = &o->modified_blocks;
-
- lighting_mblocks.insert(mblocks->begin(), mblocks->end());
-
- map->updateLighting(lighting_mblocks, *mblocks);
-
- MapEditEvent event;
- event.type = MEET_OTHER;
- for (std::map<v3s16, MapBlock *>::iterator
- it = mblocks->begin();
- it != mblocks->end(); ++it)
- event.modified_blocks.insert(it->first);
-
- map->dispatchEvent(&event);
-
- mblocks->clear();
-
return 0;
}
@@ -464,7 +453,7 @@ void LuaVoxelManip::Register(lua_State *L)
}
const char LuaVoxelManip::className[] = "VoxelManip";
-const luaL_reg LuaVoxelManip::methods[] = {
+const luaL_Reg LuaVoxelManip::methods[] = {
luamethod(LuaVoxelManip, read_from_map),
luamethod(LuaVoxelManip, get_data),
luamethod(LuaVoxelManip, set_data),
diff --git a/src/script/lua_api/l_vmanip.h b/src/script/lua_api/l_vmanip.h
index 1adb78c4e..b6a69f36a 100644
--- a/src/script/lua_api/l_vmanip.h
+++ b/src/script/lua_api/l_vmanip.h
@@ -20,9 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef L_VMANIP_H_
#define L_VMANIP_H_
-#include "lua_api/l_base.h"
-#include "irr_v3d.h"
#include <map>
+#include "irr_v3d.h"
+#include "lua_api/l_base.h"
class Map;
class MapBlock;
@@ -31,13 +31,14 @@ class MMVManip;
/*
VoxelManip
*/
-class LuaVoxelManip : public ModApiBase {
+class LuaVoxelManip : public ModApiBase
+{
private:
std::map<v3s16, MapBlock *> modified_blocks;
bool is_mapgen_vm;
static const char className[];
- static const luaL_reg methods[];
+ static const luaL_Reg methods[];
static int gc_object(lua_State *L);
diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp
new file mode 100644
index 000000000..da289e564
--- /dev/null
+++ b/src/script/scripting_client.cpp
@@ -0,0 +1,88 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "scripting_client.h"
+#include "client.h"
+#include "cpp_api/s_internal.h"
+#include "lua_api/l_client.h"
+#include "lua_api/l_env.h"
+#include "lua_api/l_minimap.h"
+#include "lua_api/l_storage.h"
+#include "lua_api/l_sound.h"
+#include "lua_api/l_util.h"
+#include "lua_api/l_item.h"
+#include "lua_api/l_nodemeta.h"
+#include "lua_api/l_localplayer.h"
+#include "lua_api/l_camera.h"
+
+ClientScripting::ClientScripting(Client *client):
+ ScriptApiBase()
+{
+ setGameDef(client);
+
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Security is mandatory client side
+ initializeSecurityClient();
+
+ lua_getglobal(L, "core");
+ int top = lua_gettop(L);
+
+ lua_newtable(L);
+ lua_setfield(L, -2, "ui");
+
+ 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");
+
+ infostream << "SCRIPTAPI: Initialized client game modules" << std::endl;
+}
+
+void ClientScripting::InitializeModApi(lua_State *L, int top)
+{
+ LuaItemStack::Register(L);
+ StorageRef::Register(L);
+ LuaMinimap::Register(L);
+ NodeMetaRef::RegisterClient(L);
+ LuaLocalPlayer::Register(L);
+ LuaCamera::Register(L);
+
+ ModApiUtil::InitializeClient(L, top);
+ ModApiClient::Initialize(L, top);
+ ModApiStorage::Initialize(L, top);
+ ModApiEnvMod::InitializeClient(L, top);
+}
+
+void ClientScripting::on_client_ready(LocalPlayer *localplayer)
+{
+ lua_State *L = getStack();
+ LuaLocalPlayer::create(L, localplayer);
+}
+
+void ClientScripting::on_camera_ready(Camera *camera)
+{
+ LuaCamera::create(getStack(), camera);
+}
diff --git a/src/script/scripting_client.h b/src/script/scripting_client.h
new file mode 100644
index 000000000..c13fde607
--- /dev/null
+++ b/src/script/scripting_client.h
@@ -0,0 +1,46 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef CLIENT_SCRIPTING_H_
+#define CLIENT_SCRIPTING_H_
+
+#include "cpp_api/s_base.h"
+#include "cpp_api/s_client.h"
+#include "cpp_api/s_security.h"
+#include "util/basic_macros.h"
+
+class Client;
+class LocalPlayer;
+class Camera;
+class ClientScripting:
+ virtual public ScriptApiBase,
+ public ScriptApiSecurity,
+ public ScriptApiClient
+{
+public:
+ ClientScripting(Client *client);
+ void on_client_ready(LocalPlayer *localplayer);
+ void on_camera_ready(Camera *camera);
+
+private:
+ virtual void InitializeModApi(lua_State *L, int top);
+ DISABLE_CLASS_COPY(ClientScripting);
+};
+#endif
diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp
index b1e50c94b..48957b472 100644
--- a/src/script/scripting_mainmenu.cpp
+++ b/src/script/scripting_mainmenu.cpp
@@ -19,11 +19,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "scripting_mainmenu.h"
#include "mods.h"
-#include "porting.h"
-#include "log.h"
#include "cpp_api/s_internal.h"
#include "lua_api/l_base.h"
#include "lua_api/l_mainmenu.h"
+#include "lua_api/l_sound.h"
#include "lua_api/l_util.h"
#include "lua_api/l_settings.h"
@@ -60,16 +59,16 @@ MainMenuScripting::MainMenuScripting(GUIEngine* guiengine)
/******************************************************************************/
void MainMenuScripting::initializeModApi(lua_State *L, int top)
{
+ registerLuaClasses(L, top);
+
// Initialize mod API modules
ModApiMainMenu::Initialize(L, top);
ModApiUtil::Initialize(L, top);
+ ModApiSound::Initialize(L, top);
- // Register reference classes (userdata)
- LuaSettings::Register(L);
-
- // Register functions to async environment
- ModApiMainMenu::InitializeAsync(asyncEngine);
- ModApiUtil::InitializeAsync(asyncEngine);
+ asyncEngine.registerStateInitializer(registerLuaClasses);
+ asyncEngine.registerStateInitializer(ModApiMainMenu::InitializeAsync);
+ asyncEngine.registerStateInitializer(ModApiUtil::InitializeAsync);
// Initialize async environment
//TODO possibly make number of async threads configurable
@@ -77,13 +76,21 @@ void MainMenuScripting::initializeModApi(lua_State *L, int top)
}
/******************************************************************************/
-void MainMenuScripting::step() {
+void MainMenuScripting::registerLuaClasses(lua_State *L, int top)
+{
+ LuaSettings::Register(L);
+}
+
+/******************************************************************************/
+void MainMenuScripting::step()
+{
asyncEngine.step(getStack());
}
/******************************************************************************/
-unsigned int MainMenuScripting::queueAsync(std::string serialized_func,
- std::string serialized_param) {
+unsigned int MainMenuScripting::queueAsync(const std::string &serialized_func,
+ const std::string &serialized_param)
+{
return asyncEngine.queueAsyncJob(serialized_func, serialized_param);
}
diff --git a/src/script/scripting_mainmenu.h b/src/script/scripting_mainmenu.h
index 3a0795df4..7b3a6eba8 100644
--- a/src/script/scripting_mainmenu.h
+++ b/src/script/scripting_mainmenu.h
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_base.h"
#include "cpp_api/s_mainmenu.h"
#include "cpp_api/s_async.h"
+#include "util/basic_macros.h"
/*****************************************************************************/
/* Scripting <-> Main Menu Interface */
@@ -39,12 +40,14 @@ public:
void step();
// Pass async events from engine to async threads
- unsigned int queueAsync(std::string serialized_func,
- std::string serialized_params);
+ unsigned int queueAsync(const std::string &serialized_func,
+ const std::string &serialized_params);
private:
void initializeModApi(lua_State *L, int top);
+ static void registerLuaClasses(lua_State *L, int top);
AsyncEngine asyncEngine;
+ DISABLE_CLASS_COPY(MainMenuScripting);
};
diff --git a/src/script/scripting_game.cpp b/src/script/scripting_server.cpp
index e313d55f8..cd01b0773 100644
--- a/src/script/scripting_game.cpp
+++ b/src/script/scripting_server.cpp
@@ -17,7 +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 "scripting_game.h"
+#include "scripting_server.h"
#include "server.h"
#include "log.h"
#include "settings.h"
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_env.h"
#include "lua_api/l_inventory.h"
#include "lua_api/l_item.h"
+#include "lua_api/l_itemstackmeta.h"
#include "lua_api/l_mapgen.h"
#include "lua_api/l_nodemeta.h"
#include "lua_api/l_nodetimer.h"
@@ -40,14 +41,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_vmanip.h"
#include "lua_api/l_settings.h"
#include "lua_api/l_http.h"
+#include "lua_api/l_storage.h"
extern "C" {
#include "lualib.h"
}
-GameScripting::GameScripting(Server* server)
+ServerScripting::ServerScripting(Server* server)
{
- setServer(server);
+ setGameDef(server);
// setEnv(env) is called by ScriptApiEnv::initializeEnvironment()
// once the environment has been created
@@ -78,22 +80,11 @@ GameScripting::GameScripting(Server* server)
infostream << "SCRIPTAPI: Initialized game modules" << std::endl;
}
-void GameScripting::InitializeModApi(lua_State *L, int top)
+void ServerScripting::InitializeModApi(lua_State *L, int top)
{
- // Initialize mod api modules
- ModApiCraft::Initialize(L, top);
- ModApiEnvMod::Initialize(L, top);
- ModApiInventory::Initialize(L, top);
- ModApiItemMod::Initialize(L, top);
- ModApiMapgen::Initialize(L, top);
- ModApiParticles::Initialize(L, top);
- ModApiRollback::Initialize(L, top);
- ModApiServer::Initialize(L, top);
- ModApiUtil::Initialize(L, top);
- ModApiHttp::Initialize(L, top);
-
// Register reference classes (userdata)
InvRef::Register(L);
+ ItemStackMetaRef::Register(L);
LuaAreaStore::Register(L);
LuaItemStack::Register(L);
LuaPerlinNoise::Register(L);
@@ -106,6 +97,20 @@ void GameScripting::InitializeModApi(lua_State *L, int top)
NodeTimerRef::Register(L);
ObjectRef::Register(L);
LuaSettings::Register(L);
+ StorageRef::Register(L);
+
+ // Initialize mod api modules
+ ModApiCraft::Initialize(L, top);
+ ModApiEnvMod::Initialize(L, top);
+ ModApiInventory::Initialize(L, top);
+ ModApiItemMod::Initialize(L, top);
+ ModApiMapgen::Initialize(L, top);
+ ModApiParticles::Initialize(L, top);
+ ModApiRollback::Initialize(L, top);
+ ModApiServer::Initialize(L, top);
+ ModApiUtil::Initialize(L, top);
+ ModApiHttp::Initialize(L, top);
+ ModApiStorage::Initialize(L, top);
}
void log_deprecated(const std::string &message)
diff --git a/src/script/scripting_game.h b/src/script/scripting_server.h
index 970b3e80d..1b335406e 100644
--- a/src/script/scripting_game.h
+++ b/src/script/scripting_server.h
@@ -17,8 +17,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef SCRIPTING_GAME_H_
-#define SCRIPTING_GAME_H_
+#ifndef SERVER_SCRIPTING_H_
+#define SERVER_SCRIPTING_H_
#include "cpp_api/s_base.h"
#include "cpp_api/s_entity.h"
@@ -28,12 +28,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_player.h"
#include "cpp_api/s_server.h"
#include "cpp_api/s_security.h"
+#include "util/basic_macros.h"
/*****************************************************************************/
-/* Scripting <-> Game Interface */
+/* Scripting <-> Server Game Interface */
/*****************************************************************************/
-class GameScripting :
+class ServerScripting:
virtual public ScriptApiBase,
public ScriptApiDetached,
public ScriptApiEntity,
@@ -44,12 +45,13 @@ class GameScripting :
public ScriptApiSecurity
{
public:
- GameScripting(Server* server);
+ ServerScripting(Server* server);
// use ScriptApiBase::loadMod() to load mods
private:
void InitializeModApi(lua_State *L, int top);
+ DISABLE_CLASS_COPY(ServerScripting);
};
void log_deprecated(const std::string &message);