d70c20cd3b
Try to place items into existing stacks when searching for a settling location. Try to launch items from reasonable corners of a source node in item_eject so they don't self-collide and end up in one pile.
167 lines
4.2 KiB
Lua
167 lines
4.2 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ItemStack, ipairs, math, minetest, nodecore, pairs, type
|
|
= ItemStack, ipairs, math, minetest, nodecore, pairs, type
|
|
local math_random
|
|
= math.random
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
for k, v in pairs(minetest) do
|
|
if type(v) == "function" then
|
|
-- Late-bind in case minetest methods overridden.
|
|
nodecore[k] = function(...) return minetest[k](...) end
|
|
else
|
|
nodecore[k] = v
|
|
end
|
|
end
|
|
|
|
local function underride(t, u, v, ...)
|
|
if v then underride(u, v, ...) end
|
|
for k, v in pairs(u) do
|
|
if t[k] == nil then
|
|
t[k] = v
|
|
elseif type(t[k]) == "table" and type(v) == "table" then
|
|
underride(t[k], v)
|
|
end
|
|
end
|
|
return t
|
|
end
|
|
nodecore.underride = underride
|
|
|
|
function nodecore.mkreg()
|
|
local t = {}
|
|
local f = function(x) t[#t + 1] = x end
|
|
return f, t
|
|
end
|
|
|
|
function nodecore.dirs()
|
|
return {
|
|
{x = 1, y = 0, z = 0},
|
|
{x = -1, y = 0, z = 0},
|
|
{x = 0, y = 1, z = 0},
|
|
{x = 0, y = -1, z = 0},
|
|
{x = 0, y = 0, z = 1},
|
|
{x = 0, y = 0, z = -1}
|
|
}
|
|
end
|
|
|
|
function nodecore.pickrand(tbl, weight)
|
|
weight = weight or function() end
|
|
local t = {}
|
|
local max = 0
|
|
for k, v in pairs(tbl) do
|
|
local w = weight(v) or 1
|
|
if w > 0 then
|
|
max = max + w
|
|
t[#t + 1] = {w = w, k = k, v = v}
|
|
end
|
|
end
|
|
if max <= 0 then return end
|
|
max = math_random() * max
|
|
for i, v in ipairs(t) do
|
|
max = max - v.w
|
|
if max <= 0 then return v.v, v.k end
|
|
end
|
|
end
|
|
|
|
function nodecore.extend_item(name, func)
|
|
local orig = minetest.registered_items[name]
|
|
local copy = {}
|
|
for k, v in pairs(orig) do copy[k] = v end
|
|
copy = func(copy, orig) or copy
|
|
minetest.register_item(":" .. name, copy)
|
|
end
|
|
|
|
function nodecore.fixedbox(...) return {type = "fixed", fixed = {...}} end
|
|
|
|
function nodecore.wieldgroup(who, group)
|
|
local wielded = who and who:get_wielded_item()
|
|
local nodedef = minetest.registered_nodes[wielded:get_name()]
|
|
if nodedef then return nodedef.groups and nodedef.groups[group] end
|
|
local caps = wielded and wielded:get_tool_capabilities()
|
|
return caps and caps.groupcaps and caps.groupcaps[group]
|
|
end
|
|
|
|
function nodecore.toolspeed(what, groups)
|
|
if not what then return end
|
|
local dg = what:get_tool_capabilities().groupcaps
|
|
local t
|
|
for gn, lv in pairs(groups) do
|
|
local gt = dg[gn]
|
|
gt = gt and gt.times
|
|
gt = gt and gt[lv]
|
|
if gt and (not t or t > gt) then t = gt end
|
|
end
|
|
return t
|
|
end
|
|
|
|
function nodecore.interval(after, func)
|
|
local function go()
|
|
minetest.after(after, go)
|
|
return func()
|
|
end
|
|
minetest.after(after, go)
|
|
end
|
|
|
|
function nodecore.wear_current_tool(player, groups, qty)
|
|
local wielded = player:get_wielded_item()
|
|
if wielded then
|
|
local wdef = wielded:get_definition()
|
|
if wdef.stack_max > 1 and qty then
|
|
local have = wielded:get_count() - qty
|
|
if have <= 0 then
|
|
wielded = ItemStack("")
|
|
else
|
|
wielded:set_count(have)
|
|
end
|
|
else
|
|
local tp = wielded:get_tool_capabilities()
|
|
local dp = minetest.get_dig_params(groups, tp)
|
|
if wdef and wdef.after_use then
|
|
wielded = wdef.after_use(wielded, player, nil, dp) or wielded
|
|
else
|
|
if not minetest.settings:get_bool("creative_mode") then
|
|
wielded:add_wear(dp.wear * (qty or 1))
|
|
if wielded:get_count() <= 0 and wdef.sound
|
|
and wdef.sound.breaks then
|
|
minetest.sound_play(wdef.sound.breaks,
|
|
{pos = pos, gain = 0.5})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return player:set_wielded_item(wielded)
|
|
end
|
|
end
|
|
|
|
function nodecore.loaded_mods()
|
|
local t = {}
|
|
for _, v in pairs(minetest.get_modnames()) do
|
|
t[v] = true
|
|
end
|
|
return t
|
|
end
|
|
|
|
function nodecore.node_group(name, pos, node)
|
|
node = node or minetest.get_node(pos)
|
|
local def = minetest.registered_nodes[node.name]
|
|
return def and def.groups and def.groups[name]
|
|
end
|
|
|
|
function nodecore.item_eject(pos, stack, speed, qty, vel)
|
|
vel = vel or {x = 0, y = 0, z = 0}
|
|
for i = 1, (qty or 1) do
|
|
local v = {
|
|
x = vel.x + (math_random() - 0.5) * speed,
|
|
y = vel.y + (math_random() - 0.5) * speed,
|
|
z = vel.z + (math_random() - 0.5) * speed,
|
|
}
|
|
local p = {
|
|
x = v.x > 0 and pos.x + 0.5 or pos.x - 0.5,
|
|
y = v.y > 0 and pos.y + 0.5 or pos.y - 0.5,
|
|
z = v.z > 0 and pos.z + 0.5 or pos.z - 0.5,
|
|
}
|
|
local obj = minetest.add_item(p, stack)
|
|
if obj then obj:setvelocity(v) end
|
|
end
|
|
end
|