Replace getpos() with get_pos()
[MineClone/MineClone2.git] / mods / ITEMS / mcl_stairs / api.lua
blobd90bc845283ff03cabed054b3359393889f4887b
1 -- Core mcl_stairs API
3 -- Wrapper around mintest.pointed_thing_to_face_pos.
4 local function get_fpos(placer, pointed_thing)
5 local fpos
6 -- Workaround: minetest.pointed_thing_to_face_pos crashes in MT 0.4.16 if
7 -- pointed_thing.under and pointed_thing.above are equal
8 -- FIXME: Remove this when MT got fixed.
9 if not vector.equals(pointed_thing.under, pointed_thing.above) then
10 -- The happy case: Everything is normal
11 local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
12 fpos = finepos.y % 1
13 else
14 -- Fallback if both above and under are equal
15 fpos = 0
16 end
17 return fpos
18 end
20 local function place_slab_normal(itemstack, placer, pointed_thing)
21 -- Use pointed node's on_rightclick function first, if present
22 local node = minetest.get_node(pointed_thing.under)
23 if placer and not placer:get_player_control().sneak then
24 if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
25 return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
26 end
27 end
29 local p0 = pointed_thing.under
30 local p1 = pointed_thing.above
32 local placer_pos = placer:get_pos()
34 local fpos = get_fpos(placer, pointed_thing)
36 local place = ItemStack(itemstack)
37 local origname = itemstack:get_name()
38 if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5)
39 or (fpos < -0.5 and fpos > -0.999999999) then
40 place:set_name(origname .. "_top")
41 end
42 local ret = minetest.item_place(place, placer, pointed_thing, 0)
43 ret:set_name(origname)
44 return ret
45 end
47 local function place_stair(itemstack, placer, pointed_thing)
48 -- Use pointed node's on_rightclick function first, if present
49 local node = minetest.get_node(pointed_thing.under)
50 if placer and not placer:get_player_control().sneak then
51 if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
52 return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
53 end
54 end
56 local p0 = pointed_thing.under
57 local p1 = pointed_thing.above
58 local param2 = 0
60 local placer_pos = placer:get_pos()
61 if placer_pos then
62 param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos))
63 end
65 local fpos = get_fpos(placer, pointed_thing)
67 if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5)
68 or (fpos < -0.5 and fpos > -0.999999999) then
69 param2 = param2 + 20
70 if param2 == 21 then
71 param2 = 23
72 elseif param2 == 23 then
73 param2 = 21
74 end
75 end
76 return minetest.item_place(itemstack, placer, pointed_thing, param2)
77 end
79 -- Register stairs.
80 -- Node will be called mcl_stairs:stair_<subname>
82 function mcl_stairs.register_stair(subname, recipeitem, groups, images, description, sounds, hardness, corner_stair_texture_override)
83 groups.stair = 1
84 groups.building_block = 1
86 if recipeitem then
87 if not images then
88 images = minetest.registered_items[recipeitem].tiles
89 end
90 if not groups then
91 groups = minetest.registered_items[recipeitem].groups
92 end
93 if not sounds then
94 sounds = minetest.registered_items[recipeitem].sounds
95 end
96 if not hardness then
97 hardness = minetest.registered_items[recipeitem]._mcl_hardness
98 end
99 end
101 minetest.register_node(":mcl_stairs:stair_" .. subname, {
102 description = description,
103 _doc_items_longdesc = "Stairs are useful to reach higher places by walking over them; jumping is not required. Placing stairs in a corner pattern will create corner stairs. Stairs placed on the bottom or at the upper half of the side of a block will be placed upside down.",
104 drawtype = "mesh",
105 mesh = "stairs_stair.obj",
106 tiles = images,
107 paramtype = "light",
108 paramtype2 = "facedir",
109 is_ground_content = false,
110 groups = groups,
111 sounds = sounds,
112 selection_box = {
113 type = "fixed",
114 fixed = {
115 {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
116 {-0.5, 0, 0, 0.5, 0.5, 0.5},
119 collision_box = {
120 type = "fixed",
121 fixed = {
122 {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
123 {-0.5, 0, 0, 0.5, 0.5, 0.5},
126 on_place = function(itemstack, placer, pointed_thing)
127 if pointed_thing.type ~= "node" then
128 return itemstack
131 return place_stair(itemstack, placer, pointed_thing)
132 end,
133 _mcl_hardness = hardness,
136 if recipeitem then
137 minetest.register_craft({
138 output = 'mcl_stairs:stair_' .. subname .. ' 4',
139 recipe = {
140 {recipeitem, "", ""},
141 {recipeitem, recipeitem, ""},
142 {recipeitem, recipeitem, recipeitem},
146 -- Flipped recipe
147 minetest.register_craft({
148 output = 'mcl_stairs:stair_' .. subname .. ' 4',
149 recipe = {
150 {"", "", recipeitem},
151 {"", recipeitem, recipeitem},
152 {recipeitem, recipeitem, recipeitem},
157 mcl_stairs.cornerstair.add("mcl_stairs:stair_"..subname, corner_stair_texture_override)
161 -- Slab facedir to placement 6d matching table
162 local slab_trans_dir = {[0] = 8, 0, 2, 1, 3, 4}
164 -- Register slabs.
165 -- Node will be called mcl_stairs:slab_<subname>
167 -- double_description: NEW argument, not supported in Minetest Game
168 -- double_description: Description of double slab
169 function mcl_stairs.register_slab(subname, recipeitem, groups, images, description, sounds, hardness, double_description)
170 local lower_slab = "mcl_stairs:slab_"..subname
171 local upper_slab = lower_slab.."_top"
172 local double_slab = lower_slab.."_double"
174 if recipeitem then
175 if not images then
176 images = minetest.registered_items[recipeitem].tiles
178 if not groups then
179 groups = minetest.registered_items[recipeitem].groups
181 if not sounds then
182 sounds = minetest.registered_items[recipeitem].sounds
184 if not hardness then
185 hardness = minetest.registered_items[recipeitem]._mcl_hardness
189 -- Automatically generate double slab description
190 if not double_description then
191 double_description = string.format("Double %s", description)
192 minetest.log("warning", "[stairs] No explicit description for double slab '"..double_slab.."' added. Using auto-generated description.")
195 groups.slab = 1
196 groups.building_block = 1
197 local longdesc = "Slabs are half as high as their full block counterparts and occupy either the lower or upper part of a block, depending on how it was placed. Slabs can be easily stepped on without needing to jump. When a slab is placed on another slab of the same type, a double slab is created."
199 local slabdef = {
200 description = description,
201 _doc_items_longdesc = longdesc,
202 drawtype = "nodebox",
203 tiles = images,
204 paramtype = "light",
205 -- Facedir intentionally left out (see below)
206 is_ground_content = false,
207 groups = groups,
208 sounds = sounds,
209 node_box = {
210 type = "fixed",
211 fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
213 on_place = function(itemstack, placer, pointed_thing)
214 local under = minetest.get_node(pointed_thing.under)
215 local wield_item = itemstack:get_name()
216 local creative_enabled = minetest.settings:get_bool("creative_mode")
218 -- place slab using under node orientation
219 local dir = vector.subtract(pointed_thing.above, pointed_thing.under)
221 local p2 = under.param2
223 -- combine two slabs if possible
224 -- Requirements: Same slab material, must be placed on top of lower slab, or on bottom of upper slab
225 if (wield_item == under.name or (minetest.registered_nodes[under.name] and wield_item == minetest.registered_nodes[under.name]._mcl_other_slab_half)) and
226 not ((dir.y >= 0 and minetest.get_item_group(under.name, "slab_top") == 1) or
227 (dir.y <= 0 and minetest.get_item_group(under.name, "slab_top") == 0)) then
229 local player_name = placer:get_player_name()
230 if minetest.is_protected(pointed_thing.under, player_name) and not
231 minetest.check_player_privs(placer, "protection_bypass") then
232 minetest.record_protection_violation(pointed_thing.under,
233 player_name)
234 return
236 local newnode = double_slab
237 minetest.set_node(pointed_thing.under, {name = newnode, param2 = p2})
238 if not creative_enabled then
239 itemstack:take_item()
241 return itemstack
242 -- No combination possible: Place slab normally
243 else
244 return place_slab_normal(itemstack, placer, pointed_thing)
246 end,
247 _mcl_hardness = hardness,
248 _mcl_other_slab_half = upper_slab,
251 minetest.register_node(":"..lower_slab, slabdef)
253 -- Register the upper slab.
254 -- Using facedir is not an option, as this would rotate the textures as well and would make
255 -- e.g. upper sandstone slabs look completely wrong.
256 local topdef = table.copy(slabdef)
257 topdef.groups.slab = 1
258 topdef.groups.slab_top = 1
259 topdef.groups.not_in_creative_inventory = 1
260 topdef.groups.not_in_craft_guide = 1
261 topdef.description = string.format("Upper %s", description)
262 topdef._doc_items_create_entry = false
263 topdef._doc_items_longdesc = nil
264 topdef._doc_items_usagehelp = nil
265 topdef.drop = lower_slab
266 topdef._mcl_other_slab_half = lower_slab
267 topdef.node_box = {
268 type = "fixed",
269 fixed = {-0.5, 0, -0.5, 0.5, 0.5, 0.5},
271 topdef.selection_box = {
272 type = "fixed",
273 fixed = {-0.5, 0, -0.5, 0.5, 0.5, 0.5},
275 minetest.register_node(":"..upper_slab, topdef)
278 -- Double slab node
279 local dgroups = table.copy(groups)
280 dgroups.not_in_creative_inventory = 1
281 dgroups.not_in_craft_guide = 1
282 dgroups.slab = nil
283 dgroups.double_slab = 1
284 minetest.register_node(":"..double_slab, {
285 description = double_description,
286 _doc_items_longdesc = "Double slabs are full blocks which are created by placing two slabs of the same kind on each other.",
287 tiles = images,
288 is_ground_content = false,
289 groups = dgroups,
290 sounds = sounds,
291 drop = lower_slab .. " 2",
292 _mcl_hardness = hardness,
295 if recipeitem then
296 minetest.register_craft({
297 output = lower_slab .. " 6",
298 recipe = {
299 {recipeitem, recipeitem, recipeitem},
305 -- Help alias for the upper slab
306 if minetest.get_modpath("doc") then
307 doc.add_entry_alias("nodes", lower_slab, "nodes", upper_slab)
312 -- Stair/slab registration function.
313 -- Nodes will be called mcl_stairs:{stair,slab}_<subname>
315 function mcl_stairs.register_stair_and_slab(subname, recipeitem,
316 groups, images, desc_stair, desc_slab, sounds, hardness,
317 double_description, corner_stair_texture_override)
318 mcl_stairs.register_stair(subname, recipeitem, groups, images, desc_stair, sounds, hardness, corner_stair_texture_override)
319 mcl_stairs.register_slab(subname, recipeitem, groups, images, desc_slab, sounds, hardness, double_description)
322 -- Very simple registration function
323 -- Makes stair and slab out of a source node
324 function mcl_stairs.register_stair_and_slab_simple(subname, sourcenode, desc_stair, desc_slab, desc_double_slab, corner_stair_texture_override)
325 local def = minetest.registered_nodes[sourcenode]
326 local groups = {}
327 -- Only allow a strict set of groups to be added to stairs and slabs for more predictable results
328 local allowed_groups = { "dig_immediate", "handy", "pickaxey", "axey", "shovely", "shearsy", "shearsy_wool", "swordy", "swordy_wool" }
329 for a=1, #allowed_groups do
330 if def.groups[allowed_groups[a]] then
331 groups[allowed_groups[a]] = def.groups[allowed_groups[a]]
334 mcl_stairs.register_stair_and_slab(subname, sourcenode, groups, def.tiles, desc_stair, desc_slab, def.sounds, def._mcl_hardness, desc_double_slab, corner_stair_texture_override)