Aaron Suen d0e6dcc410 Add "stasis" option and command.
This freezes many things that normally happen automatically
in the world, including most ABMs and AISMs, and a few other
custom step logic items like the player "hot potato" logic.

This can be used for "creative mode" purposes to setup a complex
build without it running itself away from you, and for texture
pack authors, to have time to see things that are normally
transient or difficult to observe because of the effects they have
on nearby things or players.
2020-01-10 06:26:07 -05:00

133 lines
3.4 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs, vector
= minetest, nodecore, pairs, vector
-- LUALOCALS > ---------------------------------------------------------
nodecore.amcoremod()
--[[
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
minetest.register_entity(modname .. ":stackent", {
initial_properties = nodecore.stackentprops(),
is_stack = true,
itemcheck = function(self)
local pos = self.object:get_pos()
local stack = nodecore.stack_get(pos)
if not stack or stack:is_empty() then return self.object:remove() end
local rp = vector.round(pos)
local props, scale, yaw = nodecore.stackentprops(stack,
rp.x * 3 + rp.y * 5 + rp.z * 7)
rp.y = rp.y + scale - 31/64
local obj = self.object
obj:set_properties(props)
obj:set_yaw(yaw)
obj:set_pos(rp)
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_items[node.name] or {}
local max = def.groups and def.groups.visinv and 1 or 0
local found = {}
for _, 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
return found
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)
nodecore.fallcheck(pos)
end
nodecore.register_on_register_item(function(_, def)
if def.type ~= "node" then return end
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)
nodecore.register_limited_abm({
label = "VisInv Check",
nodenames = {"group:visinv"},
interval = 1,
chance = 1,
ignore_stasis = true,
action = function(...) return nodecore.visinv_update_ents(...) end
})
------------------------------------------------------------------------
-- DIG INVENTORY
local digpos
local old_node_dig = minetest.node_dig
minetest.node_dig = function(pos, ...)
nodecore.stack_sounds(pos, "dug")
local function helper(...)
digpos = nil
return ...
end
digpos = pos
return helper(old_node_dig(pos, ...))
end
local old_get_node_drops = minetest.get_node_drops
minetest.get_node_drops = function(...)
local drops = old_get_node_drops(...)
if not digpos then return drops end
drops = drops or {}
local stack = nodecore.stack_get(digpos)
if stack and not stack:is_empty() then
drops[#drops + 1] = stack
end
return drops
end