Skip to content

Commit b848e35

Browse files
sofarparamat
authored andcommittedSep 14, 2016
Stairs: Big simplification of slabs combination
Combine slabs if identical based on orientations using a simple lookup table if the nodes are identical. Otherwise relies on place_node() to place the node, which properly handles rotation compared to adjacent nodes already, and can orient based on look_dir as well. Initial slabs placed are oriented based on (1) the orientation of the pointed "face" (assumes nodes are cubic, of course), and uses the player look direction to orient the node n/e/w/s if the slab is horizontal or upside-down. If placed against a vertical face, the slab is placed against the face without rotation around the axis perpendicular to that vertical face. This allows upside down placement and vertical placement without screwdriver. If a slab is placed on top of an upside down slab, or below a normally placed slab, the rotation is inverted so that no "floating" slab is created. Largely based on kilbith's #807 PR. Slab combining and place_node() usage by sofar. Since this relies entirely on `on_place` mechanics, this fails to combine slabs into a plain node if the space *above* is occupied. This is unavoidable due to the fact that on_place() happens after the checks required to see if pointed_thing.above is empty or not.
1 parent 0cbb516 commit b848e35

File tree

1 file changed

+51
-71
lines changed

1 file changed

+51
-71
lines changed
 

Diff for: ‎mods/stairs/init.lua

+51-71
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ function stairs.register_stair(subname, recipeitem, groups, images, description,
110110
end
111111

112112

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+
113118
-- Register slabs.
114119
-- Node will be called stairs:slab_<subname>
115120

@@ -129,86 +134,61 @@ function stairs.register_slab(subname, recipeitem, groups, images, description,
129134
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
130135
},
131136
on_place = function(itemstack, placer, pointed_thing)
132-
if pointed_thing.type ~= "node" then
133-
return itemstack
134-
end
137+
local under = minetest.get_node(pointed_thing.under)
138+
local wield_item = itemstack:get_name()
135139

136-
-- If it's being placed on an another similar one, replace it with
137-
-- a full block
138-
local slabpos = nil
139-
local slabnode = nil
140-
local p0 = pointed_thing.under
141-
local p1 = pointed_thing.above
142-
local n0 = minetest.get_node(p0)
143-
local n1 = minetest.get_node(p1)
144-
local param2 = 0
140+
if under and wield_item == under.name then
Has comments. Original line has comments.
141+
-- place slab using under node orientation
142+
local dir = minetest.dir_to_facedir(vector.subtract(
143+
pointed_thing.above, pointed_thing.under), true)
145144

146-
local n0_is_upside_down = (n0.name == "stairs:slab_" .. subname and
147-
n0.param2 >= 20)
145+
local p2 = under.param2
148146

149-
if n0.name == "stairs:slab_" .. subname and not n0_is_upside_down and
150-
p0.y + 1 == p1.y then
151-
slabpos = p0
152-
slabnode = n0
153-
elseif n1.name == "stairs:slab_" .. subname then
154-
slabpos = p1
155-
slabnode = n1
156-
end
157-
if slabpos then
158-
-- Remove the slab at slabpos
159-
minetest.remove_node(slabpos)
160-
-- Make a fake stack of a single item and try to place it
161-
local fakestack = ItemStack(recipeitem)
162-
fakestack:set_count(itemstack:get_count())
163-
164-
pointed_thing.above = slabpos
165-
local success
166-
fakestack, success = minetest.item_place(fakestack, placer,
167-
pointed_thing)
168-
-- If the item was taken from the fake stack, decrement original
169-
if success then
170-
itemstack:set_count(fakestack:get_count())
171-
-- Else put old node back
172-
else
173-
minetest.set_node(slabpos, slabnode)
174-
end
175-
return itemstack
176-
end
177-
178-
-- Upside down slabs
179-
if p0.y - 1 == p1.y then
180-
-- Turn into full block if pointing at a existing slab
181-
if n0_is_upside_down then
182-
-- Remove the slab at the position of the slab
183-
minetest.remove_node(p0)
184-
-- Make a fake stack of a single item and try to place it
185-
local fakestack = ItemStack(recipeitem)
186-
fakestack:set_count(itemstack:get_count())
187-
188-
pointed_thing.above = p0
189-
local success
190-
fakestack, success = minetest.item_place(fakestack, placer,
191-
pointed_thing)
192-
-- If the item was taken from the fake stack, decrement original
193-
if success then
194-
itemstack:set_count(fakestack:get_count())
195-
-- Else put old node back
196-
else
197-
minetest.set_node(p0, n0)
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()
198162
end
199163
return itemstack
200164
end
201165

202-
-- Place upside down slab
203-
param2 = 20
204-
end
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
205173

206-
-- If pointing at the side of a upside down slab
207-
if n0_is_upside_down and p0.y + 1 ~= p1.y then
208-
param2 = 20
209-
end
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
210189

211-
return minetest.item_place(itemstack, placer, pointed_thing, param2)
190+
return minetest.item_place(itemstack, placer, pointed_thing, rot)
191+
end
212192
end,
213193
})
214194

0 commit comments

Comments
 (0)
Please sign in to comment.