Fix negative offsets not being supported by container[]
[oweals/minetest.git] / builtin / common / misc_helpers.lua
index 01237f265248d3075bf5685c42e7a7fe6dd9ca22..25632b4ca21754aa6ff805323c8e76d6e8b6a0ce 100644 (file)
@@ -120,7 +120,12 @@ end
 -- The dumped and level arguments are internal-only.
 
 function dump(o, indent, nested, level)
-       if type(o) ~= "table" then
+       local t = type(o)
+       if not level and t == "userdata" then
+               -- when userdata (e.g. player) is passed directly, print its metatable:
+               return "userdata metatable: " .. dump(getmetatable(o))
+       end
+       if t ~= "table" then
                return basic_dump(o)
        end
        -- Contains table -> true/nil of currently nested tables
@@ -161,9 +166,9 @@ end
 --------------------------------------------------------------------------------
 function string.split(str, delim, include_empty, max_splits, sep_is_pattern)
        delim = delim or ","
-       max_splits = max_splits or -1
+       max_splits = max_splits or -2
        local items = {}
-       local pos, len, seplen = 1, #str, #delim
+       local pos, len = 1, #str
        local plain = not sep_is_pattern
        max_splits = max_splits + 1
        repeat
@@ -238,6 +243,20 @@ function math.sign(x, tolerance)
        return 0
 end
 
+--------------------------------------------------------------------------------
+function math.factorial(x)
+       assert(x % 1 == 0 and x >= 0, "factorial expects a non-negative integer")
+       if x >= 171 then
+               -- 171! is greater than the biggest double, no need to calculate
+               return math.huge
+       end
+       local v = 1
+       for k = 2, x do
+               v = v * k
+       end
+       return v
+end
+
 --------------------------------------------------------------------------------
 function get_last_folder(text,count)
        local parts = text:split(DIR_DELIM)
@@ -336,7 +355,7 @@ if INIT == "game" then
        local dirs2 = {20, 23, 22, 21}
 
        function core.rotate_and_place(itemstack, placer, pointed_thing,
-                               infinitestacks, orient_flags)
+                       infinitestacks, orient_flags, prevent_after_place)
                orient_flags = orient_flags or {}
 
                local unode = core.get_node_or_nil(pointed_thing.under)
@@ -377,7 +396,7 @@ if INIT == "game" then
                        param2 = dirs1[fdir + 1]
                elseif isceiling then
                        if orient_flags.force_facedir then
-                               cparam2 = 20
+                               param2 = 20
                        else
                                param2 = dirs2[fdir + 1]
                        end
@@ -389,7 +408,7 @@ if INIT == "game" then
 
                local old_itemstack = ItemStack(itemstack)
                local new_itemstack, removed = core.item_place_node(
-                       itemstack, placer, pointed_thing, param2
+                       itemstack, placer, pointed_thing, param2, prevent_after_place
                )
                return infinitestacks and old_itemstack or new_itemstack
        end
@@ -410,7 +429,7 @@ if INIT == "game" then
                local invert_wall = placer and placer:get_player_control().sneak or false
                core.rotate_and_place(itemstack, placer, pointed_thing,
                                is_creative(name),
-                               {invert_wall = invert_wall})
+                               {invert_wall = invert_wall}, true)
                return itemstack
        end
 end
@@ -490,7 +509,7 @@ function core.string_to_pos(value)
                p.z = tonumber(p.z)
                return p
        end
-       local p = {}
+       p = {}
        p.x, p.y, p.z = string.match(value, "^%( *([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+) *%)$")
        if p.x and p.y and p.z then
                p.x = tonumber(p.x)
@@ -546,12 +565,22 @@ function table.copy(t, seen)
        end
        return n
 end
+
+
+function table.insert_all(t, other)
+       for i=1, #other do
+               t[#t + 1] = other[i]
+       end
+       return t
+end
+
+
 --------------------------------------------------------------------------------
 -- mainmenu only functions
 --------------------------------------------------------------------------------
 if INIT == "mainmenu" then
        function core.get_game(index)
-               local games = game.get_games()
+               local games = core.get_games()
 
                if index > 0 and index <= #games then
                        return games[index]
@@ -670,6 +699,12 @@ end
 -- Returns the exact coordinate of a pointed surface
 --------------------------------------------------------------------------------
 function core.pointed_thing_to_face_pos(placer, pointed_thing)
+       -- Avoid crash in some situations when player is inside a node, causing
+       -- 'above' to equal 'under'.
+       if vector.equals(pointed_thing.above, pointed_thing.under) then
+               return pointed_thing.under
+       end
+
        local eye_height = placer:get_properties().eye_height
        local eye_offset_first = placer:get_eye_offset()
        local node_pos = pointed_thing.under