Skip to content

Commit

Permalink
TNT: Track TNT owner in metadata for protection mods
Browse files Browse the repository at this point in the history
It is useful for protection mods to know who owns an exploding
TNT block. This allows the blocks destroyed by the TNT to be
limited to the same ones the owner could destroy without using
TNT.

TNT placed within a protected area by the area owner, and later
ignited by another player will destroy within the protected area
nodes the igniter may not otherwise be able to interact with. Any
player could significantly increase the size of an explosion by
placing more TNT in an adjacent unprotected area if the original
TNT block was placed withing 1 node of such a boundary. This
feature sounds dangerous, but we are talking about TNT. Players
should use it carefully.
  • Loading branch information
fozolo authored and paramat committed Jul 2, 2017
1 parent c51ebcb commit 0f7d0bf
Showing 1 changed file with 23 additions and 9 deletions.
32 changes: 23 additions & 9 deletions mods/tnt/init.lua
Expand Up @@ -86,8 +86,8 @@ end
local basic_flame_on_construct -- cached value
local function destroy(drops, npos, cid, c_air, c_fire,
on_blast_queue, on_construct_queue,
ignore_protection, ignore_on_blast)
if not ignore_protection and minetest.is_protected(npos, "") then
ignore_protection, ignore_on_blast, owner)
if not ignore_protection and minetest.is_protected(npos, owner) then
return cid
end

Expand Down Expand Up @@ -266,13 +266,13 @@ function tnt.burn(pos, nodename)
elseif def.on_ignite then
def.on_ignite(pos)
elseif minetest.get_item_group(name, "tnt") > 0 then
minetest.swap_node(pos, {name = name .. "_burning"})
minetest.sound_play("tnt_ignite", {pos = pos})
minetest.set_node(pos, {name = name .. "_burning"})
minetest.get_node_timer(pos):start(1)
end
end

local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast)
local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast, owner)
pos = vector.round(pos)
-- scan for adjacent TNT nodes first, and enlarge the explosion
local vm1 = VoxelManip()
Expand Down Expand Up @@ -333,7 +333,7 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast)
if cid ~= c_air then
data[vi] = destroy(drops, p, cid, c_air, c_fire,
on_blast_queue, on_construct_queue,
ignore_protection, ignore_on_blast)
ignore_protection, ignore_on_blast, owner)
end
end
vi = vi + 1
Expand Down Expand Up @@ -375,14 +375,19 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast)
queued_data.fn(queued_data.pos)
end

minetest.log("action", "TNT owned by " .. owner .. " detonated at " ..
minetest.pos_to_string(pos) .. " with radius " .. radius)

return drops, radius
end

function tnt.boom(pos, def)
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
minetest.sound_play("tnt_explode", {pos = pos, gain = 1.5, max_hear_distance = 2*64})
minetest.set_node(pos, {name = "tnt:boom"})
local drops, radius = tnt_explode(pos, def.radius, def.ignore_protection,
def.ignore_on_blast)
def.ignore_on_blast, owner)
-- append entity drops
local damage_radius = (radius / def.radius) * def.damage_radius
entity_physics(pos, damage_radius, drops)
Expand Down Expand Up @@ -579,9 +584,16 @@ function tnt.register_tnt(def)
is_ground_content = false,
groups = {dig_immediate = 2, mesecon = 2, tnt = 1, flammable = 5},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
if placer:is_player() then
local meta = minetest.get_meta(pos)
meta:set_string("owner", placer:get_player_name())
end
end,
on_punch = function(pos, node, puncher)
if puncher:get_wielded_item():get_name() == "default:torch" then
minetest.set_node(pos, {name = name .. "_burning"})
minetest.swap_node(pos, {name = name .. "_burning"})
minetest.registered_nodes[name .. "_burning"].on_construct(pos)
minetest.log("action", puncher:get_player_name() ..
" ignites " .. node.name .. " at " ..
minetest.pos_to_string(pos))
Expand All @@ -600,10 +612,12 @@ function tnt.register_tnt(def)
}
},
on_burn = function(pos)
minetest.set_node(pos, {name = name .. "_burning"})
minetest.swap_node(pos, {name = name .. "_burning"})
minetest.registered_nodes[name .. "_burning"].on_construct(pos)
end,
on_ignite = function(pos, igniter)
minetest.set_node(pos, {name = name .. "_burning"})
minetest.swap_node(pos, {name = name .. "_burning"})
minetest.registered_nodes[name .. "_burning"].on_construct(pos)
end,
})
end
Expand Down

0 comments on commit 0f7d0bf

Please sign in to comment.