Protect against fire and falling "node" entities

master
Alex Yst 2018-06-17 23:01:42 -07:00
parent 85a0154607
commit 462070c334
6 changed files with 294 additions and 0 deletions

68
boundary display.lua Normal file
View File

@ -0,0 +1,68 @@
-- The node and entity code here have been directly copied from
-- zing269's simple_anchor mod
-- (<https://github.com/zing269/simple_anchor/>, copyright 2018, MIT
-- licenced), with only minor changes, mostly in the form of changing
-- the names to work within this mod's namespace instead of the
-- simple_anchor mod's namespace. In turn, this code from simple_anchor
-- was derived from TenPlus1's protector mod
-- (<https://notabug.org/TenPlus1/protector>, copyright 2016, MIT
-- licensed), but with bigger changes made.
-- display entity shown when loader node is punched
minetest.register_entity("blockprotectnodes:block", {
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "wielditem",
-- wielditem seems to be scaled to 1.5 times original node size
visual_size = {x = 1.0 / 1.5, y = 1.0 / 1.5},
textures = {"blockprotectnodes:block"},
timer = 0,
on_step = function(self, dtime)
self.timer = self.timer + dtime
-- remove after 15 seconds
if self.timer > 15 then
self.object:remove()
end
end,
})
-- Display-zone node, Do NOT place the display as a node,
-- it is made to be used as an entity (see above)
minetest.register_node("blockprotectnodes:block", {
tiles = {"blockprotectnodes-block.png"},
use_texture_alpha = true,
walkable = false,
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- sides
{-8.01, -8.01, -8.01, -7.99, 8.01, 8.01},
{-8.01, -8.01, 7.99, 8.01, 8.01, 8.01},
{7.99, -8.01, -8.01, 8.01, 8.01, 8.01},
{-8.01, -8.01, -8.01, 8.01, 8.01, -7.99},
-- top
{-8.01, 7.99, -8.01, 8.01, 8.01, 8.01},
-- bottom
{-8.01, -8.01, -8.01, 8.01, -7.99, 8.01},
},
},
groups = {dig_immediate = 3},
drop = "",
})
minetest.register_chatcommand("showblock", {
description = "Visually highlight the boundaries of the block the player is standing in",
func = function(caller_name)
local caller_pos = minetest.get_player_by_name(caller_name):get_pos()
local block = __blockprotectnodes__:get_node_block(caller_pos)
local range = __blockprotectnodes__:get_block_node_range(block)
local pos = {
x = (range.minp.x + range.maxp.x) / 2,
y = (range.minp.y + range.maxp.y) / 2,
z = (range.minp.z + range.maxp.z) / 2,
}
minetest.add_entity(pos, "blockprotectnodes:block")
return true
end,
})

View File

@ -1,2 +1,3 @@
default
fire?
sfinv?

112
falling.lua Normal file
View File

@ -0,0 +1,112 @@
local falling_node = minetest.registered_entities["__builtin:falling_node"]
-- This is pretty much a copy and paste function from
-- "minetest-0.4.17/builtin/game/falling.lua". There doesn't seem to be
-- a way to tap into the API and replace just the two parts of this I
-- need adjusted. The whole function can only either be left alone or
-- entirely replaced, so I'm replacing it with this nearly verbatim
-- copy, but with protection detection added.
--
-- This means, of course, that if changes are made in later versions of
-- Minetest, this function replacement will cause the behaviour to be
-- dragged back to what it was in Minetest 0.4.17, so I have to
-- manually update this code with each new release of Minetest. If
-- you're reading this and know of a better way, please let me know by
-- filing a bug report or pull request in the project's bug tracker.
--
-- This code is copyright Celeron55, licenced under the terms of the
-- GNU LGPLv2.1+.
function falling_node.on_step(self, dtime)
-- Set gravity
local acceleration = self.object:getacceleration()
if not vector.equals(acceleration, {x = 0, y = -10, z = 0}) then
self.object:setacceleration({x = 0, y = -10, z = 0})
end
-- Turn to actual node when colliding with ground, or continue to move
local pos = self.object:getpos()
-- Position of bottom center point
local bcp = {x = pos.x, y = pos.y - 0.7, z = pos.z}
-- 'bcn' is nil for unloaded nodes
local bcn = core.get_node_or_nil(bcp)
-- Delete on contact with ignore at world edges
if bcn and bcn.name == "ignore" then
self.object:remove()
return
end
local bcd = bcn and core.registered_nodes[bcn.name]
if bcn and
(not bcd or bcd.walkable or
(core.get_item_group(self.node.name, "float") ~= 0 and
bcd.liquidtype ~= "none")) then
if bcd and bcd.leveled and
bcn.name == self.node.name then
local addlevel = self.node.level
if not addlevel or addlevel <= 0 then
addlevel = bcd.leveled
end
if core.add_node_level(bcp, addlevel) == 0 then
self.object:remove()
return
end
elseif bcd and bcd.buildable_to and
(core.get_item_group(self.node.name, "float") == 0 or
bcd.liquidtype == "none") then
core.remove_node(bcp)
return
end
local np = {x = bcp.x, y = bcp.y + 1, z = bcp.z}
-- Check what's here
local n2 = core.get_node(np)
local nd = core.registered_nodes[n2.name]
-- If it's not air or liquid, remove node and replace it with
-- it's drops
if n2.name ~= "air" and (not nd or nd.liquidtype == "none") then
-- BEGIN MODIFIED SECTION 0 OF FUNCTION
-- Check for area protection before solidifying node.
if not minetest.is_protected(np, "") then
-- END MODIFIED SECTION 0 OF FUNCTION
core.remove_node(np)
if nd and nd.buildable_to == false then
-- Add dropped items
local drops = core.get_node_drops(n2, "")
for _, dropped_item in pairs(drops) do
core.add_item(np, dropped_item)
end
end
-- Run script hook
for _, callback in pairs(core.registered_on_dignodes) do
callback(np, n2)
end
-- BEGIN MODIFIED SECTION 1 OF FUNCTION
end
-- END MODIFIED SECTION 1 OF FUNCTION
end
-- Create node and remove entity
if core.registered_nodes[self.node.name] then
-- BEGIN MODIFIED SECTION 0 OF FUNCTION
-- Check for area protection before solidifying node.
if minetest.is_protected(np, "") then
core.add_item(np, self.node.name)
else
-- END MODIFIED SECTION 0 OF FUNCTION
core.add_node(np, self.node)
if self.meta then
local meta = core.get_meta(np)
meta:from_table(self.meta)
end
-- BEGIN MODIFIED SECTION 1 OF FUNCTION
end
-- END MODIFIED SECTION 1 OF FUNCTION
end
self.object:remove()
core.check_for_falling(np)
return
end
local vel = self.object:getvelocity()
if vector.equals(vel, {x = 0, y = 0, z = 0}) then
local npos = self.object:getpos()
self.object:setpos(vector.round(npos))
end
end
core.register_entity(":__builtin:falling_node", falling_node)

