2018-11-03 08:46:14 -04:00
|
|
|
-- LUALOCALS < ---------------------------------------------------------
|
2021-07-11 22:33:32 -04:00
|
|
|
local math, minetest, nodecore, pairs, vector
|
|
|
|
= math, minetest, nodecore, pairs, vector
|
2021-03-08 22:06:56 -05:00
|
|
|
local math_random
|
|
|
|
= math.random
|
2018-11-03 08:46:14 -04:00
|
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
|
2020-01-05 12:59:12 -05:00
|
|
|
nodecore.amcoremod()
|
|
|
|
|
2018-11-03 08:46:14 -04:00
|
|
|
--[[
|
2019-08-27 19:14:51 -04:00
|
|
|
Helpers for visible inventory. Use "visinv" node group.
|
2018-11-03 08:46:14 -04:00
|
|
|
Sets up on_construct, after_destruct and an ABM to manage
|
|
|
|
the visual entities.
|
|
|
|
--]]
|
|
|
|
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- VISIBLE STACK ENTITY
|
|
|
|
|
2020-05-26 19:26:08 -04:00
|
|
|
local function getlightcheck(rp, obj, src)
|
|
|
|
return function()
|
|
|
|
local stack = nodecore.stack_get(rp)
|
|
|
|
if not stack or stack:is_empty() then return end
|
|
|
|
|
|
|
|
local def = minetest.registered_items[stack:get_name()] or {}
|
|
|
|
if (def.light_source or 0) ~= src then return end
|
|
|
|
|
|
|
|
for _, v in pairs(nodecore.get_objects_at_pos(rp)) do
|
|
|
|
if v == obj then return true end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-07-06 07:25:03 -04:00
|
|
|
local hash = minetest.hash_node_position
|
|
|
|
local unhash = minetest.get_position_from_hash
|
|
|
|
|
2020-06-21 10:11:13 -04:00
|
|
|
local check_queue = {}
|
|
|
|
local check_queue_dirty
|
2020-06-21 09:38:54 -04:00
|
|
|
local function visinv_update_ents(pos)
|
|
|
|
pos = vector.round(pos)
|
2021-07-06 07:25:03 -04:00
|
|
|
check_queue[hash(pos)] = pos
|
2020-06-21 10:11:13 -04:00
|
|
|
check_queue_dirty = true
|
2020-06-21 09:38:54 -04:00
|
|
|
end
|
|
|
|
nodecore.visinv_update_ents = visinv_update_ents
|
|
|
|
|
2020-06-21 10:11:13 -04:00
|
|
|
local visinv_ents = {}
|
2020-06-21 09:38:54 -04:00
|
|
|
local function objremove(ent, obj)
|
2020-06-21 10:11:13 -04:00
|
|
|
visinv_ents[ent] = nil
|
2020-06-21 09:38:54 -04:00
|
|
|
return (obj or ent.object):remove()
|
|
|
|
end
|
|
|
|
|
2020-06-16 06:43:08 -04:00
|
|
|
local function itemcheck(self)
|
|
|
|
local obj = self.object
|
2021-07-06 07:25:03 -04:00
|
|
|
if not (obj and obj:get_pos()) then
|
|
|
|
visinv_ents[self] = nil
|
|
|
|
return
|
|
|
|
end
|
2020-05-26 19:06:20 -04:00
|
|
|
|
2021-07-06 07:25:03 -04:00
|
|
|
local rp = self.pos
|
2021-07-05 13:42:46 -04:00
|
|
|
local nodemeta = minetest.get_meta(rp)
|
|
|
|
local tweenfrom = minetest.deserialize(nodemeta:get_string("tweenfrom"))
|
|
|
|
|
2021-07-06 07:25:03 -04:00
|
|
|
local stack = nodecore.stack_get(rp)
|
2020-06-15 22:05:26 -04:00
|
|
|
|
2020-06-16 06:43:08 -04:00
|
|
|
local sstr = stack:to_string()
|
2021-07-05 13:42:46 -04:00
|
|
|
if (not tweenfrom) and self.stackstring == sstr then return end
|
2020-06-16 06:43:08 -04:00
|
|
|
self.stackstring = sstr
|
2020-06-15 22:05:26 -04:00
|
|
|
|
2020-06-21 09:38:54 -04:00
|
|
|
if stack:is_empty() then return objremove(self, obj) end
|
2019-03-08 19:11:05 -05:00
|
|
|
|
2020-06-16 06:43:08 -04:00
|
|
|
local def = minetest.registered_items[stack:get_name()] or {}
|
|
|
|
local src = def.light_source or 0
|
|
|
|
if src > 0 then
|
|
|
|
self.light_source = src
|
|
|
|
nodecore.dynamic_light_add(rp, src, getlightcheck(rp, obj, src))
|
|
|
|
end
|
2020-05-26 19:06:20 -04:00
|
|
|
|
2020-06-16 06:43:08 -04:00
|
|
|
local props, scale, yaw = nodecore.stackentprops(stack,
|
|
|
|
rp.x * 3 + rp.y * 5 + rp.z * 7)
|
2021-07-05 13:42:46 -04:00
|
|
|
local op = {
|
|
|
|
x = rp.x,
|
|
|
|
y = rp.y + scale - 31/64,
|
|
|
|
z = rp.z
|
|
|
|
}
|
|
|
|
|
|
|
|
if tweenfrom then
|
|
|
|
nodemeta:set_string("tweenfrom", "")
|
|
|
|
obj:set_pos(tweenfrom)
|
|
|
|
obj:move_to(op)
|
|
|
|
elseif not vector.equals(obj:get_pos(), op) then
|
|
|
|
obj:set_pos(op)
|
|
|
|
end
|
Larger, bolder, easier to see item and stack ents.
This restores an old visual scale from the extremely early days
of NodeCore. That style was removed to syncrhonize the scale of
stack nodes with item ents. The syncrhonization can work the
other way, too, though.
This was triggered by wanting to make loose item ents more
visually distinct at a glance from settled stack nodes, by making
loose item ent rotation faster. Since we were going to change the
properties either way, given that, then we might as well use the
better visual.
Since making stack nodes have a full-size collision hull, it was
distracting having the items inside be so mismatched in scale.
Also, the "pointing around stacks" thing becomes less important
in long-run gameplay with shelves in play, which do not allow
pointing around/through anyway.
2019-03-30 22:07:23 -04:00
|
|
|
|
2020-06-16 06:43:08 -04:00
|
|
|
if obj:get_yaw() ~= yaw then
|
|
|
|
obj:set_yaw(yaw)
|
|
|
|
end
|
2021-07-05 13:42:46 -04:00
|
|
|
|
2020-06-16 06:43:08 -04:00
|
|
|
return obj:set_properties(props)
|
|
|
|
end
|
|
|
|
|
|
|
|
local entname = modname .. ":stackent"
|
2020-06-17 21:53:07 -04:00
|
|
|
minetest.register_entity(entname, {
|
|
|
|
initial_properties = nodecore.stackentprops(),
|
|
|
|
is_stack = true,
|
2020-06-21 09:38:54 -04:00
|
|
|
itemcheck = itemcheck
|
2020-06-17 21:53:07 -04:00
|
|
|
})
|
2018-11-03 08:46:14 -04:00
|
|
|
|
2021-03-08 22:06:56 -05:00
|
|
|
local check_retry
|
|
|
|
local function check_retry_add(key, val)
|
|
|
|
if not check_retry then
|
|
|
|
check_retry = {}
|
|
|
|
minetest.after(1 + math_random(), function()
|
2021-03-08 22:26:00 -05:00
|
|
|
local total = 0
|
2021-03-08 22:06:56 -05:00
|
|
|
for k, v in pairs(check_retry) do
|
2021-03-08 22:26:00 -05:00
|
|
|
total = total + 1
|
2021-03-08 22:06:56 -05:00
|
|
|
check_queue[k] = v
|
|
|
|
end
|
|
|
|
check_queue_dirty = true
|
|
|
|
check_retry = nil
|
2021-03-08 22:26:00 -05:00
|
|
|
nodecore.log("warning", "visinv entity retry: " .. total)
|
2021-03-08 22:06:56 -05:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
check_retry[key] = val
|
|
|
|
end
|
|
|
|
|
2020-06-15 07:21:39 -04:00
|
|
|
nodecore.register_globalstep("visinv check", function()
|
2020-06-21 10:11:13 -04:00
|
|
|
if not check_queue_dirty then return end
|
|
|
|
local batch = check_queue
|
|
|
|
check_queue = {}
|
|
|
|
check_queue_dirty = nil
|
|
|
|
|
|
|
|
for ent in pairs(visinv_ents) do
|
2020-06-21 09:38:54 -04:00
|
|
|
if (ent.name == entname) and (not ent.gone) then
|
|
|
|
local key = ent.poskey
|
2020-06-15 22:15:38 -04:00
|
|
|
if key then
|
2020-06-21 09:38:54 -04:00
|
|
|
local data = batch[key]
|
2020-06-17 21:53:07 -04:00
|
|
|
if data then
|
2020-06-21 09:38:54 -04:00
|
|
|
if data.n then
|
|
|
|
objremove(ent)
|
2020-05-30 22:33:13 -04:00
|
|
|
else
|
2020-06-21 09:38:54 -04:00
|
|
|
itemcheck(ent)
|
|
|
|
data.n = true
|
2020-05-30 22:33:13 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2020-06-21 09:38:54 -04:00
|
|
|
for poskey, data in pairs(batch) do
|
|
|
|
if (not data.n) and (not nodecore.stack_get(data):is_empty()) then
|
2021-07-11 22:33:32 -04:00
|
|
|
local obj = minetest.add_entity(data, entname)
|
2020-06-21 09:38:54 -04:00
|
|
|
local ent = obj and obj:get_luaentity()
|
|
|
|
if ent then
|
2020-06-21 10:11:13 -04:00
|
|
|
visinv_ents[ent] = true
|
2020-06-21 09:38:54 -04:00
|
|
|
ent.is_stack = true
|
|
|
|
ent.poskey = poskey
|
2021-07-06 07:25:03 -04:00
|
|
|
ent.pos = unhash(poskey)
|
2020-06-21 09:38:54 -04:00
|
|
|
itemcheck(ent)
|
2021-03-08 22:06:56 -05:00
|
|
|
else
|
|
|
|
check_retry_add(poskey, data)
|
2020-06-21 09:38:54 -04:00
|
|
|
end
|
2020-05-30 22:33:13 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2018-11-03 08:46:14 -04:00
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- NODE REGISTRATION HELPERS
|
|
|
|
|
|
|
|
function nodecore.visinv_on_construct(pos)
|
2021-04-10 09:00:39 -04:00
|
|
|
return nodecore.visinv_update_ents(pos)
|
2018-11-03 08:46:14 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
function nodecore.visinv_after_destruct(pos)
|
|
|
|
nodecore.visinv_update_ents(pos)
|
2021-04-10 09:00:39 -04:00
|
|
|
return nodecore.fallcheck(pos)
|
2018-11-03 08:46:14 -04:00
|
|
|
end
|
|
|
|
|
2019-08-31 09:26:53 -04:00
|
|
|
nodecore.register_on_register_item(function(_, def)
|
2019-01-24 20:45:14 -05:00
|
|
|
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
|
2021-04-10 09:00:39 -04:00
|
|
|
def.can_have_itemstack = true
|
2018-11-03 08:46:14 -04:00
|
|
|
def.on_construct = def.on_construct or nodecore.visinv_on_construct
|
|
|
|
def.after_destruct = def.after_destruct or nodecore.visinv_after_destruct
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2020-06-21 03:52:09 -04:00
|
|
|
nodecore.register_lbm({
|
|
|
|
name = modname .. ":init",
|
|
|
|
run_at_every_load = true,
|
2018-11-03 08:46:14 -04:00
|
|
|
nodenames = {"group:visinv"},
|
2021-03-09 00:09:05 -05:00
|
|
|
action = function(...) return nodecore.visinv_update_ents(...) end
|
|
|
|
})
|
|
|
|
|
|
|
|
nodecore.register_abm({
|
|
|
|
label = "visinv check",
|
|
|
|
interval = 2,
|
|
|
|
chance = 1,
|
|
|
|
nodenames = {"group:visinv"},
|
2018-11-03 08:46:14 -04:00
|
|
|
action = function(...) return nodecore.visinv_update_ents(...) end
|
|
|
|
})
|
|
|
|
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- DIG INVENTORY
|
|
|
|
|
2020-09-11 22:57:33 -04:00
|
|
|
local dug
|
2018-11-03 08:46:14 -04:00
|
|
|
local old_node_dig = minetest.node_dig
|
2020-09-11 22:57:33 -04:00
|
|
|
minetest.node_dig = function(pos, node, digger, ...)
|
2019-03-24 18:42:32 -04:00
|
|
|
nodecore.stack_sounds(pos, "dug")
|
2018-11-03 08:46:14 -04:00
|
|
|
local function helper(...)
|
2020-09-11 22:57:33 -04:00
|
|
|
dug = nil
|
2018-11-03 08:46:14 -04:00
|
|
|
return ...
|
|
|
|
end
|
2020-09-11 22:57:33 -04:00
|
|
|
dug = {pos = pos, who = digger}
|
|
|
|
return helper(old_node_dig(pos, node, digger, ...))
|
2018-11-03 08:46:14 -04:00
|
|
|
end
|
|
|
|
local old_get_node_drops = minetest.get_node_drops
|
|
|
|
minetest.get_node_drops = function(...)
|
2019-03-24 18:34:17 -04:00
|
|
|
local drops = old_get_node_drops(...)
|
2020-09-11 22:57:33 -04:00
|
|
|
if not dug then return drops end
|
2019-03-24 18:34:17 -04:00
|
|
|
drops = drops or {}
|
2020-09-11 22:57:33 -04:00
|
|
|
local stack = nodecore.stack_get(dug.pos)
|
2019-03-05 19:20:38 -05:00
|
|
|
if stack and not stack:is_empty() then
|
2020-09-11 22:57:33 -04:00
|
|
|
local def = stack:get_definition()
|
|
|
|
local dmg = def and def.groups and def.groups.damage_touch
|
2020-09-11 22:58:34 -04:00
|
|
|
if dug.who and dmg and dmg > 0 then
|
2020-09-11 22:57:33 -04:00
|
|
|
nodecore.addphealth(dug.who, -dmg, "hot pickup")
|
|
|
|
nodecore.item_eject(dug.pos, stack, 0.001)
|
|
|
|
else
|
|
|
|
drops[#drops + 1] = stack
|
|
|
|
end
|
2019-03-05 19:20:38 -05:00
|
|
|
end
|
2019-03-24 18:34:17 -04:00
|
|
|
return drops
|
2019-01-28 23:13:21 -05:00
|
|
|
end
|