1
1
-- minetest/fire/init.lua
2
2
3
+ -- Global namespace for functions
4
+
3
5
fire = {}
4
6
7
+
8
+ -- Register flame node
9
+
5
10
minetest .register_node (" fire:basic_flame" , {
6
11
description = " Fire" ,
7
12
drawtype = " firelike" ,
8
13
tiles = {{
9
- name = " fire_basic_flame_animated.png" ,
10
- animation = {type = " vertical_frames" , aspect_w = 16 , aspect_h = 16 , length = 1 },
14
+ name = " fire_basic_flame_animated.png" ,
15
+ animation = {type = " vertical_frames" ,
16
+ aspect_w = 16 , aspect_h = 16 , length = 1 },
11
17
}},
12
18
inventory_image = " fire_basic_flame.png" ,
13
19
light_source = 14 ,
14
- groups = {igniter = 2 , dig_immediate = 3 },
20
+ groups = {igniter = 2 , dig_immediate = 3 },
15
21
drop = ' ' ,
16
22
walkable = false ,
17
23
buildable_to = true ,
@@ -29,44 +35,55 @@ minetest.register_node("fire:basic_flame", {
29
35
on_blast = function () end ,
30
36
})
31
37
32
- fire .D = 6
38
+
39
+ -- Fire sounds table
33
40
-- key: position hash of low corner of area
34
41
-- value: {handle=sound handle, name=sound name}
35
42
fire .sounds = {}
36
43
44
+
45
+ -- Get sound area of position
46
+
47
+ -- size of sound areas
48
+ fire .D = 6
49
+
37
50
function fire .get_area_p0p1 (pos )
38
51
local p0 = {
39
- x = math.floor (pos .x / fire .D )* fire .D ,
40
- y = math.floor (pos .y / fire .D )* fire .D ,
41
- z = math.floor (pos .z / fire .D )* fire .D ,
52
+ x = math.floor (pos .x / fire .D ) * fire .D ,
53
+ y = math.floor (pos .y / fire .D ) * fire .D ,
54
+ z = math.floor (pos .z / fire .D ) * fire .D ,
42
55
}
43
56
local p1 = {
44
- x = p0 .x + fire .D - 1 ,
45
- y = p0 .y + fire .D - 1 ,
46
- z = p0 .z + fire .D - 1
57
+ x = p0 .x + fire .D - 1 ,
58
+ y = p0 .y + fire .D - 1 ,
59
+ z = p0 .z + fire .D - 1
47
60
}
48
61
return p0 , p1
49
62
end
50
63
64
+
65
+ -- Update fire sounds in sound area of position
66
+
51
67
function fire .update_sounds_around (pos )
52
68
local p0 , p1 = fire .get_area_p0p1 (pos )
53
- local cp = {x = (p0 .x + p1 .x )/ 2 , y = (p0 .y + p1 .y )/ 2 , z = (p0 .z + p1 .z )/ 2 }
69
+ local cp = {x = (p0 .x + p1 .x ) / 2 , y = (p0 .y + p1 .y ) / 2 , z = (p0 .z + p1 .z ) / 2 }
54
70
local flames_p = minetest .find_nodes_in_area (p0 , p1 , {" fire:basic_flame" })
55
71
-- print("number of flames at "..minetest.pos_to_string(p0).."/"
56
72
-- ..minetest.pos_to_string(p1)..": "..#flames_p)
57
73
local should_have_sound = (# flames_p > 0 )
58
74
local wanted_sound = nil
59
75
if # flames_p >= 9 then
60
- wanted_sound = {name = " fire_large" , gain = 1.5 }
76
+ wanted_sound = {name = " fire_large" , gain = 1.5 }
61
77
elseif # flames_p > 0 then
62
- wanted_sound = {name = " fire_small" , gain = 1.5 }
78
+ wanted_sound = {name = " fire_small" , gain = 1.5 }
63
79
end
64
80
local p0_hash = minetest .hash_node_position (p0 )
65
81
local sound = fire .sounds [p0_hash ]
66
82
if not sound then
67
83
if should_have_sound then
68
84
fire .sounds [p0_hash ] = {
69
- handle = minetest .sound_play (wanted_sound , {pos = cp , max_hear_distance = 16 , loop = true }),
85
+ handle = minetest .sound_play (wanted_sound ,
86
+ {pos = cp , max_hear_distance = 16 , loop = true }),
70
87
name = wanted_sound .name ,
71
88
}
72
89
end
@@ -77,53 +94,71 @@ function fire.update_sounds_around(pos)
77
94
elseif sound .name ~= wanted_sound .name then
78
95
minetest .sound_stop (sound .handle )
79
96
fire .sounds [p0_hash ] = {
80
- handle = minetest .sound_play (wanted_sound , {pos = cp , max_hear_distance = 16 , loop = true }),
97
+ handle = minetest .sound_play (wanted_sound ,
98
+ {pos = cp , max_hear_distance = 16 , loop = true }),
81
99
name = wanted_sound .name ,
82
100
}
83
101
end
84
102
end
85
103
end
86
104
105
+
106
+ -- Update fire sounds on flame node construct or destruct
107
+
87
108
function fire .on_flame_add_at (pos )
88
109
fire .update_sounds_around (pos )
89
110
end
90
111
112
+
91
113
function fire .on_flame_remove_at (pos )
92
114
fire .update_sounds_around (pos )
93
115
end
94
116
117
+
118
+ -- Return positions for flames around a burning node
119
+
95
120
function fire .find_pos_for_flame_around (pos )
96
121
return minetest .find_node_near (pos , 1 , {" air" })
97
122
end
98
123
124
+
125
+ -- Detect nearby extinguishing nodes
126
+
99
127
function fire .flame_should_extinguish (pos )
100
128
if minetest .setting_getbool (" disable_fire" ) then return true end
101
129
-- return minetest.find_node_near(pos, 1, {"group:puts_out_fire"})
102
- local p0 = {x = pos .x - 2 , y = pos .y , z = pos .z - 2 }
103
- local p1 = {x = pos .x + 2 , y = pos .y , z = pos .z + 2 }
130
+ local p0 = {x = pos .x - 1 , y = pos .y , z = pos .z - 1 }
131
+ local p1 = {x = pos .x + 1 , y = pos .y + 1 , z = pos .z + 1 }
104
132
local ps = minetest .find_nodes_in_area (p0 , p1 , {" group:puts_out_fire" })
105
133
return (# ps ~= 0 )
106
134
end
107
135
136
+
108
137
-- Ignite neighboring nodes
138
+
109
139
minetest .register_abm ({
110
140
nodenames = {" group:flammable" },
111
141
neighbors = {" group:igniter" },
112
- interval = 5 ,
113
- chance = 2 ,
142
+ interval = 7 ,
143
+ chance = 32 ,
114
144
action = function (p0 , node , _ , _ )
115
145
-- If there is water or stuff like that around flame, don't ignite
116
146
if fire .flame_should_extinguish (p0 ) then
117
147
return
118
148
end
119
149
local p = fire .find_pos_for_flame_around (p0 )
120
150
if p then
121
- minetest .set_node (p , {name = " fire:basic_flame" })
151
+ minetest .set_node (p , {name = " fire:basic_flame" })
122
152
end
123
153
end ,
124
154
})
125
155
156
+
126
157
-- Rarely ignite things from far
158
+
159
+ --[[ Currently disabled to reduce the chance of uncontrollable spreading
160
+ fires that disrupt servers. Also for less lua processing load.
161
+
127
162
minetest.register_abm({
128
163
nodenames = {"group:igniter"},
129
164
neighbors = {"air"},
@@ -143,33 +178,36 @@ minetest.register_abm({
143
178
end
144
179
local p2 = fire.find_pos_for_flame_around(p)
145
180
if p2 then
146
- minetest .set_node (p2 , {name = " fire:basic_flame" })
181
+ minetest.set_node(p2, {name = "fire:basic_flame"})
147
182
end
148
183
end
149
184
end,
150
185
})
186
+ --]]
187
+
151
188
152
189
-- Remove flammable nodes and flame
190
+
153
191
minetest .register_abm ({
154
192
nodenames = {" fire:basic_flame" },
155
- interval = 3 ,
156
- chance = 2 ,
193
+ interval = 5 ,
194
+ chance = 16 ,
157
195
action = function (p0 , node , _ , _ )
158
196
-- If there is water or stuff like that around flame, remove flame
159
197
if fire .flame_should_extinguish (p0 ) then
160
198
minetest .remove_node (p0 )
161
199
return
162
200
end
163
201
-- Make the following things rarer
164
- if math.random (1 ,3 ) == 1 then
202
+ if math.random (1 , 3 ) == 1 then
165
203
return
166
204
end
167
205
-- If there are no flammable nodes around flame, remove flame
168
206
if not minetest .find_node_near (p0 , 1 , {" group:flammable" }) then
169
207
minetest .remove_node (p0 )
170
208
return
171
209
end
172
- if math.random (1 ,4 ) == 1 then
210
+ if math.random (1 , 4 ) == 1 then
173
211
-- remove a flammable node around flame
174
212
local p = minetest .find_node_near (p0 , 1 , {" group:flammable" })
175
213
if p then
0 commit comments