aboutsummaryrefslogtreecommitdiff
path: root/src/script/lua_api
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/lua_api')
-rw-r--r--src/script/lua_api/l_areastore.cpp1
-rw-r--r--src/script/lua_api/l_camera.cpp21
-rw-r--r--src/script/lua_api/l_client.cpp16
-rw-r--r--src/script/lua_api/l_craft.cpp10
-rw-r--r--src/script/lua_api/l_env.cpp32
-rw-r--r--src/script/lua_api/l_http.cpp15
-rw-r--r--src/script/lua_api/l_item.cpp11
-rw-r--r--src/script/lua_api/l_item.h3
-rw-r--r--src/script/lua_api/l_localplayer.cpp22
-rw-r--r--src/script/lua_api/l_mainmenu.cpp28
-rw-r--r--src/script/lua_api/l_mainmenu.h4
-rw-r--r--src/script/lua_api/l_mapgen.cpp89
-rw-r--r--src/script/lua_api/l_mapgen.h3
-rw-r--r--src/script/lua_api/l_nodemeta.cpp2
-rw-r--r--src/script/lua_api/l_object.cpp125
-rw-r--r--src/script/lua_api/l_object.h11
-rw-r--r--src/script/lua_api/l_server.cpp4
-rw-r--r--src/script/lua_api/l_vmanip.cpp2
18 files changed, 321 insertions, 78 deletions
diff --git a/src/script/lua_api/l_areastore.cpp b/src/script/lua_api/l_areastore.cpp
index d53d74aa8..908c766b0 100644
--- a/src/script/lua_api/l_areastore.cpp
+++ b/src/script/lua_api/l_areastore.cpp
@@ -185,6 +185,7 @@ int LuaAreaStore::l_insert_area(lua_State *L)
if (lua_isnumber(L, 5))
a.id = lua_tonumber(L, 5);
+ // Insert & assign a new ID if necessary
if (!ast->insertArea(&a))
return 0;
diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp
index 462006777..80071b3b8 100644
--- a/src/script/lua_api/l_camera.cpp
+++ b/src/script/lua_api/l_camera.cpp
@@ -31,19 +31,24 @@ LuaCamera::LuaCamera(Camera *m) : m_camera(m)
void LuaCamera::create(lua_State *L, Camera *m)
{
+ lua_getglobal(L, "core");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int objectstable = lua_gettop(L);
+ lua_getfield(L, -1, "camera");
+
+ // Duplication check
+ if (lua_type(L, -1) == LUA_TUSERDATA) {
+ lua_pop(L, 1);
+ return;
+ }
+
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");
+ lua_pushvalue(L, lua_gettop(L));
+ lua_setfield(L, objectstable, "camera");
}
int LuaCamera::l_set_camera_mode(lua_State *L)
diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp
index 6d9d832b7..6345fc75f 100644
--- a/src/script/lua_api/l_client.cpp
+++ b/src/script/lua_api/l_client.cpp
@@ -210,17 +210,13 @@ int ModApiClient::l_get_language(lua_State *L)
int ModApiClient::l_get_wielded_item(lua_State *L)
{
Client *client = getClient(L);
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ if (!player)
+ return 0;
- 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());
- }
+ ItemStack selected_item;
+ player->getWieldedItem(&selected_item, nullptr);
+ LuaItemStack::create(L, selected_item);
return 1;
}
diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp
index 0899b945e..18622ee00 100644
--- a/src/script/lua_api/l_craft.cpp
+++ b/src/script/lua_api/l_craft.cpp
@@ -294,7 +294,7 @@ int ModApiCraft::l_clear_craft(lua_State *L)
std::string type = getstringfield_default(L, table, "type", "shaped");
CraftOutput c_output(output, 0);
if (!output.empty()) {
- if (craftdef->clearCraftRecipesByOutput(c_output, getServer(L))) {
+ if (craftdef->clearCraftsByOutput(c_output, getServer(L))) {
lua_pushboolean(L, true);
return 1;
}
@@ -351,7 +351,13 @@ int ModApiCraft::l_clear_craft(lua_State *L)
throw LuaError("Unknown crafting definition type: \"" + type + "\"");
}
- if (!craftdef->clearCraftRecipesByInput(method, width, recipe, getServer(L))) {
+ std::vector<ItemStack> items;
+ items.reserve(recipe.size());
+ for (const auto &item : recipe)
+ items.emplace_back(item, 1, 0, getServer(L)->idef());
+ CraftInput input(method, width, items);
+
+ if (!craftdef->clearCraftsByInput(input, getServer(L))) {
warningstream << "No craft recipe matches input" << std::endl;
lua_pushboolean(L, false);
return 1;
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index 711bd3fdd..a56b1cb0b 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -350,7 +350,7 @@ int ModApiEnvMod::l_get_node(lua_State *L)
// pos
v3s16 pos = read_v3s16(L, 1);
// Do it
- MapNode n = env->getMap().getNodeNoEx(pos);
+ MapNode n = env->getMap().getNode(pos);
// Return node
pushnode(L, n, env->getGameDef()->ndef());
return 1;
@@ -366,7 +366,7 @@ int ModApiEnvMod::l_get_node_or_nil(lua_State *L)
v3s16 pos = read_v3s16(L, 1);
// Do it
bool pos_ok;
- MapNode n = env->getMap().getNodeNoEx(pos, &pos_ok);
+ MapNode n = env->getMap().getNode(pos, &pos_ok);
if (pos_ok) {
// Return node
pushnode(L, n, env->getGameDef()->ndef());
@@ -392,7 +392,7 @@ int ModApiEnvMod::l_get_node_light(lua_State *L)
u32 dnr = time_to_daynight_ratio(time_of_day, true);
bool is_position_ok;
- MapNode n = env->getMap().getNodeNoEx(pos, &is_position_ok);
+ MapNode n = env->getMap().getNode(pos, &is_position_ok);
if (is_position_ok) {
const NodeDefManager *ndef = env->getGameDef()->ndef();
lua_pushinteger(L, n.getLightBlend(dnr, ndef));
@@ -417,7 +417,7 @@ int ModApiEnvMod::l_place_node(lua_State *L)
MapNode n = readnode(L, 2, ndef);
// Don't attempt to load non-loaded area as of now
- MapNode n_old = env->getMap().getNodeNoEx(pos);
+ MapNode n_old = env->getMap().getNode(pos);
if(n_old.getContent() == CONTENT_IGNORE){
lua_pushboolean(L, false);
return 1;
@@ -446,7 +446,7 @@ int ModApiEnvMod::l_dig_node(lua_State *L)
v3s16 pos = read_v3s16(L, 1);
// Don't attempt to load non-loaded area as of now
- MapNode n = env->getMap().getNodeNoEx(pos);
+ MapNode n = env->getMap().getNode(pos);
if(n.getContent() == CONTENT_IGNORE){
lua_pushboolean(L, false);
return 1;
@@ -469,7 +469,7 @@ int ModApiEnvMod::l_punch_node(lua_State *L)
v3s16 pos = read_v3s16(L, 1);
// Don't attempt to load non-loaded area as of now
- MapNode n = env->getMap().getNodeNoEx(pos);
+ MapNode n = env->getMap().getNode(pos);
if(n.getContent() == CONTENT_IGNORE){
lua_pushboolean(L, false);
return 1;
@@ -491,7 +491,7 @@ int ModApiEnvMod::l_get_node_max_level(lua_State *L)
}
v3s16 pos = read_v3s16(L, 1);
- MapNode n = env->getMap().getNodeNoEx(pos);
+ MapNode n = env->getMap().getNode(pos);
lua_pushnumber(L, n.getMaxLevel(env->getGameDef()->ndef()));
return 1;
}
@@ -506,7 +506,7 @@ int ModApiEnvMod::l_get_node_level(lua_State *L)
}
v3s16 pos = read_v3s16(L, 1);
- MapNode n = env->getMap().getNodeNoEx(pos);
+ MapNode n = env->getMap().getNode(pos);
lua_pushnumber(L, n.getLevel(env->getGameDef()->ndef()));
return 1;
}
@@ -522,7 +522,7 @@ int ModApiEnvMod::l_set_node_level(lua_State *L)
u8 level = 1;
if(lua_isnumber(L, 2))
level = lua_tonumber(L, 2);
- MapNode n = env->getMap().getNodeNoEx(pos);
+ MapNode n = env->getMap().getNode(pos);
lua_pushnumber(L, n.setLevel(env->getGameDef()->ndef(), level));
env->setNode(pos, n);
return 1;
@@ -539,7 +539,7 @@ int ModApiEnvMod::l_add_node_level(lua_State *L)
u8 level = 1;
if(lua_isnumber(L, 2))
level = lua_tonumber(L, 2);
- MapNode n = env->getMap().getNodeNoEx(pos);
+ MapNode n = env->getMap().getNode(pos);
lua_pushnumber(L, n.addLevel(env->getGameDef()->ndef(), level));
env->setNode(pos, n);
return 1;
@@ -780,7 +780,7 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
for (const v3s16 &i : list) {
v3s16 p = pos + i;
- content_t c = env->getMap().getNodeNoEx(p).getContent();
+ content_t c = env->getMap().getNode(p).getContent();
if (CONTAINS(filter, c)) {
push_v3s16(L, p);
return 1;
@@ -832,7 +832,7 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
for (s16 y = minp.Y; y <= maxp.Y; y++)
for (s16 z = minp.Z; z <= maxp.Z; z++) {
v3s16 p(x, y, z);
- content_t c = env->getMap().getNodeNoEx(p).getContent();
+ content_t c = env->getMap().getNode(p).getContent();
std::vector<content_t>::iterator it = std::find(filter.begin(), filter.end(), c);
if (it != filter.end()) {
@@ -898,10 +898,10 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
for (s16 z = minp.Z; z <= maxp.Z; z++) {
s16 y = minp.Y;
v3s16 p(x, y, z);
- content_t c = env->getMap().getNodeNoEx(p).getContent();
+ content_t c = env->getMap().getNode(p).getContent();
for (; y <= maxp.Y; y++) {
v3s16 psurf(x, y + 1, z);
- content_t csurf = env->getMap().getNodeNoEx(psurf).getContent();
+ content_t csurf = env->getMap().getNode(psurf).getContent();
if (c != CONTENT_AIR && csurf == CONTENT_AIR &&
CONTAINS(filter, c)) {
push_v3s16(L, v3s16(x, y, z));
@@ -1035,7 +1035,7 @@ int ModApiEnvMod::l_fix_light(lua_State *L)
for (auto &modified_block : modified_blocks)
event.modified_blocks.insert(modified_block.first);
- map.dispatchEvent(&event);
+ map.dispatchEvent(event);
}
lua_pushboolean(L, success);
@@ -1144,7 +1144,7 @@ int ModApiEnvMod::l_delete_area(lua_State *L)
}
}
- map.dispatchEvent(&event);
+ map.dispatchEvent(event);
lua_pushboolean(L, success);
return 1;
}
diff --git a/src/script/lua_api/l_http.cpp b/src/script/lua_api/l_http.cpp
index ac261cd60..2ff651cb5 100644
--- a/src/script/lua_api/l_http.cpp
+++ b/src/script/lua_api/l_http.cpp
@@ -53,9 +53,8 @@ void ModApiHttp::read_http_fetch_request(lua_State *L, HTTPFetchRequest &req)
lua_getfield(L, 1, "post_data");
if (lua_istable(L, 2)) {
lua_pushnil(L);
- while (lua_next(L, 2) != 0)
- {
- req.post_fields[luaL_checkstring(L, -2)] = luaL_checkstring(L, -1);
+ while (lua_next(L, 2) != 0) {
+ req.post_fields[readParam<std::string>(L, -2)] = readParam<std::string>(L, -1);
lua_pop(L, 1);
}
} else if (lua_isstring(L, 2)) {
@@ -66,10 +65,8 @@ void ModApiHttp::read_http_fetch_request(lua_State *L, HTTPFetchRequest &req)
lua_getfield(L, 1, "extra_headers");
if (lua_istable(L, 2)) {
lua_pushnil(L);
- while (lua_next(L, 2) != 0)
- {
- const char *header = luaL_checkstring(L, -1);
- req.extra_headers.emplace_back(header);
+ while (lua_next(L, 2) != 0) {
+ req.extra_headers.emplace_back(readParam<std::string>(L, -1));
lua_pop(L, 1);
}
}
@@ -83,7 +80,7 @@ void ModApiHttp::push_http_fetch_result(lua_State *L, HTTPFetchResult &res, bool
setboolfield(L, -1, "timeout", res.timeout);
setboolfield(L, -1, "completed", completed);
setintfield(L, -1, "code", res.response_code);
- setstringfield(L, -1, "data", res.data.c_str());
+ setstringfield(L, -1, "data", res.data);
}
// http_api.fetch_async(HTTPRequest definition)
@@ -94,7 +91,7 @@ int ModApiHttp::l_http_fetch_async(lua_State *L)
HTTPFetchRequest req;
read_http_fetch_request(L, req);
- actionstream << "Mod performs HTTP request with URL " << req.url << std::endl;
+ infostream << "Mod performs HTTP request with URL " << req.url << std::endl;
httpfetch_async(req);
// Convert handle to hex string since lua can't handle 64-bit integers
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index e41d23fd1..f9708b560 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -175,6 +175,16 @@ int LuaItemStack::l_set_metadata(lua_State *L)
return 1;
}
+// get_description(self)
+int LuaItemStack::l_get_description(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ LuaItemStack *o = checkobject(L, 1);
+ std::string desc = o->m_stack.getDescription(getGameDef(L)->idef());
+ lua_pushstring(L, desc.c_str());
+ return 1;
+}
+
// clear(self) -> true
int LuaItemStack::l_clear(lua_State *L)
{
@@ -470,6 +480,7 @@ const luaL_Reg LuaItemStack::methods[] = {
luamethod(LuaItemStack, get_meta),
luamethod(LuaItemStack, get_metadata),
luamethod(LuaItemStack, set_metadata),
+ luamethod(LuaItemStack, get_description),
luamethod(LuaItemStack, clear),
luamethod(LuaItemStack, replace),
luamethod(LuaItemStack, to_string),
diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h
index 5ff715b2a..6fab58045 100644
--- a/src/script/lua_api/l_item.h
+++ b/src/script/lua_api/l_item.h
@@ -66,6 +66,9 @@ private:
// set_metadata(self, string)
static int l_set_metadata(lua_State *L);
+ // get_description(self)
+ static int l_get_description(lua_State *L);
+
// clear(self) -> true
static int l_clear(lua_State *L);
diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp
index 7444d0e88..3e14e48e4 100644
--- a/src/script/lua_api/l_localplayer.cpp
+++ b/src/script/lua_api/l_localplayer.cpp
@@ -30,20 +30,24 @@ LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m)
void LuaLocalPlayer::create(lua_State *L, LocalPlayer *m)
{
+ lua_getglobal(L, "core");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int objectstable = lua_gettop(L);
+ lua_getfield(L, -1, "localplayer");
+
+ // Duplication check
+ if (lua_type(L, -1) == LUA_TUSERDATA) {
+ lua_pop(L, 1);
+ return;
+ }
+
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");
+ lua_pushvalue(L, lua_gettop(L));
+ lua_setfield(L, objectstable, "localplayer");
}
int LuaLocalPlayer::l_get_velocity(lua_State *L)
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index 2557f448a..76db7ed13 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -107,6 +107,21 @@ int ModApiMainMenu::l_update_formspec(lua_State *L)
}
/******************************************************************************/
+int ModApiMainMenu::l_set_formspec_prepend(lua_State *L)
+{
+ GUIEngine *engine = getGuiEngine(L);
+ sanity_check(engine != NULL);
+
+ if (engine->m_startgame)
+ return 0;
+
+ std::string formspec(luaL_checkstring(L, 1));
+ engine->setFormspecPrepend(formspec);
+
+ return 0;
+}
+
+/******************************************************************************/
int ModApiMainMenu::l_start(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
@@ -867,6 +882,16 @@ bool ModApiMainMenu::mayModifyPath(const std::string &path)
return false;
}
+
+/******************************************************************************/
+int ModApiMainMenu::l_may_modify_path(lua_State *L)
+{
+ const char *target = luaL_checkstring(L, 1);
+ std::string absolute_destination = fs::RemoveRelativePathComponents(target);
+ lua_pushboolean(L, ModApiMainMenu::mayModifyPath(absolute_destination));
+ return 1;
+}
+
/******************************************************************************/
int ModApiMainMenu::l_show_path_select_dialog(lua_State *L)
{
@@ -1031,6 +1056,7 @@ int ModApiMainMenu::l_do_async_callback(lua_State *L)
void ModApiMainMenu::Initialize(lua_State *L, int top)
{
API_FCT(update_formspec);
+ API_FCT(set_formspec_prepend);
API_FCT(set_clouds);
API_FCT(get_textlist_index);
API_FCT(get_table_index);
@@ -1057,6 +1083,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
API_FCT(delete_dir);
API_FCT(copy_dir);
API_FCT(extract_zip);
+ API_FCT(may_modify_path);
API_FCT(get_mainmenu_path);
API_FCT(show_path_select_dialog);
API_FCT(download_file);
@@ -1086,6 +1113,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top)
API_FCT(delete_dir);
API_FCT(copy_dir);
//API_FCT(extract_zip); //TODO remove dependency to GuiEngine
+ API_FCT(may_modify_path);
API_FCT(download_file);
//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 4a664359a..b2ca49320 100644
--- a/src/script/lua_api/l_mainmenu.h
+++ b/src/script/lua_api/l_mainmenu.h
@@ -104,6 +104,8 @@ private:
static int l_update_formspec(lua_State *L);
+ static int l_set_formspec_prepend(lua_State *L);
+
static int l_get_screen_info(lua_State *L);
//filesystem
@@ -130,6 +132,8 @@ private:
static int l_extract_zip(lua_State *L);
+ static int l_may_modify_path(lua_State *L);
+
static int l_download_file(lua_State *L);
static int l_get_video_drivers(lua_State *L);
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp
index 92ed4377e..2e0cba8dd 100644
--- a/src/script/lua_api/l_mapgen.cpp
+++ b/src/script/lua_api/l_mapgen.cpp
@@ -405,7 +405,16 @@ Biome *read_biome_def(lua_State *L, int index, const NodeDefManager *ndef)
nn.push_back(getstringfield_default(L, index, "node_river_water", ""));
nn.push_back(getstringfield_default(L, index, "node_riverbed", ""));
nn.push_back(getstringfield_default(L, index, "node_dust", ""));
- nn.push_back(getstringfield_default(L, index, "node_cave_liquid", ""));
+
+ size_t nnames = getstringlistfield(L, index, "node_cave_liquid", &nn);
+ // If no cave liquids defined, set list to "ignore" to trigger old hardcoded
+ // cave liquid behaviour.
+ if (nnames == 0) {
+ nn.emplace_back("ignore");
+ nnames = 1;
+ }
+ b->m_nnlistsizes.push_back(nnames);
+
nn.push_back(getstringfield_default(L, index, "node_dungeon", ""));
nn.push_back(getstringfield_default(L, index, "node_dungeon_alt", ""));
nn.push_back(getstringfield_default(L, index, "node_dungeon_stair", ""));
@@ -1745,6 +1754,83 @@ int ModApiMapgen::l_serialize_schematic(lua_State *L)
return 1;
}
+// read_schematic(schematic, options={...})
+int ModApiMapgen::l_read_schematic(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
+
+ //// Read options
+ std::string write_yslice = getstringfield_default(L, 2, "write_yslice_prob", "all");
+
+ //// Get schematic
+ bool was_loaded = false;
+ Schematic *schem = (Schematic *)get_objdef(L, 1, schemmgr);
+ if (!schem) {
+ schem = load_schematic(L, 1, NULL, NULL);
+ was_loaded = true;
+ }
+ if (!schem) {
+ errorstream << "read_schematic: failed to get schematic" << std::endl;
+ return 0;
+ }
+ lua_pop(L, 2);
+
+ //// Create the Lua table
+ u32 numnodes = schem->size.X * schem->size.Y * schem->size.Z;
+ const std::vector<std::string> &names = schem->m_nodenames;
+
+ lua_createtable(L, 0, (write_yslice == "none") ? 2 : 3);
+
+ // Create the size field
+ push_v3s16(L, schem->size);
+ lua_setfield(L, 1, "size");
+
+ // Create the yslice_prob field
+ if (write_yslice != "none") {
+ lua_createtable(L, schem->size.Y, 0);
+ for (u16 y = 0; y != schem->size.Y; ++y) {
+ u8 probability = schem->slice_probs[y] & MTSCHEM_PROB_MASK;
+ if (probability < MTSCHEM_PROB_ALWAYS || write_yslice != "low") {
+ lua_createtable(L, 0, 2);
+ lua_pushinteger(L, y);
+ lua_setfield(L, 3, "ypos");
+ lua_pushinteger(L, probability * 2);
+ lua_setfield(L, 3, "prob");
+ lua_rawseti(L, 2, y + 1);
+ }
+ }
+ lua_setfield(L, 1, "yslice_prob");
+ }
+
+ // Create the data field
+ lua_createtable(L, numnodes, 0); // data table
+ for (u32 i = 0; i < numnodes; ++i) {
+ MapNode node = schem->schemdata[i];
+ u8 probability = node.param1 & MTSCHEM_PROB_MASK;
+ bool force_place = node.param1 & MTSCHEM_FORCE_PLACE;
+ lua_createtable(L, 0, force_place ? 4 : 3);
+ lua_pushstring(L, names[schem->schemdata[i].getContent()].c_str());
+ lua_setfield(L, 3, "name");
+ lua_pushinteger(L, probability * 2);
+ lua_setfield(L, 3, "prob");
+ lua_pushinteger(L, node.param2);
+ lua_setfield(L, 3, "param2");
+ if (force_place) {
+ lua_pushboolean(L, 1);
+ lua_setfield(L, 3, "force_place");
+ }
+ lua_rawseti(L, 2, i + 1);
+ }
+ lua_setfield(L, 1, "data");
+
+ if (was_loaded)
+ delete schem;
+
+ return 1;
+}
+
void ModApiMapgen::Initialize(lua_State *L, int top)
{
@@ -1784,4 +1870,5 @@ void ModApiMapgen::Initialize(lua_State *L, int top)
API_FCT(place_schematic);
API_FCT(place_schematic_on_vmanip);
API_FCT(serialize_schematic);
+ API_FCT(read_schematic);
}
diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h
index 1339791f3..4a6a9ccf4 100644
--- a/src/script/lua_api/l_mapgen.h
+++ b/src/script/lua_api/l_mapgen.h
@@ -131,6 +131,9 @@ private:
// serialize_schematic(schematic, format, options={...})
static int l_serialize_schematic(lua_State *L);
+ // read_schematic(schematic, options={...})
+ static int l_read_schematic(lua_State *L);
+
public:
static void Initialize(lua_State *L, int top);
diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp
index 22fc61782..229ce73db 100644
--- a/src/script/lua_api/l_nodemeta.cpp
+++ b/src/script/lua_api/l_nodemeta.cpp
@@ -68,7 +68,7 @@ void NodeMetaRef::reportMetadataChange(const std::string *name)
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
event.p = m_p;
event.is_private_change = name && meta && meta->isPrivate(*name);
- m_env->getMap().dispatchEvent(&event);
+ m_env->getMap().dispatchEvent(event);
}
// Exported functions
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index b3ed39c7c..efdb345c9 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -170,8 +170,8 @@ int ObjectRef::l_punch(lua_State *L)
ObjectRef *puncher_ref = checkobject(L, 2);
ServerActiveObject *co = getobject(ref);
ServerActiveObject *puncher = getobject(puncher_ref);
- if (co == NULL) return 0;
- if (puncher == NULL) return 0;
+ if (!co || !puncher)
+ return 0;
v3f dir;
if (lua_type(L, 5) != LUA_TTABLE)
dir = co->getBasePosition() - puncher->getBasePosition();
@@ -187,12 +187,14 @@ int ObjectRef::l_punch(lua_State *L)
u16 dst_origin_hp = puncher->getHP();
// Do it
- co->punch(dir, &toolcap, puncher, time_from_last_punch);
+ u16 wear = co->punch(dir, &toolcap, puncher, time_from_last_punch);
+ lua_pushnumber(L, wear);
// If the punched is a player, and its HP changed
if (src_original_hp != co->getHP() &&
co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
- getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher));
+ getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co,
+ PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher));
}
// If the puncher is a player, and its HP changed
@@ -201,7 +203,7 @@ int ObjectRef::l_punch(lua_State *L)
getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher,
PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, co));
}
- return 0;
+ return 1;
}
// right_click(self, clicker); clicker = an another ObjectRef
@@ -307,8 +309,9 @@ int ObjectRef::l_get_wield_list(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if (co == NULL) return 0;
- // Do it
+ if (!co)
+ return 0;
+
lua_pushstring(L, co->getWieldList().c_str());
return 1;
}
@@ -319,8 +322,9 @@ int ObjectRef::l_get_wield_index(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if (co == NULL) return 0;
- // Do it
+ if (!co)
+ return 0;
+
lua_pushinteger(L, co->getWieldIndex() + 1);
return 1;
}
@@ -331,13 +335,15 @@ int ObjectRef::l_get_wielded_item(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if (co == NULL) {
+ if (!co) {
// Empty ItemStack
LuaItemStack::create(L, ItemStack());
return 1;
}
- // Do it
- LuaItemStack::create(L, co->getWieldedItem());
+
+ ItemStack selected_item;
+ co->getWieldedItem(&selected_item, nullptr);
+ LuaItemStack::create(L, selected_item);
return 1;
}
@@ -352,7 +358,7 @@ int ObjectRef::l_set_wielded_item(lua_State *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));
+ getServer(L)->SendInventory((PlayerSAO *)co, true);
}
lua_pushboolean(L, success);
return 1;
@@ -583,6 +589,24 @@ int ObjectRef::l_get_eye_offset(lua_State *L)
return 2;
}
+// send_mapblock(self, pos)
+int ObjectRef::l_send_mapblock(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+
+ RemotePlayer *player = getplayer(ref);
+ if (!player)
+ return 0;
+ v3s16 p = read_v3s16(L, 2);
+
+ session_t peer_id = player->getPeerId();
+ bool r = getServer(L)->SendBlock(peer_id, p);
+
+ lua_pushboolean(L, r);
+ return 1;
+}
+
// set_animation_frame_speed(self, frame_speed)
int ObjectRef::l_set_animation_frame_speed(lua_State *L)
{
@@ -731,17 +755,14 @@ int ObjectRef::l_set_properties(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if (co == NULL) return 0;
+ if (!co)
+ return 0;
+
ObjectProperties *prop = co->accessObjectProperties();
if (!prop)
return 0;
- read_object_properties(L, 2, prop, getServer(L)->idef());
- if (prop->hp_max < co->getHP()) {
- PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
- co->setHP(prop->hp_max, reason);
- if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
- getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, reason);
- }
+
+ read_object_properties(L, 2, co, prop, getServer(L)->idef());
co->notifyObjectPropertiesModified();
return 0;
}
@@ -1074,6 +1095,27 @@ int ObjectRef::l_get_player_velocity(lua_State *L)
return 1;
}
+// add_player_velocity(self, {x=num, y=num, z=num})
+int ObjectRef::l_add_player_velocity(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ v3f vel = checkFloatPos(L, 2);
+
+ RemotePlayer *player = getplayer(ref);
+ PlayerSAO *co = getplayersao(ref);
+ if (!player || !co)
+ return 0;
+
+ session_t peer_id = player->getPeerId();
+ if (peer_id == PEER_ID_INEXISTENT)
+ return 0;
+ // Do it
+ co->setMaxSpeedOverride(vel);
+ getServer(L)->SendPlayerSpeed(peer_id, vel);
+ return 0;
+}
+
// get_look_dir(self)
int ObjectRef::l_get_look_dir(lua_State *L)
{
@@ -1210,6 +1252,37 @@ int ObjectRef::l_set_look_yaw(lua_State *L)
return 1;
}
+// set_fov(self, degrees[, is_multiplier])
+int ObjectRef::l_set_fov(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ RemotePlayer *player = getplayer(ref);
+ if (!player)
+ return 0;
+
+ player->setFov({ static_cast<f32>(luaL_checknumber(L, 2)), readParam<bool>(L, 3) });
+ getServer(L)->SendPlayerFov(player->getPeerId());
+
+ return 0;
+}
+
+// get_fov(self)
+int ObjectRef::l_get_fov(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ RemotePlayer *player = getplayer(ref);
+ if (!player)
+ return 0;
+
+ PlayerFovSpec fov_spec = player->getFov();
+ lua_pushnumber(L, fov_spec.fov);
+ lua_pushboolean(L, fov_spec.is_multiplier);
+
+ return 2;
+}
+
// set_breath(self, breath)
int ObjectRef::l_set_breath(lua_State *L)
{
@@ -1239,6 +1312,9 @@ int ObjectRef::l_get_breath(lua_State *L)
// set_attribute(self, attribute, value)
int ObjectRef::l_set_attribute(lua_State *L)
{
+ log_deprecated(L,
+ "Deprecated call to set_attribute, use MetaDataRef methods instead.");
+
ObjectRef *ref = checkobject(L, 1);
PlayerSAO* co = getplayersao(ref);
if (co == NULL)
@@ -1257,6 +1333,9 @@ int ObjectRef::l_set_attribute(lua_State *L)
// get_attribute(self, attribute)
int ObjectRef::l_get_attribute(lua_State *L)
{
+ log_deprecated(L,
+ "Deprecated call to get_attribute, use MetaDataRef methods instead.");
+
ObjectRef *ref = checkobject(L, 1);
PlayerSAO* co = getplayersao(ref);
if (co == NULL)
@@ -1907,6 +1986,7 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, is_player_connected),
luamethod(ObjectRef, get_player_name),
luamethod(ObjectRef, get_player_velocity),
+ luamethod(ObjectRef, add_player_velocity),
luamethod(ObjectRef, get_look_dir),
luamethod(ObjectRef, get_look_pitch),
luamethod(ObjectRef, get_look_yaw),
@@ -1916,6 +1996,8 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, set_look_vertical),
luamethod(ObjectRef, set_look_yaw),
luamethod(ObjectRef, set_look_pitch),
+ luamethod(ObjectRef, get_fov),
+ luamethod(ObjectRef, set_fov),
luamethod(ObjectRef, get_breath),
luamethod(ObjectRef, set_breath),
luamethod(ObjectRef, get_attribute),
@@ -1951,5 +2033,6 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, get_local_animation),
luamethod(ObjectRef, set_eye_offset),
luamethod(ObjectRef, get_eye_offset),
+ luamethod(ObjectRef, send_mapblock),
{0,0}
};
diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h
index c7d963d87..e817e1d33 100644
--- a/src/script/lua_api/l_object.h
+++ b/src/script/lua_api/l_object.h
@@ -212,6 +212,12 @@ private:
// get_player_velocity(self)
static int l_get_player_velocity(lua_State *L);
+ // add_player_velocity(self, {x=num, y=num, z=num})
+ static int l_add_player_velocity(lua_State *L);
+
+ // get_fov(self)
+ static int l_get_fov(lua_State *L);
+
// get_look_dir(self)
static int l_get_look_dir(lua_State *L);
@@ -229,6 +235,9 @@ private:
// get_look_yaw2(self)
static int l_get_look_horizontal(lua_State *L);
+ // set_fov(self, degrees, is_multiplier)
+ static int l_set_fov(lua_State *L);
+
// set_look_vertical(self, radians)
static int l_set_look_vertical(lua_State *L);
@@ -351,4 +360,6 @@ private:
// get_nametag_attributes(self)
static int l_get_nametag_attributes(lua_State *L);
+ // send_mapblock(pos)
+ static int l_send_mapblock(lua_State *L);
};
diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp
index 6017a5475..7c083e652 100644
--- a/src/script/lua_api/l_server.cpp
+++ b/src/script/lua_api/l_server.cpp
@@ -233,6 +233,10 @@ int ModApiServer::l_get_player_information(lua_State *L)
lua_pushnumber(L, prot_vers);
lua_settable(L, table);
+ lua_pushstring(L, "formspec_version");
+ lua_pushnumber(L, player->formspec_version);
+ lua_settable(L, table);
+
#ifndef NDEBUG
lua_pushstring(L,"serialization_version");
lua_pushnumber(L, ser_vers);
diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp
index c92983bd3..fd73d21d1 100644
--- a/src/script/lua_api/l_vmanip.cpp
+++ b/src/script/lua_api/l_vmanip.cpp
@@ -126,7 +126,7 @@ int LuaVoxelManip::l_write_to_map(lua_State *L)
for (const auto &modified_block : o->modified_blocks)
event.modified_blocks.insert(modified_block.first);
- map->dispatchEvent(&event);
+ map->dispatchEvent(event);
o->modified_blocks.clear();
return 0;