2018-11-03 08:46:14 -04:00
|
|
|
-- LUALOCALS < ---------------------------------------------------------
|
2019-03-08 19:11:05 -05:00
|
|
|
local ItemStack, math, minetest, nodecore, pairs, type, vector
|
|
|
|
= ItemStack, math, minetest, nodecore, pairs, type, vector
|
|
|
|
local math_floor, math_pi
|
|
|
|
= math.floor, math.pi
|
2018-11-03 08:46:14 -04:00
|
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
|
|
|
|
--[[
|
|
|
|
Helpers for visible inventory. Use "visinv" node group.
|
|
|
|
Sets up on_construct, after_destruct and an ABM to manage
|
|
|
|
the visual entities.
|
|
|
|
--]]
|
|
|
|
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- VISIBLE STACK ENTITY
|
|
|
|
|
2019-03-08 19:11:05 -05:00
|
|
|
local function stackentprops(stack, func)
|
2018-11-03 08:46:14 -04:00
|
|
|
local t = {
|
|
|
|
hp_max = 1,
|
|
|
|
physical = false,
|
|
|
|
collide_with_objects = false,
|
|
|
|
collisionbox = {0, 0, 0, 0, 0, 0},
|
|
|
|
visual = "wielditem",
|
|
|
|
visual_size = {x = 0.4, y = 0.4 },
|
|
|
|
textures = {""},
|
|
|
|
spritediv = {x = 1, y = 1},
|
|
|
|
initial_sprite_basepos = {x = 0, y = 0},
|
2019-03-04 19:33:55 -05:00
|
|
|
is_visible = false,
|
|
|
|
static_save = false
|
2018-11-03 08:46:14 -04:00
|
|
|
}
|
|
|
|
if stack then
|
|
|
|
t.is_visible = true
|
|
|
|
t.textures[1] = stack:get_name()
|
|
|
|
local s = 0.2 + 0.1 * stack:get_count() / stack:get_stack_max()
|
|
|
|
t.visual_size = {x = s, y = s}
|
2019-01-27 01:40:39 -05:00
|
|
|
local max = stack:get_stack_max()
|
2018-11-03 08:46:14 -04:00
|
|
|
if func then func(s) end
|
|
|
|
end
|
|
|
|
return t
|
|
|
|
end
|
|
|
|
|
|
|
|
minetest.register_entity(modname .. ":stackent", {
|
|
|
|
initial_properties = stackentprops(),
|
|
|
|
is_stack = true,
|
|
|
|
itemcheck = function(self)
|
|
|
|
local pos = self.object:getpos()
|
2019-02-23 10:21:27 -05:00
|
|
|
local stack = nodecore.stack_get(pos)
|
2019-02-28 23:47:36 -05:00
|
|
|
if not stack or stack:is_empty() then return self.object:remove() end
|
2019-03-08 19:11:05 -05:00
|
|
|
|
|
|
|
local rp = vector.round(pos)
|
|
|
|
local rot = rp.x * 3 + rp.y * 5 + rp.z * 7
|
2019-03-09 21:24:17 -05:00
|
|
|
local max = stack:get_stack_max()
|
|
|
|
local ratio = (max == 1)
|
|
|
|
and 1 - (stack:get_wear() / 65536)
|
|
|
|
or stack:get_count() / max
|
2019-03-08 19:11:05 -05:00
|
|
|
if ratio ~= 1 then rot = rot + 1/8 + 3/8 * (1 - ratio) end
|
|
|
|
rot = rot - 2 * math_floor(rot / 2)
|
|
|
|
self.object:set_yaw(rot * math_pi / 2)
|
|
|
|
|
|
|
|
return self.object:set_properties(stackentprops(stack, function(s)
|
|
|
|
pos.y = math_floor(pos.y + 0.5) - 0.5 + s + 1/64
|
2018-11-03 08:46:14 -04:00
|
|
|
self.object:setpos(pos)
|
2019-03-08 19:11:05 -05:00
|
|
|
end))
|
2018-11-03 08:46:14 -04:00
|
|
|
end,
|
|
|
|
on_activate = function(self)
|
|
|
|
self.cktime = 0.00001
|
|
|
|
end,
|
|
|
|
on_step = function(self, dtime)
|
|
|
|
self.cktime = (self.cktime or 0) - dtime
|
|
|
|
if self.cktime > 0 then return end
|
|
|
|
self.cktime = 1
|
|
|
|
return self:itemcheck()
|
|
|
|
end
|
|
|
|
})
|
|
|
|
|
|
|
|
function nodecore.visinv_update_ents(pos, node)
|
|
|
|
node = node or minetest.get_node(pos)
|
|
|
|
local def = minetest.registered_nodes[node.name]
|
|
|
|
local max = def and def.groups and def.groups.visinv and 1 or 0
|
|
|
|
|
|
|
|
local found = {}
|
|
|
|
for k, v in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
|
|
|
|
if v and v.get_luaentity and v:get_luaentity()
|
|
|
|
and v:get_luaentity().is_stack then
|
|
|
|
found[#found + 1] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if #found < max then
|
|
|
|
minetest.add_entity(pos, modname .. ":stackent")
|
|
|
|
else
|
|
|
|
while #found > max do
|
|
|
|
found[#found]:remove()
|
|
|
|
found[#found] = nil
|
|
|
|
end
|
|
|
|
end
|
2019-03-08 19:11:05 -05:00
|
|
|
|
|
|
|
return found
|
2018-11-03 08:46:14 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- NODE REGISTRATION HELPERS
|
|
|
|
|
|
|
|
function nodecore.visinv_on_construct(pos)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local inv = meta:get_inventory()
|
|
|
|
inv:set_size("solo", 1)
|
|
|
|
nodecore.visinv_update_ents(pos)
|
|
|
|
end
|
|
|
|
|
|
|
|
function nodecore.visinv_after_destruct(pos)
|
|
|
|
nodecore.visinv_update_ents(pos)
|
|
|
|
minetest.after(0, function()
|
|
|
|
minetest.check_for_falling(pos)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2019-01-24 20:45:14 -05:00
|
|
|
nodecore.register_on_register_item(function(name, def)
|
|
|
|
if def.type ~= "node" then return end
|
2019-02-23 21:30:35 -05:00
|
|
|
|
2018-11-03 08:46:14 -04:00
|
|
|
def.groups = def.groups or {}
|
|
|
|
|
|
|
|
if def.groups.visinv then
|
|
|
|
def.on_construct = def.on_construct or nodecore.visinv_on_construct
|
|
|
|
def.after_destruct = def.after_destruct or nodecore.visinv_after_destruct
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2019-01-06 12:02:37 -05:00
|
|
|
nodecore.register_limited_abm({
|
2018-11-03 08:46:14 -04:00
|
|
|
label = "VisInv Check",
|
|
|
|
nodenames = {"group:visinv"},
|
|
|
|
interval = 1,
|
|
|
|
chance = 1,
|
|
|
|
action = function(...) return nodecore.visinv_update_ents(...) end
|
|
|
|
})
|
|
|
|
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- DIG INVENTORY
|
|
|
|
|
|
|
|
local digpos
|
|
|
|
local old_node_dig = minetest.node_dig
|
2019-03-03 16:22:02 -05:00
|
|
|
minetest.node_dig = function(pos, node, digger, ...)
|
2018-11-03 08:46:14 -04:00
|
|
|
local function helper(...)
|
|
|
|
digpos = nil
|
|
|
|
return ...
|
|
|
|
end
|
|
|
|
digpos = pos
|
2019-03-03 16:22:02 -05:00
|
|
|
return helper(old_node_dig(pos, node, digger, ...))
|
|
|
|
end
|
|
|
|
local function trydirect(stack)
|
|
|
|
stack = ItemStack(stack)
|
|
|
|
|
|
|
|
local p = digplayer
|
2019-03-03 16:46:30 -05:00
|
|
|
if (not p) or (not p:get_player_control().sneak) then return end
|
2019-03-03 16:22:02 -05:00
|
|
|
|
|
|
|
local inv = p:get_inventory()
|
|
|
|
for i = 1, inv:get_size("main") do
|
2019-03-03 16:46:30 -05:00
|
|
|
if i ~= p:get_wield_index()
|
|
|
|
and inv:get_stack("main", i):is_empty() then
|
|
|
|
return inv:set_stack("main", i, stack)
|
2019-03-03 16:22:02 -05:00
|
|
|
end
|
|
|
|
end
|
2018-11-03 08:46:14 -04:00
|
|
|
end
|
|
|
|
local old_get_node_drops = minetest.get_node_drops
|
2019-03-05 19:20:38 -05:00
|
|
|
local deferred_drop
|
2018-11-03 08:46:14 -04:00
|
|
|
minetest.get_node_drops = function(...)
|
2019-03-05 19:20:38 -05:00
|
|
|
if not digpos then
|
|
|
|
return old_get_node_drops(...)
|
|
|
|
end
|
2019-02-23 10:21:27 -05:00
|
|
|
local stack = nodecore.stack_get(digpos)
|
2019-03-05 19:20:38 -05:00
|
|
|
if stack and not stack:is_empty() then
|
|
|
|
deferred_drop = stack
|
|
|
|
end
|
|
|
|
return old_get_node_drops(...)
|
|
|
|
end
|
|
|
|
local old_handle_node_drops = minetest.handle_node_drops
|
|
|
|
function minetest.handle_node_drops(pos, drops, digger, ...)
|
|
|
|
old_handle_node_drops(pos, drops, digger, ...)
|
2019-03-08 19:11:05 -05:00
|
|
|
|
2019-03-05 19:20:38 -05:00
|
|
|
if not deferred_drop then return end
|
2019-03-05 20:57:51 -05:00
|
|
|
local defer = deferred_drop
|
|
|
|
deferred_drop = nil
|
2019-03-08 19:11:05 -05:00
|
|
|
|
2019-03-05 19:20:38 -05:00
|
|
|
if digger and digger:is_player()
|
|
|
|
and digger:get_player_control().sneak then
|
|
|
|
local inv = digger:get_inventory()
|
|
|
|
for i = 1, inv:get_size("main") do
|
|
|
|
if inv:get_stack("main", i):is_empty() then
|
2019-03-05 20:57:51 -05:00
|
|
|
return inv:set_stack("main", i, defer)
|
2019-03-05 19:20:38 -05:00
|
|
|
end
|
|
|
|
end
|
2018-11-03 08:46:14 -04:00
|
|
|
end
|
2019-03-05 19:20:38 -05:00
|
|
|
|
2019-03-05 20:57:51 -05:00
|
|
|
return old_handle_node_drops(pos, {defer}, digger, ...)
|
2019-01-28 23:13:21 -05:00
|
|
|
end
|