Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement get_node with a get_node_raw #14384

Merged
merged 4 commits into from Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions builtin/common/item_s.lua
Expand Up @@ -239,3 +239,18 @@ if core.set_read_node and core.set_push_node then
core.set_push_node(push_node)
core.set_push_node = nil
end

if INIT == "game" then
Desour marked this conversation as resolved.
Show resolved Hide resolved
local get_node_raw = core.get_node_raw
core.get_node_raw = nil

function core.get_node(pos)
local content, param1, param2 = get_node_raw(pos.x, pos.y, pos.z)
return {name = content2name[content], param1 = param1, param2 = param2}
end

function core.get_node_or_nil(pos)
local content, param1, param2, pos_ok = get_node_raw(pos.x, pos.y, pos.z)
return pos_ok and {name = content2name[content], param1 = param1, param2 = param2} or nil
end
end
65 changes: 52 additions & 13 deletions games/devtest/mods/benchmarks/init.lua
Expand Up @@ -71,6 +71,22 @@ minetest.register_chatcommand("bench_content2name", {
end,
})

local function get_positions_cube(ppos)
local pos_list = {}

local i = 1
for x=2,100 do
for y=2,100 do
for z=2,100 do
pos_list[i] = ppos:offset(x, y, z)
i = i + 1
end
end
end

return pos_list
end

minetest.register_chatcommand("bench_bulk_set_node", {
params = "",
description = "Benchmark: Bulk-set 99×99×99 stone nodes",
Expand All @@ -79,25 +95,15 @@ minetest.register_chatcommand("bench_bulk_set_node", {
if not player then
return false, "No player."
end
local pos_list = {}
local ppos = player:get_pos()
local i = 1
for x=2,100 do
for y=2,100 do
for z=2,100 do
pos_list[i] = {x=ppos.x + x,y = ppos.y + y,z = ppos.z + z}
i = i + 1
end
end
end
local pos_list = get_positions_cube(player:get_pos())

minetest.chat_send_player(name, "Benchmarking minetest.bulk_set_node. Warming up ...");
minetest.chat_send_player(name, "Benchmarking minetest.bulk_set_node. Warming up ...")

-- warm up with stone to prevent having different callbacks
-- due to different node topology
minetest.bulk_set_node(pos_list, {name = "mapgen_stone"})

minetest.chat_send_player(name, "Warming up finished, now benchmarking ...");
minetest.chat_send_player(name, "Warming up finished, now benchmarking ...")

local start_time = minetest.get_us_time()
for i=1,#pos_list do
Expand All @@ -114,4 +120,37 @@ minetest.register_chatcommand("bench_bulk_set_node", {
end,
})

minetest.register_chatcommand("bench_bulk_get_node", {
params = "",
description = "Benchmark: Bulk-get 99×99×99 nodes",
func = function(name, param)
local player = minetest.get_player_by_name(name)
if not player then
return false, "No player."
end
local pos_list = get_positions_cube(player:get_pos())
local function bench()
local start_time = minetest.get_us_time()
for i=1,#pos_list do
local n = minetest.get_node(pos_list[i])
-- Make sure the name lookup is never optimized away.
-- Table allocation might still be omitted. But only accessing
-- the name of a node is a common pattern anyways.
if n.name == "benchmarks:nonexistent_node" then
error("should never happen")
end
end
return minetest.get_us_time() - start_time
end

minetest.chat_send_player(name, "Benchmarking minetest.get_node. Warming up ...")
bench()

minetest.chat_send_player(name, "Warming up finished, now benchmarking ...")
local result_us = bench()

local msg = string.format("Benchmark results: minetest.get_node loop 1: %.2f ms",
result_us / 1000)
return true, msg
end,
})
42 changes: 14 additions & 28 deletions src/script/lua_api/l_env.cpp
Expand Up @@ -324,39 +324,26 @@ int ModApiEnv::l_swap_node(lua_State *L)
return 1;
}

// get_node(pos)
// pos = {x=num, y=num, z=num}
int ModApiEnv::l_get_node(lua_State *L)
{
GET_ENV_PTR;

// pos
v3s16 pos = read_v3s16(L, 1);
// Do it
MapNode n = env->getMap().getNode(pos);
// Return node
pushnode(L, n);
return 1;
}

// get_node_or_nil(pos)
// pos = {x=num, y=num, z=num}
int ModApiEnv::l_get_node_or_nil(lua_State *L)
// get_node_raw(x, y, z) -> content, param1, param2, pos_ok
int ModApiEnv::l_get_node_raw(lua_State *L)
{
GET_ENV_PTR;

// pos
v3s16 pos = read_v3s16(L, 1);
// mirrors implementation of read_v3s16 (with the exact same rounding)
double x = lua_tonumber(L, 1);
double y = lua_tonumber(L, 2);
double z = lua_tonumber(L, 3);
Desour marked this conversation as resolved.
Show resolved Hide resolved
v3s16 pos = doubleToInt(v3d(x, y, z), 1.0);
// Do it
bool pos_ok;
MapNode n = env->getMap().getNode(pos, &pos_ok);
if (pos_ok) {
// Return node
pushnode(L, n);
} else {
lua_pushnil(L);
}
return 1;
// Return node and pos_ok
lua_pushinteger(L, n.getContent());
lua_pushinteger(L, n.getParam1());
lua_pushinteger(L, n.getParam2());
lua_pushboolean(L, pos_ok);
return 4;
}

// get_node_light(pos, timeofday)
Expand Down Expand Up @@ -1479,8 +1466,7 @@ void ModApiEnv::Initialize(lua_State *L, int top)
API_FCT(swap_node);
API_FCT(add_item);
API_FCT(remove_node);
API_FCT(get_node);
API_FCT(get_node_or_nil);
API_FCT(get_node_raw);
API_FCT(get_node_light);
API_FCT(get_natural_light);
API_FCT(place_node);
Expand Down
13 changes: 5 additions & 8 deletions src/script/lua_api/l_env.h
Expand Up @@ -74,13 +74,10 @@ class ModApiEnv : public ModApiEnvBase {
// pos = {x=num, y=num, z=num}
static int l_swap_node(lua_State *L);

// get_node(pos)
// pos = {x=num, y=num, z=num}
static int l_get_node(lua_State *L);

// get_node_or_nil(pos)
// pos = {x=num, y=num, z=num}
static int l_get_node_or_nil(lua_State *L);
// get_node_raw(x, y, z) -> content, param1, param2, pos_ok
// Used to implement get_node and get_node_or_nil in lua.
Desour marked this conversation as resolved.
Show resolved Hide resolved
// This is still faster than doing it from C++ even with optimized pushnode.
static int l_get_node_raw(lua_State *L);

// get_node_light(pos, timeofday)
// pos = {x=num, y=num, z=num}
Expand Down Expand Up @@ -245,7 +242,7 @@ class ModApiEnv : public ModApiEnvBase {

/*
* Duplicates of certain env APIs that operate not on the global
* map but on a VoxelManipulator. This is for emerge scripting.
* map but on a VoxelManipulator. This is for emerge scripting.
*/
class ModApiEnvVM : public ModApiEnvBase {
private:
Expand Down