108
fire.lua Normal file
View File

@ -0,0 +1,108 @@
local function ignite(pos, node, active_object_count, active_object_count_wider)
-- If there is water or stuff like that around node, don't ignite
if minetest.find_node_near(pos, 1, {"group:puts_out_fire"})
-- If the flammable node is too close to an unloaded block, we can't
-- properly detect the presence of protected flammable nodes within
-- that block. We'll put off ignition until that block is loaded, at
-- which point this ABM will be likely to be called again soon, seeing
-- as the flammable node and igniter are still present.
or #minetest.find_nodes_in_area({
x = pos.x - 2,
y = pos.y - 2,
z = pos.z - 2,
}, {
x = pos.x + 2,
y = pos.y + 2,
z = pos.z + 2,
}, "ignore") > 0 then
return
end
local p = minetest.find_node_near(pos, 1, {"air"})
if p then
local fuels = minetest.find_nodes_in_area({
x = p.x - 1,
y = p.y - 1,
z = p.z - 1,
}, {
x = p.x + 1,
y = p.y + 1,
z = p.z + 1,
}, {
"group:flammable",
"ignore",
})
local allow_ignition = true
for _, fuel in next, fuels do
if minetest.is_protected(fuel, "") then
allow_ignition = false
end
end
if allow_ignition then
minetest.set_node(p, {name = "fire:basic_flame"})
else
local igniters = minetest.find_nodes_in_area({
x = pos.x - 1,
y = pos.y - 1,
z = pos.z - 1,
}, {
x = pos.x + 1,
y = pos.y + 1,
z = pos.z + 1,
}, "group:igniter")
for _, igniter in next, igniters do
local node = minetest.get_node(igniter)
if minetest.registered_nodes[node.name].liquidtype == "none" then
minetest.remove_node(igniter)
else
default.cool_lava(igniter, node)
end
end
end
end
end
for _, ABM in next, minetest.registered_abms do
if ABM.mod_origin == "fire" and ABM.label == "Ignite flame" then
ABM.action = ignite
end
end
local ignite_using_tool = minetest.registered_tools["fire:flint_and_steel"].on_use
minetest.override_item("fire:flint_and_steel", {
on_use = function(itemstack, user, pointed_thing)
local allow_use = true
local player_name = user:get_player_name()
if pointed_thing.type == "node" then
local node_under = minetest.get_node(pointed_thing.under).name
local nodedef = minetest.registered_nodes[node_under]
if minetest.get_item_group(node_under, "flammable") > 0
and minetest.get_node(pointed_thing.above).name == "air"
and not nodedef.on_ignite then
local fuels = minetest.find_nodes_in_area({
x = pointed_thing.above.x - 1,
y = pointed_thing.above.y - 1,
z = pointed_thing.above.z - 1,
}, {
x = pointed_thing.above.x + 1,
y = pointed_thing.above.y + 1,
z = pointed_thing.above.z + 1,
}, {
"group:flammable",
"ignore",
})
for _, fuel in next, fuels do
if minetest.is_protected(fuel, player_name)
or not minetest.get_node_or_nil(fuel) then
allow_use = false
end
end
end
end
if allow_use then
return ignite_using_tool(itemstack, user, pointed_thing)
else
minetest.chat_send_player(player_name, "This area is protected.")
return itemstack
end
end,
})

View File

@ -3,6 +3,11 @@ local modpath = minetest.get_modpath(minetest.get_current_modname())
dofile(modpath.."/API.lua")
dofile(modpath.."/crafts.lua")
dofile(modpath.."/nodes.lua")
dofile(modpath.."/boundary display.lua")
dofile(modpath.."/falling.lua")
if minetest.get_modpath("fire") then
dofile(modpath.."/fire.lua")
end
if minetest.settings:get_bool("blockprotectnodes.sfinv_page") and minetest.get_modpath("sfinv") then
dofile(modpath.."/sfinv.lua")
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B