diff --git a/game_api.txt b/game_api.txt
index 9c576947..c4250d50 100644
--- a/game_api.txt
+++ b/game_api.txt
@@ -599,6 +599,18 @@ Both nodedefs and entitydefs can provide an `on_blast()` callback
 * `drops` - a list of drops, e.g. {"wool:red"}
 
 
+Node drops:
+
+When a node is detonated it is removed according to the following rules.
+1. If `on_blast` is defined, that is called.
+2. Else if the node has group `flammable` it is replaced with a fire node.
+3. Else the dropped items are retrieved and it is replaced with air.
+
+The parameter `_tnt_loss` in any item definition can be set to a number to
+effect that "one in X" of these drops will be lost during an explosion.
+For example `_tnt_loss = 2` would cause 50% of items to disappear.
+The default is to not lose any items, which is equivalent to `_tnt_loss = 0`.
+
 Screwdriver API
 ---------------
 
diff --git a/mods/default/nodes.lua b/mods/default/nodes.lua
index 2bde6f8e..8537d9e8 100644
--- a/mods/default/nodes.lua
+++ b/mods/default/nodes.lua
@@ -271,6 +271,7 @@ minetest.register_node("default:cobble", {
 	is_ground_content = false,
 	groups = {cracky = 3, stone = 2},
 	sounds = default.node_sound_stone_defaults(),
+	_tnt_loss = 4,
 })
 
 minetest.register_node("default:stonebrick", {
@@ -297,9 +298,9 @@ minetest.register_node("default:mossycobble", {
 	is_ground_content = false,
 	groups = {cracky = 3, stone = 1},
 	sounds = default.node_sound_stone_defaults(),
+	_tnt_loss = 4,
 })
 
-
 minetest.register_node("default:desert_stone", {
 	description = S("Desert Stone"),
 	tiles = {"default_desert_stone.png"},
@@ -315,6 +316,7 @@ minetest.register_node("default:desert_cobble", {
 	is_ground_content = false,
 	groups = {cracky = 3, stone = 2},
 	sounds = default.node_sound_stone_defaults(),
+	_tnt_loss = 4,
 })
 
 minetest.register_node("default:desert_stonebrick", {
@@ -444,6 +446,7 @@ minetest.register_node("default:dirt", {
 	tiles = {"default_dirt.png"},
 	groups = {crumbly = 3, soil = 1},
 	sounds = default.node_sound_dirt_defaults(),
+	_tnt_loss = 3,
 })
 
 minetest.register_node("default:dirt_with_grass", {
@@ -530,6 +533,7 @@ minetest.register_node("default:dry_dirt", {
 	tiles = {"default_dry_dirt.png"},
 	groups = {crumbly = 3, soil = 1},
 	sounds = default.node_sound_dirt_defaults(),
+	_tnt_loss = 3,
 })
 
 minetest.register_node("default:dry_dirt_with_dry_grass", {
@@ -576,6 +580,7 @@ minetest.register_node("default:sand", {
 	tiles = {"default_sand.png"},
 	groups = {crumbly = 3, falling_node = 1, sand = 1},
 	sounds = default.node_sound_sand_defaults(),
+	_tnt_loss = 2,
 })
 
 minetest.register_node("default:desert_sand", {
@@ -583,6 +588,7 @@ minetest.register_node("default:desert_sand", {
 	tiles = {"default_desert_sand.png"},
 	groups = {crumbly = 3, falling_node = 1, sand = 1},
 	sounds = default.node_sound_sand_defaults(),
+	_tnt_loss = 2,
 })
 
 minetest.register_node("default:silver_sand", {
@@ -590,6 +596,7 @@ minetest.register_node("default:silver_sand", {
 	tiles = {"default_silver_sand.png"},
 	groups = {crumbly = 3, falling_node = 1, sand = 1},
 	sounds = default.node_sound_sand_defaults(),
+	_tnt_loss = 2,
 })
 
 
@@ -604,7 +611,8 @@ minetest.register_node("default:gravel", {
 			{items = {"default:flint"}, rarity = 16},
 			{items = {"default:gravel"}}
 		}
-	}
+	},
+	_tnt_loss = 3,
 })
 
 minetest.register_node("default:clay", {
@@ -639,6 +647,7 @@ minetest.register_node("default:snow", {
 	},
 	groups = {crumbly = 3, falling_node = 1, snowy = 1},
 	sounds = default.node_sound_snow_defaults(),
+	_tnt_loss = 1, -- means it will disappear entirely
 
 	on_construct = function(pos)
 		pos.y = pos.y - 1
@@ -2807,6 +2816,7 @@ minetest.register_node("default:glass", {
 	is_ground_content = false,
 	groups = {cracky = 3, oddly_breakable_by_hand = 3},
 	sounds = default.node_sound_glass_defaults(),
+	_tnt_loss = 2,
 })
 
 minetest.register_node("default:obsidian_glass", {
diff --git a/mods/tnt/init.lua b/mods/tnt/init.lua
index 05f01e3d..4acbdaa9 100644
--- a/mods/tnt/init.lua
+++ b/mods/tnt/init.lua
@@ -12,12 +12,6 @@ if enable_tnt == nil then
 	enable_tnt = minetest.is_singleplayer()
 end
 
--- loss probabilities array (one in X will be lost)
-local loss_prob = {}
-
-loss_prob["default:cobble"] = 3
-loss_prob["default:dirt"] = 4
-
 local tnt_radius = tonumber(minetest.settings:get("tnt_radius") or 3)
 
 -- Fill a list with data for content IDs, after all nodes are registered
@@ -27,7 +21,7 @@ minetest.register_on_mods_loaded(function()
 		cid_data[minetest.get_content_id(name)] = {
 			name = name,
 			drops = def.drops,
-			flammable = def.groups.flammable,
+			flammable = def.groups and (def.groups.flammable or 0) ~= 0,
 			on_blast = def.on_blast,
 		}
 	end
@@ -76,11 +70,14 @@ end
 
 local function add_drop(drops, item)
 	item = ItemStack(item)
-	local name = item:get_name()
-	if loss_prob[name] ~= nil and math.random(1, loss_prob[name]) == 1 then
+	-- Note that this needs to be set on the dropped item, not the node.
+	-- Value represents "one in X will be lost"
+	local lost = item:get_definition()._tnt_loss or 0
+	if lost > 0 and (lost == 1 or math.random(1, lost) == 1) then
 		return
 	end
 
+	local name = item:get_name()
 	local drop = drops[name]
 	if drop == nil then
 		drops[name] = item