Protect against fire and falling "node" entities
parent
85a0154607
commit
462070c334
|
@ -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,
|
||||
})
|
|
@ -1,2 +1,3 @@
|
|||
default
|
||||
fire?
|
||||
sfinv?
|
||||
|
|
|
@ -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)
|
|
@ -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,
|
||||
})
|
5
init.lua
5
init.lua
|
@ -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 |
Loading…
Reference in New Issue