151 lines
5.5 KiB
Lua
151 lines
5.5 KiB
Lua
local override_item = minetest.override_item
|
|
local pointed_thing_to_face_pos = minetest.pointed_thing_to_face_pos
|
|
local dir_to_facedir = minetest.dir_to_facedir
|
|
local is_creative_enabled = minetest.is_creative_enabled
|
|
local item_place_node = minetest.item_place_node
|
|
|
|
local stairs = {}
|
|
local slabs = {}
|
|
local slopes = {}
|
|
|
|
|
|
-- Correct stairs placement
|
|
--
|
|
-- Derived from the original stairs on_place function of Minetest Game.
|
|
--
|
|
-- @param itemstack An itemstack according to Minetest API
|
|
-- @param placer A placer object according to Minetest API
|
|
-- @param pointed_thing A pointed_thing according to Minetest API
|
|
-- @return mixed itemstack and position according to Minetest API
|
|
local properly_rotate = function (itemstack, placer, pointed_thing)
|
|
local under = pointed_thing.under
|
|
local above = pointed_thing.above
|
|
local param2 = 0
|
|
|
|
if placer then
|
|
local placer_pos = placer:get_pos()
|
|
local finepos = pointed_thing_to_face_pos(placer, pointed_thing)
|
|
local fpos = finepos.y % 1
|
|
|
|
local under_above = under.y - 1 == above.y
|
|
local fpos_perimeter = (fpos > 0 and fpos < 0.5)
|
|
local fpos_limit = (fpos < -0.5 and fpos > -0.999999999)
|
|
|
|
if placer_pos then
|
|
param2 = dir_to_facedir(vector.subtract(above, placer_pos))
|
|
end
|
|
|
|
if under_above or fpos_perimeter or fpos_limit then
|
|
param2 = param2 + 20
|
|
if param2 == 21 then
|
|
param2 = 23
|
|
elseif param2 == 23 then
|
|
param2 = 21
|
|
end
|
|
end
|
|
end
|
|
|
|
return minetest.item_place(itemstack, placer, pointed_thing, param2)
|
|
end
|
|
|
|
|
|
-- Correct slabs placement
|
|
--
|
|
-- Derived from the original stairs on_place function of Minetest Game.
|
|
--
|
|
-- @param itemstack An itemstack according to Minetest API
|
|
-- @param placer A placer object according to Minetest API
|
|
-- @param pointed_thing A pointed_thing according to Minetest API
|
|
-- @return mixed itemstack and position according to Minetest API
|
|
local on_place_slabs = function (itemstack, placer, pointed_thing)
|
|
local under = minetest.get_node(pointed_thing.under)
|
|
local wield_item = itemstack:get_name()
|
|
local player_name = placer and placer:get_player_name() or ''
|
|
|
|
-- Special behavior if placed on a slab
|
|
if under and under.name:find(':slab_') then
|
|
local pt_above = pointed_thing.above
|
|
local pt_under = pointed_thing.under
|
|
local fdir = dir_to_facedir(vector.subtract(pt_above, pt_under), true)
|
|
local p2 = under.param2
|
|
|
|
-- Slab placement based on upside-down slabs or below slabs
|
|
--
|
|
-- ┌────────┐
|
|
-- │ │
|
|
-- ┢━━━━━━━━┪ <-- Slab A (bottom half of the node seen sideways)
|
|
-- ┃ ┃
|
|
-- ┈┈┈┈┣━━━━━━━━┫┈┈┈┈
|
|
-- ┃ ┃
|
|
-- ┡━━━━━━━━┩ <-- Slab B (top half of the node, seen sideways)
|
|
-- │ │
|
|
-- └────────┘
|
|
--
|
|
-- Slabs A and B are rotated according slab B or A on placement so that
|
|
-- slabs placed on regular slabs from below automatically become
|
|
-- upside-down slabs and slabs placed on top of upside-down slabs are
|
|
-- not rotated into the same position.
|
|
if p2 >= 20 and fdir == 8 then p2 = p2 - 20 end -- Slab A rotation
|
|
if p2 <= 3 and fdir == 4 then p2 = p2 + 20 end -- Slab B rotation
|
|
|
|
-- Place node usind the calculated rotation
|
|
item_place_node(ItemStack(wield_item), placer, pointed_thing, p2)
|
|
|
|
-- Remove one item if not in creative and return the itemstack
|
|
if not is_creative_enabled(player_name) then itemstack:take_item() end
|
|
return itemstack
|
|
end
|
|
|
|
-- When not placed on a slab just properly rotate the slab
|
|
return properly_rotate(itemstack, placer, pointed_thing)
|
|
end
|
|
|
|
|
|
|
|
-- Determine all stairs and slabs and put them into the respective tables.
|
|
for name,definition in pairs(minetest.registered_nodes) do
|
|
local from_moreblocks = definition.mod_origin == 'moreblocks'
|
|
local from_bakedclay = definition.mod_origin == 'bakedclay'
|
|
local mod_origin = from_moreblocks or from_bakedclay
|
|
|
|
local stair = string.match(name, ':stair_') ~= nil
|
|
local slab = string.match(name, ':slab_') ~= nil
|
|
local slope = string.match(name, ':slope_') ~= nil
|
|
|
|
if stair and mod_origin then table.insert(stairs, name) end
|
|
if slab and mod_origin then table.insert(slabs, name) end
|
|
if slope and mod_origin then table.insert(slopes, name) end
|
|
end
|
|
|
|
|
|
-- Iterate over all stairs and override the broken on_place function.
|
|
for _,name in pairs(stairs) do
|
|
override_item(name, {
|
|
on_place = function (itemstack, placer, pointed_thing)
|
|
if pointed_thing.type ~= "node" then return itemstack end
|
|
return properly_rotate(itemstack, placer, pointed_thing)
|
|
end
|
|
})
|
|
end
|
|
|
|
|
|
-- Iterate over all slopes and override the broken on_place function.
|
|
for _,name in pairs(slopes) do
|
|
override_item(name, {
|
|
on_place = function (itemstack, placer, pointed_thing)
|
|
if pointed_thing.type ~= "node" then return itemstack end
|
|
return properly_rotate(itemstack, placer, pointed_thing)
|
|
end
|
|
})
|
|
end
|
|
|
|
|
|
-- Iterate over all slabs and override the broken on_place function.
|
|
for _,name in pairs(slabs) do
|
|
override_item(name, {
|
|
on_place = function (itemstack, placer, pointed_thing)
|
|
return on_place_slabs(itemstack, placer, pointed_thing)
|
|
end
|
|
})
|
|
end
|