{image="default_water.png", backface_culling=false},
{image="default_water.png", backface_culling=true},
},
- groups = {water=3, liquid=3},
+ groups = {water=3, liquid=3, puts_out_fire=1},
})
minetest.register_node("default:water_source", {
-- New-style water source material (mostly unused)
{image="default_water.png", backface_culling=false},
},
- groups = {water=3, liquid=3},
+ groups = {water=3, liquid=3, puts_out_fire=1},
})
minetest.register_node("default:lava_flowing", {
{image="default_lava.png", backface_culling=false},
{image="default_lava.png", backface_culling=true},
},
- groups = {lava=3, liquid=2, hot=3, igniter=3},
+ groups = {lava=3, liquid=2, hot=3, igniter=2},
})
minetest.register_node("default:lava_source", {
-- New-style lava source material (mostly unused)
{image="default_lava.png", backface_culling=false},
},
- groups = {lava=3, liquid=2, hot=3, igniter=3},
+ groups = {lava=3, liquid=2, hot=3, igniter=2},
})
minetest.register_node("default:torch", {
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
},
- groups = {choppy=2,dig_immediate=3},
+ groups = {choppy=2,dig_immediate=3,flammable=1},
legacy_wallmounted = true,
sounds = default.node_sound_defaults(),
})
--- /dev/null
+-- minetest/fire/init.lua
+
+minetest.register_node("fire:basic_flame", {
+ description = "Fire",
+ drawtype = "glasslike",
+ tile_images = {"fire_basic_flame.png"},
+ light_source = 14,
+ groups = {igniter=3,dig_immediate=3},
+ drop = '',
+ walkable = false,
+})
+
+local fire = {}
+fire.D = 6
+-- key: position hash of low corner of area
+-- value: {handle=sound handle, name=sound name}
+fire.sounds = {}
+
+function fire.get_area_p0p1(pos)
+ local p0 = {
+ x=math.floor(pos.x/fire.D)*fire.D,
+ y=math.floor(pos.y/fire.D)*fire.D,
+ z=math.floor(pos.z/fire.D)*fire.D,
+ }
+ local p1 = {
+ x=p0.x+fire.D-1,
+ y=p0.y+fire.D-1,
+ z=p0.z+fire.D-1
+ }
+ return p0, p1
+end
+
+function fire.update_sounds_around(pos)
+ local p0, p1 = fire.get_area_p0p1(pos)
+ local cp = {x=(p0.x+p1.x)/2, y=(p0.y+p1.y)/2, z=(p0.z+p1.z)/2}
+ local flames_p = minetest.env:find_nodes_in_area(p0, p1, {"fire:basic_flame"})
+ --print("number of flames at "..minetest.pos_to_string(p0).."/"
+ -- ..minetest.pos_to_string(p1)..": "..#flames_p)
+ local should_have_sound = (#flames_p > 0)
+ local wanted_sound = nil
+ if #flames_p >= 9 then
+ wanted_sound = {name="fire_large", gain=1.5}
+ elseif #flames_p > 0 then
+ wanted_sound = {name="fire_small", gain=1.5}
+ end
+ local p0_hash = minetest.hash_node_position(p0)
+ local sound = fire.sounds[p0_hash]
+ if not sound then
+ if should_have_sound then
+ fire.sounds[p0_hash] = {
+ handle = minetest.sound_play(wanted_sound, {pos=cp, loop=true}),
+ name = wanted_sound.name,
+ }
+ end
+ else
+ if not wanted_sound then
+ minetest.sound_stop(sound.handle)
+ fire.sounds[p0_hash] = nil
+ elseif sound.name ~= wanted_sound.name then
+ minetest.sound_stop(sound.handle)
+ fire.sounds[p0_hash] = {
+ handle = minetest.sound_play(wanted_sound, {pos=cp, loop=true}),
+ name = wanted_sound.name,
+ }
+ end
+ end
+end
+
+function fire.on_flame_add_at(pos)
+ --print("flame added at "..minetest.pos_to_string(pos))
+ fire.update_sounds_around(pos)
+end
+
+function fire.on_flame_remove_at(pos)
+ --print("flame removed at "..minetest.pos_to_string(pos))
+ fire.update_sounds_around(pos)
+end
+
+function fire.find_pos_for_flame_around(pos)
+ return minetest.env:find_node_near(pos, 1, {"air"})
+end
+
+function fire.flame_should_extinguish(pos)
+ --return minetest.env:find_node_near(pos, 1, {"group:puts_out_fire"})
+ local p0 = {x=pos.x-2, y=pos.y, z=pos.z-2}
+ local p1 = {x=pos.x+2, y=pos.y, z=pos.z+2}
+ local ps = minetest.env:find_nodes_in_area(p0, p1, {"group:puts_out_fire"})
+ return (#ps ~= 0)
+end
+
+minetest.register_on_placenode(function(pos, newnode, placer)
+ if newnode.name == "fire:basic_flame" then
+ fire.on_flame_add_at(pos)
+ end
+end)
+
+minetest.register_on_dignode(function(pos, oldnode, digger)
+ if oldnode.name == "fire:basic_flame" then
+ fire.on_flame_remove_at(pos)
+ end
+end)
+
+-- Ignite neighboring nodes
+minetest.register_abm({
+ nodenames = {"group:flammable"},
+ neighbors = {"group:igniter"},
+ interval = 1,
+ chance = 2,
+ action = function(p0, node, _, _)
+ -- If there is water or stuff like that around flame, don't ignite
+ if fire.flame_should_extinguish(p0) then
+ return
+ end
+ local p = fire.find_pos_for_flame_around(p0)
+ if p then
+ minetest.env:set_node(p, {name="fire:basic_flame"})
+ fire.on_flame_add_at(p)
+ end
+ end,
+})
+
+-- Rarely ignite things from far
+minetest.register_abm({
+ nodenames = {"group:igniter"},
+ neighbors = {"air"},
+ interval = 2,
+ chance = 10,
+ action = function(p0, node, _, _)
+ local reg = minetest.registered_nodes[node.name]
+ if not reg or not reg.groups.igniter or reg.groups.igniter < 2 then
+ return
+ end
+ local d = reg.groups.igniter
+ local p = minetest.env:find_node_near(p0, d, {"group:flammable"})
+ if p then
+ -- If there is water or stuff like that around flame, don't ignite
+ if fire.flame_should_extinguish(p) then
+ return
+ end
+ local p2 = fire.find_pos_for_flame_around(p)
+ if p2 then
+ minetest.env:set_node(p2, {name="fire:basic_flame"})
+ fire.on_flame_add_at(p2)
+ end
+ end
+ end,
+})
+
+-- Remove flammable nodes and flame
+minetest.register_abm({
+ nodenames = {"fire:basic_flame"},
+ interval = 1,
+ chance = 2,
+ action = function(p0, node, _, _)
+ -- If there is water or stuff like that around flame, remove flame
+ if fire.flame_should_extinguish(p0) then
+ minetest.env:remove_node(p0)
+ fire.on_flame_remove_at(p0)
+ return
+ end
+ -- Make the following things rarer
+ if math.random(1,3) == 1 then
+ return
+ end
+ -- If there are no flammable nodes around flame, remove flame
+ if not minetest.env:find_node_near(p0, 1, {"group:flammable"}) then
+ minetest.env:remove_node(p0)
+ fire.on_flame_remove_at(p0)
+ return
+ end
+ if math.random(1,4) == 1 then
+ -- remove a flammable node around flame
+ local p = minetest.env:find_node_near(p0, 1, {"group:flammable"})
+ if p then
+ -- If there is water or stuff like that around flame, don't remove
+ if fire.flame_should_extinguish(p0) then
+ return
+ end
+ minetest.env:remove_node(p)
+ end
+ else
+ -- remove flame
+ minetest.env:remove_node(p0)
+ fire.on_flame_remove_at(p0)
+ end
+ end,
+})
+