bd35a4df55
Protection mechanics are fully disabled for all actions carried out by world mechanics itself, including machine digging/placing and entity/fluid displacement. This may create new opportunities for players to abuse and bypass protection mechanics. This is an acceptable loss; the integrity of game mechanics is more important, or else players are forced to remove protections anyway in order to get their builds to actually work.
93 lines
2.9 KiB
Lua
93 lines
2.9 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ItemStack, ipairs, math, minetest, nodecore, vector
|
|
= ItemStack, ipairs, math, minetest, nodecore, vector
|
|
local math_random
|
|
= math.random
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local stackonly = nodecore.group_expand("group:is_stack_only", true)
|
|
|
|
local function nuke(self)
|
|
self.itemstring = ""
|
|
self.object:remove()
|
|
return true
|
|
end
|
|
|
|
local hand = ItemStack("")
|
|
nodecore.register_item_entity_on_settle(function(self, pos)
|
|
local curnode = minetest.get_node(pos)
|
|
if curnode.name == "ignore" then return end
|
|
|
|
local below = {x = pos.x, y = pos.y - 0.55, z = pos.z}
|
|
local bnode = minetest.get_node(below)
|
|
|
|
if (pos.y - 1 >= nodecore.map_limit_min) and (bnode.name == "ignore")
|
|
then return end
|
|
|
|
local item = ItemStack(self.itemstring)
|
|
item = nodecore.stack_settle(pos, item, curnode, nil, true)
|
|
if item:is_empty() then return nuke(self) end
|
|
if nodecore.stack_can_fall_in(below, item, bnode, nil, self) then
|
|
self.object:set_pos({x = pos.x, y = pos.y - 0.55, z = pos.z})
|
|
self.object:set_velocity({x = 0, y = 0, z = 0})
|
|
return
|
|
end
|
|
item = nodecore.stack_settle(below, item, bnode)
|
|
if item:is_empty() then return nuke(self) end
|
|
|
|
if self.nextscan and nodecore.gametime < self.nextscan then return end
|
|
self.nextscan = (self.nextscan or nodecore.gametime) + 0.75 + 0.5 * math_random()
|
|
|
|
local function placeat(p)
|
|
nodecore.place_stack(p, item)
|
|
minetest.get_meta(p):set_string("tweenfrom",
|
|
minetest.serialize(self.object:get_pos()))
|
|
return nuke(self)
|
|
end
|
|
|
|
local itemname = item:get_name()
|
|
local function trydig(p)
|
|
local node = minetest.get_node(p)
|
|
if node.name ~= itemname then
|
|
local def = minetest.registered_nodes[node.name]
|
|
if def and (not def.walkable) and def.diggable
|
|
and nodecore.tool_digs(hand, def.groups) then
|
|
nodecore.protection_bypass(minetest.dig_node, p)
|
|
return placeat(p)
|
|
end
|
|
end
|
|
end
|
|
|
|
local boxes = {}
|
|
local digs = {}
|
|
for rel in nodecore.settlescan() do
|
|
local p = vector.add(pos, rel)
|
|
local n = minetest.get_node(p)
|
|
if stackonly[n.name] then
|
|
item = nodecore.stack_add(p, item)
|
|
if item:is_empty() then return nuke(self) end
|
|
else
|
|
boxes[#boxes + 1] = p
|
|
end
|
|
if ((p.y >= nodecore.map_limit_min)
|
|
and (rel.y <= 0 or (p.y - 1 < nodecore.map_limit_min)
|
|
or nodecore.walkable({x = p.x, y = p.y - 1, z = p.z}))) then
|
|
if nodecore.buildable_to(p) then
|
|
return placeat(p)
|
|
elseif rel.x == 0 and rel.z == 0 and math_random(1, 10) == 1 then
|
|
if trydig(p) then return true end
|
|
else
|
|
digs[#digs + 1] = p
|
|
end
|
|
end
|
|
end
|
|
for _, p in ipairs(boxes) do
|
|
item = nodecore.stack_add(p, item)
|
|
if item:is_empty() then return nuke(self) end
|
|
end
|
|
for _, p in ipairs(digs) do
|
|
if trydig(p) then return true end
|
|
end
|
|
self.itemstring = item:to_string()
|
|
end)
|