Clean up some node groups
[minetest_tutorial_subgame.git] / mods / default / nodes.lua
blobfcad369af0a4175d4a0cceba0eaf699be10dc32e
1 -- mods/default/nodes.lua
3 -- intllib support
4 local S, F
5 if (minetest.get_modpath("intllib")) then
6 S = intllib.Getter()
7 F = function( s )
8 return minetest.formspec_escape(S(s))
9 end
10 else
11 S = function ( s ) return s end
12 F = function ( s ) return minetest.formspec_escape(s) end
13 end
15 minetest.register_node("default:stone", {
16 description = S("stone"),
17 tiles = {"default_stone.png"},
18 is_ground_content = true,
19 groups = {cracky=3, stone=1},
20 drop = 'default:cobble',
21 legacy_mineral = true,
22 sounds = default.node_sound_stone_defaults(),
25 minetest.register_node("default:stone_with_coal", {
26 description = S("coal ore"),
27 tiles = {"default_stone.png^default_mineral_coal.png"},
28 is_ground_content = true,
29 groups = {cracky=3},
30 drop = 'default:coal_lump',
31 sounds = default.node_sound_stone_defaults(),
34 minetest.register_node("default:stone_with_iron", {
35 description = S("iron ore"),
36 tiles = {"default_stone.png^default_mineral_iron.png"},
37 is_ground_content = true,
38 groups = {cracky=2},
39 drop = 'default:iron_lump',
40 sounds = default.node_sound_stone_defaults(),
43 minetest.register_node("default:stone_with_gold", {
44 description = S("gold ore"),
45 tiles = {"default_stone.png^default_mineral_gold.png"},
46 is_ground_content = true,
47 groups = {cracky=2},
48 drop = "default:gold_lump",
49 sounds = default.node_sound_stone_defaults(),
52 minetest.register_node("default:stone_with_diamond", {
53 description = S("diamond ore"),
54 tiles = {"default_stone.png^default_mineral_diamond.png"},
55 is_ground_content = true,
56 groups = {cracky=1},
57 drop = "default:diamond",
58 sounds = default.node_sound_stone_defaults(),
61 minetest.register_node("default:dirt_with_grass", {
62 description = S("dirt with grass"),
63 tiles = {"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
64 is_ground_content = true,
65 groups = {immortal=1},
66 drop = 'default:dirt',
67 sounds = default.node_sound_dirt_defaults({
68 footstep = {name="default_grass_footstep", gain=0.25},
69 }),
72 minetest.register_node("default:dirt", {
73 description = S("dirt"),
74 tiles = {"default_dirt.png"},
75 is_ground_content = true,
76 groups = {immortal=1},
77 sounds = default.node_sound_dirt_defaults(),
80 minetest.register_node("default:sand", {
81 description = S("sand"),
82 tiles = {"default_sand.png"},
83 is_ground_content = true,
84 groups = {crumbly=3, falling_node=1, sand=1},
85 sounds = default.node_sound_sand_defaults(),
88 minetest.register_node("default:tree", {
89 description = S("tree trunk"),
90 tiles = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"},
91 paramtype2 = "facedir",
92 is_ground_content = false,
93 groups = {immortal=1},
94 sounds = default.node_sound_wood_defaults(),
95 on_place = minetest.rotate_node
98 minetest.register_node("default:leaves", {
99 description = S("leaves"),
100 drawtype = "allfaces_optional",
101 waving = 1,
102 visual_scale = 1.3,
103 tiles = {"default_leaves.png"},
104 paramtype = "light",
105 is_ground_content = false,
106 groups = {immortal=1},
107 drop = {
108 max_items = 1,
109 items = {
111 -- player will get sapling with 1/20 chance
112 items = {'default:sapling'},
113 rarity = 20,
116 -- player will get leaves only if he get no saplings,
117 -- this is because max_items is 1
118 items = {'default:leaves'},
122 sounds = default.node_sound_leaves_defaults(),
125 minetest.register_node("default:ladder", {
126 description = S("ladder"),
127 drawtype = "signlike",
128 tiles = {"default_ladder.png"},
129 inventory_image = "default_ladder.png",
130 wield_image = "default_ladder.png",
131 paramtype = "light",
132 paramtype2 = "wallmounted",
133 walkable = false,
134 climbable = true,
135 is_ground_content = false,
136 selection_box = {
137 type = "wallmounted",
139 groups = {},
140 legacy_wallmounted = true,
141 sounds = default.node_sound_wood_defaults(),
144 minetest.register_node("default:wood", {
145 description = S("wooden planks"),
146 tiles = {"default_wood.png"},
147 groups = {choppy=2,wood=1},
148 sounds = default.node_sound_wood_defaults(),
151 minetest.register_node("default:water_flowing", {
152 description = S("flowing water"),
153 inventory_image = minetest.inventorycube("default_water.png"),
154 drawtype = "flowingliquid",
155 tiles = {"default_water.png"},
156 special_tiles = {
158 image="default_water_flowing_animated.png",
159 backface_culling=false,
160 animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.8}
163 image="default_water_flowing_animated.png",
164 backface_culling=true,
165 animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.8}
168 alpha = WATER_ALPHA,
169 paramtype = "light",
170 paramtype2 = "flowingliquid",
171 walkable = false,
172 pointable = false,
173 diggable = false,
174 buildable_to = true,
175 drop = "",
176 drowning = 1,
177 liquidtype = "flowing",
178 liquid_alternative_flowing = "default:water_flowing",
179 liquid_alternative_source = "default:water_source",
180 liquid_viscosity = WATER_VISC,
181 post_effect_color = {a=64, r=100, g=100, b=200},
182 groups = {water=3, liquid=3, puts_out_fire=1, not_in_creative_inventory=1, freezes=1, melt_around=1},
185 minetest.register_node("default:water_source", {
186 description = S("water source"),
187 inventory_image = minetest.inventorycube("default_water.png"),
188 drawtype = "liquid",
189 tiles = {
190 {name="default_water_source_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}}
192 special_tiles = {
193 -- New-style water source material (mostly unused)
195 name="default_water_source_animated.png",
196 animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0},
197 backface_culling = false,
200 alpha = WATER_ALPHA,
201 paramtype = "light",
202 walkable = false,
203 pointable = false,
204 diggable = false,
205 buildable_to = true,
206 drop = "",
207 drowning = 1,
208 liquidtype = "source",
209 liquid_alternative_flowing = "default:water_flowing",
210 liquid_alternative_source = "default:water_source",
211 liquid_viscosity = WATER_VISC,
212 post_effect_color = {a=64, r=100, g=100, b=200},
213 groups = {water=3, liquid=3, puts_out_fire=1, freezes=1},
216 minetest.register_node("default:torch", {
217 description = S("torch"),
218 drawtype = "torchlike",
219 --tiles = {"default_torch_on_floor.png", "default_torch_on_ceiling.png", "default_torch.png"},
220 tiles = {
221 {name="default_torch_on_floor_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}},
222 {name="default_torch_on_ceiling_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}},
223 {name="default_torch_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}}
225 inventory_image = "default_torch_on_floor.png",
226 wield_image = "default_torch_on_floor.png",
227 paramtype = "light",
228 paramtype2 = "wallmounted",
229 sunlight_propagates = true,
230 is_ground_content = false,
231 walkable = false,
232 light_source = LIGHT_MAX-1,
233 selection_box = {
234 type = "wallmounted",
235 wall_top = {-0.1, 0.5-0.6, -0.1, 0.1, 0.5, 0.1},
236 wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
237 wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
239 groups = {immortal = 1},
240 legacy_wallmounted = true,
241 sounds = default.node_sound_defaults(),
244 function default.chest_formspec()
245 return
246 "size[8,10.6]"..
247 default.gui_bg..
248 default.gui_bg_img..
249 default.gui_slots..
250 "label[0,-0.2;"..minetest.formspec_escape(S("Chest inventory:")).."]"..
251 "list[current_name;main;0,0.3;8,4;]"..
252 "label[0,4.35;"..minetest.formspec_escape(S("Player inventory:")).."]"..
253 "list[current_player;main;0,4.85;8,1;]"..
254 "list[current_player;main;0,6.08;8,3;8]"..
255 "listring[current_name;main]"..
256 "listring[current_player;main]"..
257 "label[0,9.1;"..default.gui_controls.."]"..
258 default.get_hotbar_bg(0,4.85)
261 minetest.register_node("default:chest", {
262 description = S("storage chest"),
263 tiles = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
264 "default_chest_side.png", "default_chest_side.png", "default_chest_front.png"},
265 paramtype2 = "facedir",
266 groups = {immortal=1},
267 legacy_facedir_simple = true,
268 is_ground_content = false,
269 sounds = default.node_sound_wood_defaults(),
270 on_construct = function(pos)
271 local meta = minetest.get_meta(pos)
272 meta:set_string("formspec", default.chest_formspec())
273 meta:set_string("infotext", S("Chest (Rightclick to open)"))
274 local inv = meta:get_inventory()
275 inv:set_size("main", 8*4)
276 end,
277 can_dig = function(pos,player)
278 local meta = minetest.get_meta(pos);
279 local inv = meta:get_inventory()
280 return inv:is_empty("main")
281 end,
282 on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
283 minetest.log("action", player:get_player_name()..
284 " moves stuff in chest at "..minetest.pos_to_string(pos))
285 end,
286 on_metadata_inventory_put = function(pos, listname, index, stack, player)
287 minetest.log("action", player:get_player_name()..
288 " moves stuff to chest at "..minetest.pos_to_string(pos))
289 end,
290 on_metadata_inventory_take = function(pos, listname, index, stack, player)
291 minetest.log("action", player:get_player_name()..
292 " takes stuff from chest at "..minetest.pos_to_string(pos))
293 end,
296 function default.furnace_active(pos, percent, item_percent)
297 local formspec =
298 "size[8,9.8]"..
299 default.gui_bg..
300 default.gui_bg_img..
301 default.gui_slots..
302 "label[-0.1,-0.3;"..minetest.formspec_escape(S("This furnace is active and constantly burning its fuel.")).."]"..
303 "label[2.25,0.1;"..minetest.formspec_escape(S("Source:")).."]"..
304 "list[current_name;src;2.25,0.5;1,1;]"..
305 "label[2.25,2.5;"..minetest.formspec_escape(S("Fuel:")).."]"..
306 "list[current_name;fuel;2.25,2.9;1,1;]"..
307 "label[2.25,1.3;"..minetest.formspec_escape(S("Flame:")).."]"..
308 "image[2.25,1.7;1,1;default_furnace_fire_bg.png^[lowpart:"..
309 (100-percent)..":default_furnace_fire_fg.png]"..
310 "label[3.75,1.3;"..minetest.formspec_escape(S("Progress:")).."]"..
311 "image[3.75,1.7;1,1;gui_furnace_arrow_bg.png^[lowpart:"..
312 (item_percent*100)..":gui_furnace_arrow_fg.png^[transformR270]"..
313 "label[5.75,0.70;"..minetest.formspec_escape(S("Output slots:")).."]"..
314 "list[current_name;dst;5.75,1.16;2,2;]"..
315 "label[0,3.75;"..minetest.formspec_escape(S("Player inventory:")).."]"..
316 "list[current_player;main;0,4.25;8,1;]"..
317 "list[current_player;main;0,5.5;8,3;8]"..
318 "listring[current_name;dst]"..
319 "listring[current_player;main]"..
320 "listring[current_name;src]"..
321 "listring[current_player;main]"..
322 "label[0,8.5;"..default.gui_controls.."]"..
323 default.get_hotbar_bg(0,4.25)
324 return formspec
327 function default.get_furnace_active_formspec(pos, percent)
328 local meta = minetest.get_meta(pos)local inv = meta:get_inventory()
329 local srclist = inv:get_list("src")
330 local cooked = nil
331 local aftercooked = nil
332 if srclist then
333 cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
335 local item_percent = 0
336 if cooked then
337 item_percent = meta:get_float("src_time")/cooked.time
340 return default.furnace_active(pos, percent, item_percent)
343 default.furnace_inactive_formspec =
344 "size[8,9.8]"..
345 default.gui_bg..
346 default.gui_bg_img..
347 default.gui_slots..
348 "label[-0.1,-0.3;"..minetest.formspec_escape(S("This furnace is inactive. Please read the sign above.")).."]"..
349 "label[2.25,0.1;"..minetest.formspec_escape(S("Source:")).."]"..
350 "list[current_name;src;2.25,0.5;1,1;]"..
351 "label[2.25,2.5;"..minetest.formspec_escape(S("Fuel:")).."]"..
352 "list[current_name;fuel;2.25,2.9;1,1;]"..
353 "label[2.25,1.3;"..minetest.formspec_escape(S("Flame:")).."]"..
354 "image[2.25,1.7;1,1;default_furnace_fire_bg.png]"..
355 "label[3.75,1.3;"..minetest.formspec_escape(S("Progress:")).."]"..
356 "image[3.75,1.7;1,1;gui_furnace_arrow_bg.png^[transformR270]"..
357 "label[5.75,0.70;"..minetest.formspec_escape(S("Output slots:")).."]"..
358 "list[current_name;dst;5.75,1.16;2,2;]"..
359 "label[0,3.75;"..minetest.formspec_escape(S("Player inventory:")).."]"..
360 "list[current_player;main;0,4.25;8,1;]"..
361 "list[current_player;main;0,5.5;8,3;8]"..
362 "listring[current_name;dst]"..
363 "listring[current_player;main]"..
364 "listring[current_name;src]"..
365 "listring[current_player;main]"..
366 "label[0,8.5;"..default.gui_controls.."]"..
367 default.get_hotbar_bg(0,4.25)
369 minetest.register_node("default:furnace", {
370 description = S("furnace"),
371 tiles = {"default_furnace_top.png", "default_furnace_bottom.png", "default_furnace_side.png",
372 "default_furnace_side.png", "default_furnace_side.png", "default_furnace_front.png"},
373 paramtype2 = "facedir",
374 groups = {immortal=1},
375 legacy_facedir_simple = true,
376 is_ground_content = false,
377 sounds = default.node_sound_stone_defaults(),
378 on_construct = function(pos)
379 local meta = minetest.get_meta(pos)
380 meta:set_string("formspec", default.furnace_inactive_formspec)
381 meta:set_string("infotext", S("Inactive furnace (Rightclick to examine)"))
382 local inv = meta:get_inventory()
383 inv:set_size("fuel", 1)
384 inv:set_size("src", 1)
385 inv:set_size("dst", 4)
386 end,
387 can_dig = function(pos,player)
388 local meta = minetest.get_meta(pos);
389 local inv = meta:get_inventory()
390 if not inv:is_empty("fuel") then
391 return false
392 elseif not inv:is_empty("dst") then
393 return false
394 elseif not inv:is_empty("src") then
395 return false
397 return true
398 end,
399 allow_metadata_inventory_put = function(pos, listname, index, stack, player)
400 if minetest.is_protected(pos, player:get_player_name()) then
401 return 0
403 local meta = minetest.get_meta(pos)
404 local inv = meta:get_inventory()
405 if listname == "fuel" then
406 if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
407 if inv:is_empty("src") then
408 meta:set_string("infotext",S("Empty furnace (Rightclick to examine)"))
410 return stack:get_count()
411 else
412 return 0
414 elseif listname == "src" then
415 return stack:get_count()
416 elseif listname == "dst" then
417 return 0
419 end,
420 allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
421 if minetest.is_protected(pos, player:get_player_name()) then
422 return 0
424 local meta = minetest.get_meta(pos)
425 local inv = meta:get_inventory()
426 local stack = inv:get_stack(from_list, from_index)
427 if to_list == "fuel" then
428 if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
429 if inv:is_empty("src") then
430 meta:set_string("infotext",S("Empty furnace (Rightclick to examine)"))
432 return count
433 else
434 return 0
436 elseif to_list == "src" then
437 return count
438 elseif to_list == "dst" then
439 return 0
441 end,
442 allow_metadata_inventory_take = function(pos, listname, index, stack, player)
443 if minetest.is_protected(pos, player:get_player_name()) then
444 return 0
446 return stack:get_count()
447 end,
450 minetest.register_node("default:furnace_active", {
451 description = S("furnace"),
452 tiles = {
453 "default_furnace_top.png",
454 "default_furnace_bottom.png",
455 "default_furnace_side.png",
456 "default_furnace_side.png",
457 "default_furnace_side.png",
459 image = "default_furnace_front_active.png",
460 backface_culling = false,
461 animation = {
462 type = "vertical_frames",
463 aspect_w = 16,
464 aspect_h = 16,
465 length = 1.5
469 paramtype2 = "facedir",
470 light_source = 8,
471 drop = "default:furnace",
472 groups = {immortal=1,not_in_creative_inventory=1,hot=1},
473 legacy_facedir_simple = true,
474 is_ground_content = false,
475 sounds = default.node_sound_stone_defaults(),
476 on_construct = function(pos)
477 local meta = minetest.get_meta(pos)
478 meta:set_string("formspec", default.furnace_inactive_formspec)
479 meta:set_string("infotext", S("Inactive furnace (Rightclick to examine)"));
480 local inv = meta:get_inventory()
481 inv:set_size("fuel", 1)
482 inv:set_size("src", 1)
483 inv:set_size("dst", 4)
484 end,
485 can_dig = function(pos,player)
486 local meta = minetest.get_meta(pos);
487 local inv = meta:get_inventory()
488 if not inv:is_empty("fuel") then
489 return false
490 elseif not inv:is_empty("dst") then
491 return false
492 elseif not inv:is_empty("src") then
493 return false
495 return true
496 end,
497 allow_metadata_inventory_put = function(pos, listname, index, stack, player)
498 if minetest.is_protected(pos, player:get_player_name()) then
499 return 0
501 local meta = minetest.get_meta(pos)
502 local inv = meta:get_inventory()
503 if listname == "fuel" then
504 if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
505 if inv:is_empty("src") then
506 meta:set_string("infotext",S("Empty furnace (Rightclick to examine)"))
508 return stack:get_count()
509 else
510 return 0
512 elseif listname == "src" then
513 return stack:get_count()
514 elseif listname == "dst" then
515 return 0
517 end,
518 allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
519 if minetest.is_protected(pos, player:get_player_name()) then
520 return 0
522 local meta = minetest.get_meta(pos)
523 local inv = meta:get_inventory()
524 local stack = inv:get_stack(from_list, from_index)
525 if to_list == "fuel" then
526 if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
527 if inv:is_empty("src") then
528 meta:set_string("infotext",S("Empty furnace (Rightclick to examine)"))
530 return count
531 else
532 return 0
534 elseif to_list == "src" then
535 return count
536 elseif to_list == "dst" then
537 return 0
539 end,
540 allow_metadata_inventory_take = function(pos, listname, index, stack, player)
541 if minetest.is_protected(pos, player:get_player_name()) then
542 return 0
544 return stack:get_count()
545 end,
548 local function swap_node(pos,name)
549 local node = minetest.get_node(pos)
550 if node.name == name then
551 return
553 node.name = name
554 minetest.swap_node(pos,node)
557 minetest.register_abm({
558 nodenames = {"default:chest"},
559 interval = 5,
560 chance = 1,
561 action = function(pos,node,active_object_count, active_object_count_wider)
562 local meta = minetest.get_meta(pos)
563 meta:set_string("formspec", default.chest_formspec())
564 meta:set_string("infotext", S("Chest (Rightclick to open)"))
568 minetest.register_abm({
569 nodenames = {"default:furnace","default:furnace_active"},
570 interval = 1.0,
571 chance = 1,
572 action = function(pos, node, active_object_count, active_object_count_wider)
573 local meta = minetest.get_meta(pos)
574 for i, name in ipairs({
575 "fuel_totaltime",
576 "fuel_time",
577 "src_totaltime",
578 "src_time"
579 }) do
580 if meta:get_string(name) == "" then
581 meta:set_float(name, 0.0)
585 local inv = meta:get_inventory()
587 local srclist = inv:get_list("src")
588 local cooked = nil
589 local aftercooked
591 if srclist then
592 cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
595 local was_active = false
597 if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
598 was_active = true
599 meta:set_float("fuel_time", meta:get_float("fuel_time") + 1)
600 meta:set_float("src_time", meta:get_float("src_time") + 1)
601 if cooked and cooked.item and meta:get_float("src_time") >= cooked.time then
602 -- check if there's room for output in "dst" list
603 if inv:room_for_item("dst",cooked.item) then
604 -- Put result in "dst" list
605 inv:add_item("dst", cooked.item)
606 -- take stuff from "src" list
607 inv:set_stack("src", 1, aftercooked.items[1])
608 else
609 --print("Could not insert '"..cooked.item:to_string().."'")
611 meta:set_string("src_time", 0)
615 if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
616 local percent = math.floor(meta:get_float("fuel_time") /
617 meta:get_float("fuel_totaltime") * 100)
618 meta:set_string("infotext",string.format(S("Active furnace (Flame used: %d%%) (Rightclick to examine)"), percent))
619 swap_node(pos,"default:furnace_active")
620 meta:set_string("formspec",default.get_furnace_active_formspec(pos, percent))
621 return
624 local fuel = nil
625 local afterfuel
626 local cooked = nil
627 local fuellist = inv:get_list("fuel")
628 local srclist = inv:get_list("src")
630 if srclist then
631 cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
633 if fuellist then
634 fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
637 if not fuel or fuel.time <= 0 then
638 meta:set_string("infotext",S("Furnace without fuel (Rightclick to examine)"))
639 swap_node(pos,"default:furnace")
640 meta:set_string("formspec", default.furnace_inactive_formspec)
641 return
644 if cooked.item:is_empty() then
645 if was_active then
646 meta:set_string("infotext",S("Empty furnace (Rightclick to examine)"))
647 swap_node(pos,"default:furnace")
648 meta:set_string("formspec", default.furnace_inactive_formspec)
650 return
653 meta:set_string("fuel_totaltime", fuel.time)
654 meta:set_string("fuel_time", 0)
656 inv:set_stack("fuel", 1, afterfuel.items[1])
657 end,
660 minetest.register_node("default:cobble", {
661 description = S("cobblestone"),
662 tiles = {"default_cobble.png"},
663 is_ground_content = true,
664 groups = {cracky=3, stone=2},
665 sounds = default.node_sound_stone_defaults(),
668 minetest.register_node("default:apple", {
669 description = S("apple"),
670 drawtype = "plantlike",
671 visual_scale = 1.0,
672 tiles = {"default_apple.png"},
673 inventory_image = "default_apple.png",
674 paramtype = "light",
675 sunlight_propagates = true,
676 walkable = false,
677 is_ground_content = true,
678 selection_box = {
679 type = "fixed",
680 fixed = {-0.2, -0.5, -0.2, 0.2, 0, 0.2}
682 groups = {dig_immediate=3,},
683 on_use = minetest.item_eat(1),
684 sounds = default.node_sound_leaves_defaults(),
685 after_place_node = function(pos, placer, itemstack)
686 if placer:is_player() then
687 minetest.set_node(pos, {name="default:apple", param2=1})
689 end,