Stairs: Big simplification of slabs combination
[oweals/minetest_game.git] / mods / stairs / init.lua
1 -- Minetest 0.4 mod: stairs
2 -- See README.txt for licensing and other information.
3
4
5 -- Global namespace for functions
6
7 stairs = {}
8
9
10 -- Register aliases for new pine node names
11
12 minetest.register_alias("stairs:stair_pinewood", "stairs:stair_pine_wood")
13 minetest.register_alias("stairs:slab_pinewood", "stairs:slab_pine_wood")
14
15
16 -- Get setting for replace ABM
17
18 local replace = minetest.setting_getbool("enable_stairs_replace_abm")
19
20
21 -- Register stairs.
22 -- Node will be called stairs:stair_<subname>
23
24 function stairs.register_stair(subname, recipeitem, groups, images, description, sounds)
25         groups.stair = 1
26         minetest.register_node(":stairs:stair_" .. subname, {
27                 description = description,
28                 drawtype = "mesh",
29                 mesh = "stairs_stair.obj",
30                 tiles = images,
31                 paramtype = "light",
32                 paramtype2 = "facedir",
33                 is_ground_content = false,
34                 groups = groups,
35                 sounds = sounds,
36                 selection_box = {
37                         type = "fixed",
38                         fixed = {
39                                 {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
40                                 {-0.5, 0, 0, 0.5, 0.5, 0.5},
41                         },
42                 },
43                 collision_box = {
44                         type = "fixed",
45                         fixed = {
46                                 {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
47                                 {-0.5, 0, 0, 0.5, 0.5, 0.5},
48                         },
49                 },
50                 on_place = function(itemstack, placer, pointed_thing)
51                         if pointed_thing.type ~= "node" then
52                                 return itemstack
53                         end
54
55                         local p0 = pointed_thing.under
56                         local p1 = pointed_thing.above
57                         local param2 = 0
58
59                         local placer_pos = placer:getpos()
60                         if placer_pos then
61                                 local dir = {
62                                         x = p1.x - placer_pos.x,
63                                         y = p1.y - placer_pos.y,
64                                         z = p1.z - placer_pos.z
65                                 }
66                                 param2 = minetest.dir_to_facedir(dir)
67                         end
68
69                         if p0.y - 1 == p1.y then
70                                 param2 = param2 + 20
71                                 if param2 == 21 then
72                                         param2 = 23
73                                 elseif param2 == 23 then
74                                         param2 = 21
75                                 end
76                         end
77
78                         return minetest.item_place(itemstack, placer, pointed_thing, param2)
79                 end,
80         })
81
82         -- for replace ABM
83         if replace then
84                 minetest.register_node(":stairs:stair_" .. subname .. "upside_down", {
85                         replace_name = "stairs:stair_" .. subname,
86                         groups = {slabs_replace = 1},
87                 })
88         end
89
90         if recipeitem then
91                 minetest.register_craft({
92                         output = 'stairs:stair_' .. subname .. ' 8',
93                         recipe = {
94                                 {recipeitem, "", ""},
95                                 {recipeitem, recipeitem, ""},
96                                 {recipeitem, recipeitem, recipeitem},
97                         },
98                 })
99
100                 -- Flipped recipe for the silly minecrafters
101                 minetest.register_craft({
102                         output = 'stairs:stair_' .. subname .. ' 8',
103                         recipe = {
104                                 {"", "", recipeitem},
105                                 {"", recipeitem, recipeitem},
106                                 {recipeitem, recipeitem, recipeitem},
107                         },
108                 })
109         end
110 end
111
112
113 -- Slab facedir to placement 6d matching table
114 local slab_trans_dir = {[0] = 8, 0, 2, 1, 3, 4}
115 -- Slab facedir when placing initial slab against other surface
116 local slab_trans_dir_place = {[0] = 0, 20, 12, 16, 4, 8}
117
118 -- Register slabs.
119 -- Node will be called stairs:slab_<subname>
120
121 function stairs.register_slab(subname, recipeitem, groups, images, description, sounds)
122         groups.slab = 1
123         minetest.register_node(":stairs:slab_" .. subname, {
124                 description = description,
125                 drawtype = "nodebox",
126                 tiles = images,
127                 paramtype = "light",
128                 paramtype2 = "facedir",
129                 is_ground_content = false,
130                 groups = groups,
131                 sounds = sounds,
132                 node_box = {
133                         type = "fixed",
134                         fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
135                 },
136                 on_place = function(itemstack, placer, pointed_thing)
137                         local under = minetest.get_node(pointed_thing.under)
138                         local wield_item = itemstack:get_name()
139
140                         if under and wield_item == under.name then
141                                 -- place slab using under node orientation
142                                 local dir = minetest.dir_to_facedir(vector.subtract(
143                                         pointed_thing.above, pointed_thing.under), true)
144
145                                 local p2 = under.param2
146
147                                 -- combine two slabs if possible
148                                 if slab_trans_dir[math.floor(p2 / 4)] == dir then
149                                         if not recipeitem then
150                                                 return itemstack
151                                         end
152                                         local player_name = placer:get_player_name()
153                                         if minetest.is_protected(pointed_thing.under, player_name) and not
154                                                         minetest.check_player_privs(placer, "protection_bypass") then
155                                                 minetest.record_protection_violation(pointed_thing.under,
156                                                         player_name)
157                                                 return
158                                         end
159                                         minetest.set_node(pointed_thing.under, {name = recipeitem, param2 = p2})
160                                         if not minetest.setting_getbool("creative_mode") then
161                                                 itemstack:take_item()
162                                         end
163                                         return itemstack
164                                 end
165
166                                 -- Placing a slab on an upside down slab should make it right-side up.
167                                 if p2 >= 20 and dir == 8 then
168                                         p2 = p2 - 20
169                                 -- same for the opposite case: slab below normal slab
170                                 elseif p2 <= 3 and dir == 4 then
171                                         p2 = p2 + 20
172                                 end
173
174                                 -- else attempt to place node with proper param2
175                                 minetest.item_place_node(ItemStack(wield_item), placer, pointed_thing, p2)
176                                 if not minetest.setting_getbool("creative_mode") then
177                                         itemstack:take_item()
178                                 end
179                                 return itemstack
180                         else
181                                 -- place slab using look direction of player
182                                 local dir = minetest.dir_to_wallmounted(vector.subtract(
183                                         pointed_thing.above, pointed_thing.under), true)
184
185                                 local rot = slab_trans_dir_place[dir]
186                                 if rot == 0 or rot == 20 then
187                                         rot = rot + minetest.dir_to_facedir(placer:get_look_dir())
188                                 end
189
190                                 return minetest.item_place(itemstack, placer, pointed_thing, rot)
191                         end
192                 end,
193         })
194
195         -- for replace ABM
196         if replace then
197                 minetest.register_node(":stairs:slab_" .. subname .. "upside_down", {
198                         replace_name = "stairs:slab_".. subname,
199                         groups = {slabs_replace = 1},
200                 })
201         end
202
203         if recipeitem then
204                 minetest.register_craft({
205                         output = 'stairs:slab_' .. subname .. ' 6',
206                         recipe = {
207                                 {recipeitem, recipeitem, recipeitem},
208                         },
209                 })
210         end
211 end
212
213
214 -- Optionally replace old "upside_down" nodes with new param2 versions.
215 -- Disabled by default.
216
217 if replace then
218         minetest.register_abm({
219                 label = "Slab replace",
220                 nodenames = {"group:slabs_replace"},
221                 interval = 16,
222                 chance = 1,
223                 action = function(pos, node)
224                         node.name = minetest.registered_nodes[node.name].replace_name
225                         node.param2 = node.param2 + 20
226                         if node.param2 == 21 then
227                                 node.param2 = 23
228                         elseif node.param2 == 23 then
229                                 node.param2 = 21
230                         end
231                         minetest.set_node(pos, node)
232                 end,
233         })
234 end
235
236
237 -- Stair/slab registration function.
238 -- Nodes will be called stairs:{stair,slab}_<subname>
239
240 function stairs.register_stair_and_slab(subname, recipeitem,
241                 groups, images, desc_stair, desc_slab, sounds)
242         stairs.register_stair(subname, recipeitem, groups, images, desc_stair, sounds)
243         stairs.register_slab(subname, recipeitem, groups, images, desc_slab, sounds)
244 end
245
246
247 -- Register default stairs and slabs
248
249 stairs.register_stair_and_slab(
250         "wood",
251         "default:wood",
252         {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
253         {"default_wood.png"},
254         "Wooden Stair",
255         "Wooden Slab",
256         default.node_sound_wood_defaults()
257 )
258
259 stairs.register_stair_and_slab(
260         "junglewood",
261         "default:junglewood",
262         {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
263         {"default_junglewood.png"},
264         "Jungle Wood Stair",
265         "Jungle Wood Slab",
266         default.node_sound_wood_defaults()
267 )
268
269 stairs.register_stair_and_slab(
270         "pine_wood",
271         "default:pine_wood",
272         {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3},
273         {"default_pine_wood.png"},
274         "Pine Wood Stair",
275         "Pine Wood Slab",
276         default.node_sound_wood_defaults()
277 )
278
279 stairs.register_stair_and_slab(
280         "acacia_wood",
281         "default:acacia_wood",
282         {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
283         {"default_acacia_wood.png"},
284         "Acacia Wood Stair",
285         "Acacia Wood Slab",
286         default.node_sound_wood_defaults()
287 )
288
289 stairs.register_stair_and_slab(
290         "aspen_wood",
291         "default:aspen_wood",
292         {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3},
293         {"default_aspen_wood.png"},
294         "Aspen Wood Stair",
295         "Aspen Wood Slab",
296         default.node_sound_wood_defaults()
297 )
298
299 stairs.register_stair_and_slab(
300         "stone",
301         "default:stone",
302         {cracky = 3},
303         {"default_stone.png"},
304         "Stone Stair",
305         "Stone Slab",
306         default.node_sound_stone_defaults()
307 )
308
309 stairs.register_stair_and_slab(
310         "cobble",
311         "default:cobble",
312         {cracky = 3},
313         {"default_cobble.png"},
314         "Cobblestone Stair",
315         "Cobblestone Slab",
316         default.node_sound_stone_defaults()
317 )
318
319 stairs.register_stair_and_slab(
320         "mossycobble",
321         nil,
322         {cracky = 3},
323         {"default_mossycobble.png"},
324         "Mossy Cobblestone Stair",
325         "Mossy Cobblestone Slab",
326         default.node_sound_stone_defaults()
327 )
328
329 stairs.register_stair_and_slab(
330         "stonebrick",
331         "default:stonebrick",
332         {cracky = 2},
333         {"default_stone_brick.png"},
334         "Stone Brick Stair",
335         "Stone Brick Slab",
336         default.node_sound_stone_defaults()
337 )
338
339 stairs.register_stair_and_slab(
340         "stone_block",
341         "default:stone_block",
342         {cracky = 2},
343         {"default_stone_block.png"},
344         "Stone Block Stair",
345         "Stone Block Slab",
346         default.node_sound_stone_defaults()
347 )
348
349 stairs.register_stair_and_slab(
350         "desert_stone",
351         "default:desert_stone",
352         {cracky = 3},
353         {"default_desert_stone.png"},
354         "Desert Stone Stair",
355         "Desert Stone Slab",
356         default.node_sound_stone_defaults()
357 )
358
359 stairs.register_stair_and_slab(
360         "desert_cobble",
361         "default:desert_cobble",
362         {cracky = 3},
363         {"default_desert_cobble.png"},
364         "Desert Cobblestone Stair",
365         "Desert Cobblestone Slab",
366         default.node_sound_stone_defaults()
367 )
368
369 stairs.register_stair_and_slab(
370         "desert_stonebrick",
371         "default:desert_stonebrick",
372         {cracky = 2},
373         {"default_desert_stone_brick.png"},
374         "Desert Stone Brick Stair",
375         "Desert Stone Brick Slab",
376         default.node_sound_stone_defaults()
377 )
378
379 stairs.register_stair_and_slab(
380         "desert_stone_block",
381         "default:desert_stone_block",
382         {cracky = 2},
383         {"default_desert_stone_block.png"},
384         "Desert Stone Block Stair",
385         "Desert Stone Block Slab",
386         default.node_sound_stone_defaults()
387 )
388
389 stairs.register_stair_and_slab(
390         "sandstone",
391         "default:sandstone",
392         {crumbly = 1, cracky = 3},
393         {"default_sandstone.png"},
394         "Sandstone Stair",
395         "Sandstone Slab",
396         default.node_sound_stone_defaults()
397 )
398
399 stairs.register_stair_and_slab(
400         "sandstonebrick",
401         "default:sandstonebrick",
402         {cracky = 2},
403         {"default_sandstone_brick.png"},
404         "Sandstone Brick Stair",
405         "Sandstone Brick Slab",
406         default.node_sound_stone_defaults()
407 )
408
409 stairs.register_stair_and_slab(
410         "sandstone_block",
411         "default:sandstone_block",
412         {cracky = 2},
413         {"default_sandstone_block.png"},
414         "Sandstone Block Stair",
415         "Sandstone Block Slab",
416         default.node_sound_stone_defaults()
417 )
418
419 stairs.register_stair_and_slab(
420         "obsidian",
421         "default:obsidian",
422         {cracky = 1, level = 2},
423         {"default_obsidian.png"},
424         "Obsidian Stair",
425         "Obsidian Slab",
426         default.node_sound_stone_defaults()
427 )
428
429 stairs.register_stair_and_slab(
430         "obsidianbrick",
431         "default:obsidianbrick",
432         {cracky = 1, level = 2},
433         {"default_obsidian_brick.png"},
434         "Obsidian Brick Stair",
435         "Obsidian Brick Slab",
436         default.node_sound_stone_defaults()
437 )
438
439 stairs.register_stair_and_slab(
440         "obsidian_block",
441         "default:obsidian_block",
442         {cracky = 1, level = 2},
443         {"default_obsidian_block.png"},
444         "Obsidian Block Stair",
445         "Obsidian Block Slab",
446         default.node_sound_stone_defaults()
447 )
448
449 stairs.register_stair_and_slab(
450         "brick",
451         "default:brick",
452         {cracky = 3},
453         {"default_brick.png"},
454         "Brick Stair",
455         "Brick Slab",
456         default.node_sound_stone_defaults()
457 )
458
459 stairs.register_stair_and_slab(
460         "straw",
461         "farming:straw",
462         {snappy = 3, flammable = 4},
463         {"farming_straw.png"},
464         "Straw Stair",
465         "Straw Slab",
466         default.node_sound_leaves_defaults()
467 )
468
469 stairs.register_stair_and_slab(
470         "steelblock",
471         "default:steelblock",
472         {cracky = 1, level = 2},
473         {"default_steel_block.png"},
474         "Steel Block Stair",
475         "Steel Block Slab",
476         default.node_sound_stone_defaults()
477 )
478
479 stairs.register_stair_and_slab(
480         "copperblock",
481         "default:copperblock",
482         {cracky = 1, level = 2},
483         {"default_copper_block.png"},
484         "Copper Block Stair",
485         "Copper Block Slab",
486         default.node_sound_stone_defaults()
487 )
488
489 stairs.register_stair_and_slab(
490         "bronzeblock",
491         "default:bronzeblock",
492         {cracky = 1, level = 2},
493         {"default_bronze_block.png"},
494         "Bronze Block Stair",
495         "Bronze Block Slab",
496         default.node_sound_stone_defaults()
497 )
498
499 stairs.register_stair_and_slab(
500         "goldblock",
501         "default:goldblock",
502         {cracky = 1},
503         {"default_gold_block.png"},
504         "Gold Block Stair",
505         "Gold Block Slab",
506         default.node_sound_stone_defaults()
507 )