540 lines
24 KiB
Lua
Executable File
540 lines
24 KiB
Lua
Executable File
-------------------------------------------------------------------------------------
|
|
-- _________ ___. __________.__ __ --
|
|
-- \_ ___ \ ____ _____\_ |__ ____\______ \ | ____ ____ | | __ --
|
|
-- / \ \/ / _ \ / \| __ \ / _ \| | _/ | / _ \_/ ___\| |/ / --
|
|
-- \ \___( <_> ) Y Y \ \_\ ( <_> ) | \ |_( <_> ) \___| < --
|
|
-- \______ /\____/|__|_| /___ /\____/|______ /____/\____/ \___ >__|_ \ --
|
|
-- \/ \/ \/ \/ \/ \/ --
|
|
-- --
|
|
-- Orginally written/created by Pithydon/Pithy --
|
|
-- Version 5.5.0.1 --
|
|
-- first 3 numbers version of minetest created for, --
|
|
-- last digit mod version for MT version --
|
|
-------------------------------------------------------------------------------------
|
|
|
|
----------------------------
|
|
-- Settings --
|
|
----------------------------
|
|
local S = minetest.get_translator(minetest.get_current_modname())
|
|
local cs = tonumber(minetest.settings:get("comboblock_scale")) or 16
|
|
local node_count = 0
|
|
local existing_node_count = 0
|
|
local to_many_nodes = false
|
|
comboblock = {}
|
|
|
|
local m_name = minetest.get_current_modname()
|
|
local m_path = minetest.get_modpath(m_name)
|
|
dofile(m_path.. "/i_comboblock_letter.lua" )
|
|
----------------------------
|
|
-- Functions --
|
|
----------------------------
|
|
------------------------------
|
|
-- Group retrieval function --
|
|
------------------------------
|
|
--by blert2112 minetest forum
|
|
local function registered_nodes_by_group(groupname)
|
|
local result = {}
|
|
for name, def in pairs(minetest.registered_nodes) do
|
|
node_count = node_count + 1
|
|
if def.groups[groupname] then
|
|
result[#result+1] = name
|
|
end
|
|
end
|
|
return result
|
|
end
|
|
|
|
----------------------------
|
|
-- Add Lowpart and Resize --
|
|
----------------------------
|
|
-- Add "^[lowpart:50:" and resize to all image names
|
|
-- against source node for V2 (bottoms)
|
|
function add_lowpart(tiles)
|
|
|
|
local name_split = string.split(tiles.name,"^")
|
|
local new_name = ""
|
|
local i = 1
|
|
while i <= #name_split do
|
|
|
|
if string.sub(name_split[i],1,1) == "[" then
|
|
if name_split[i] =="[transformR90" then -- remove the rotate 90's
|
|
new_name = new_name.."^[transformR180FY"..name_split[i]
|
|
else
|
|
new_name = new_name.."^"..name_split[i] -- catch coloring etc
|
|
end
|
|
else
|
|
new_name = new_name..
|
|
"^[lowpart:50:"..name_split[i].. -- overlay lower 50%
|
|
"\\^[resize\\:"..cs.."x"..cs -- resize image to comboblock scale
|
|
|
|
end
|
|
i=i+1
|
|
end
|
|
return new_name -- Output Single image eg ^[lowpart:50:default_cobble.png
|
|
end -- Output Two or more image eg ^[lowpart:50:default_cobble.png^[lowpart:50:cracked_cobble.png
|
|
|
|
-------------------------
|
|
-- Get Comboblock Name --
|
|
-------------------------
|
|
local function cb_get_name(pla_tar,placer,node_c_name) -- pas == pot_short_axis
|
|
|
|
if not pla_tar.err then
|
|
local first_node_name = pla_tar[1]
|
|
local second_node_name = node_c_name
|
|
|
|
if pla_tar[1] == "clicked" then
|
|
first_node_name = node_c_name
|
|
second_node_name = pla_tar[1]
|
|
end
|
|
|
|
local output = "comboblock:"..first_node_name:split(":")[2].."_onc_"..second_node_name:split(":")[2]
|
|
|
|
return output
|
|
else
|
|
minetest.chat_send_player(placer:get_player_name(), pla_tar.err)
|
|
end
|
|
end
|
|
|
|
------------------------
|
|
-- Comboblock Raycast --
|
|
------------------------
|
|
local function combo_raycast(placer)
|
|
-- calculation of eye position ripped from builtins 'pointed_thing_to_face_pos'
|
|
local placer_pos = placer:get_pos()
|
|
local eye_height = placer:get_properties().eye_height
|
|
local eye_offset = placer:get_eye_offset()
|
|
placer_pos.y = placer_pos.y + eye_height
|
|
placer_pos = vector.add(placer_pos, eye_offset)
|
|
|
|
-- get wielded item range 5 is engine default
|
|
-- order tool/item range >> hand_range >> fallback 5
|
|
local tool_range = placer:get_wielded_item():get_definition().range or nil
|
|
local hand_range
|
|
for key, val in pairs(minetest.registered_items) do
|
|
if key == "" then
|
|
hand_range = val.range or nil
|
|
end
|
|
end
|
|
local wield_range = tool_range or hand_range or 5
|
|
|
|
-- determine ray end position
|
|
local look_dir = placer:get_look_dir()
|
|
look_dir = vector.multiply(look_dir, wield_range)
|
|
local end_pos = vector.add(look_dir, placer_pos)
|
|
|
|
-- get pointed_thing
|
|
local ray = {}
|
|
local ray = minetest.raycast(placer_pos, end_pos, false, false)
|
|
local ray_pt = ray:next()
|
|
|
|
return ray_pt
|
|
end
|
|
|
|
--------------------------
|
|
-- Comboblock Give Drop --
|
|
--------------------------
|
|
function comboblock.give_drop(digger, item)
|
|
if not creative.is_enabled_for(digger:get_player_name()) then
|
|
local inv = digger:get_inventory()
|
|
if inv:room_for_item("main", ItemStack(item.." ".. 1)) then
|
|
inv:add_item("main", ItemStack(item.." ".. 1))
|
|
else
|
|
local pos = digger:get_pos()
|
|
minetest.item_drop(ItemStack(item.." ".. 1), digger, pos)
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------
|
|
-- After Dig Node --
|
|
--------------------
|
|
|
|
local function cb_after_dig_node(pos, oldnode, oldmetadata, digger)
|
|
-- I know weird I put the node back but otherwise we cant raycast and get exact pos
|
|
-- This avoids having to alter on_dig which is not recommended.
|
|
minetest.swap_node(pos, {name = oldnode.name, param2 = oldnode.param2})
|
|
|
|
local pointed = combo_raycast(digger)
|
|
local point = vector.subtract(pointed.intersection_point,pointed.under)
|
|
local normal = pointed.intersection_normal
|
|
local nor_string = tostring(math.abs(normal.x)..math.abs(normal.y)..math.abs(normal.z))
|
|
local exact_nor_string = tostring(normal.x..normal.y..normal.z)
|
|
local v1 = minetest.registered_nodes[oldnode.name].comboblock_v1
|
|
local v2 = minetest.registered_nodes[oldnode.name].comboblock_v2
|
|
|
|
-- always lose this thread: https://forum.minetest.net/viewtopic.php?f=47&t=24188
|
|
-- converts axis and param2 into useful values for removal/swap
|
|
local comboblock_p2_axis = {
|
|
["100"] = {[0] = {"hb",22,0},[1] = {"vl",10,4 },[2] = {"vr",4 ,10},[3] = {"bb",13,13},[4] = {"bt",13,13},[5] = {"ht",0,22}, ["h"] = "z", ["v"] = "y"}, -- +X
|
|
["-100"] = {[0] = {"hb",22,0},[1] = {"vl",10,4 },[2] = {"vr",4 ,10},[3] = {"bb",19,19},[4] = {"bt",19,19},[5] = {"ht",0,22}, ["h"] = "z", ["v"] = "y"}, -- -X
|
|
["010"] = {[0] = {"bb",22,0},[1] = {"vl",10,4 },[2] = {"vr",4 ,10},[3] = {"hb",19,13},[4] = {"ht",13,19},[5] = {"bt",0,22}, ["h"] = "z", ["v"] = "x"}, -- +Y
|
|
["0-10"] = {[0] = {"bb",22,0},[1] = {"vl",10,4 },[2] = {"vr",4 ,10},[3] = {"hb",19,13},[4] = {"ht",13,19},[5] = {"bt",0,22}, ["h"] = "z", ["v"] = "x"}, -- -Y
|
|
["001"] = {[0] = {"hb",22,0},[1] = {"bb",4 ,4 },[2] = {"bt",4 ,4 },[3] = {"vl",19,13},[4] = {"vr",13,19},[5] = {"ht",0,22}, ["h"] = "x", ["v"] = "y"}, -- +Z
|
|
["00-1"] = {[0] = {"hb",22,0},[1] = {"bb",10,10},[2] = {"bt",10,10},[3] = {"vl",19,13},[4] = {"vr",13,19},[5] = {"ht",0,22}, ["h"] = "x", ["v"] = "y"}} -- -Z
|
|
|
|
local p2_axis = math.floor(oldnode.param2/4)
|
|
local outcome = comboblock_p2_axis[exact_nor_string][p2_axis][1]
|
|
local o_p2_v1 = comboblock_p2_axis[exact_nor_string][p2_axis][2]
|
|
local o_p2_v2 = comboblock_p2_axis[exact_nor_string][p2_axis][3]
|
|
|
|
local hor = comboblock_p2_axis[exact_nor_string]["h"]
|
|
local ver = comboblock_p2_axis[exact_nor_string]["v"]
|
|
|
|
|
|
-- v1 is always top half v2 is always bottom half - reverse of expected.
|
|
-- Using swap to minimise accidental callback triggering
|
|
if outcome == "hb" then
|
|
if point[ver] >= 0 then
|
|
minetest.swap_node(pos, {name = v2, param2 = o_p2_v2})
|
|
comboblock.give_drop(digger, v1)
|
|
else
|
|
minetest.swap_node(pos, {name = v1, param2 = o_p2_v1})
|
|
comboblock.give_drop(digger, v2)
|
|
end
|
|
|
|
elseif outcome == "ht" then
|
|
if point[ver] >= 0 then
|
|
minetest.swap_node(pos, {name = v1, param2 = o_p2_v1})
|
|
comboblock.give_drop(digger, v2)
|
|
else
|
|
minetest.swap_node(pos, {name = v2, param2 = o_p2_v2})
|
|
comboblock.give_drop(digger, v1)
|
|
end
|
|
|
|
elseif outcome == "vl" then
|
|
if point[hor] >= 0 then
|
|
minetest.swap_node(pos, {name = v2, param2 = o_p2_v2})
|
|
comboblock.give_drop(digger, v1)
|
|
else
|
|
minetest.swap_node(pos, {name = v1, param2 = o_p2_v1})
|
|
comboblock.give_drop(digger, v2)
|
|
end
|
|
|
|
elseif outcome == "vr" then
|
|
if point[hor] >= 0 then
|
|
minetest.swap_node(pos, {name = v1, param2 = o_p2_v1 })
|
|
comboblock.give_drop(digger, v2)
|
|
else
|
|
minetest.swap_node(pos, {name = v2, param2 = o_p2_v2 })
|
|
comboblock.give_drop(digger, v1)
|
|
end
|
|
|
|
elseif outcome == "bb" then
|
|
if tonumber(exact_nor_string) == nil or
|
|
tonumber(exact_nor_string) < 0 then
|
|
minetest.swap_node(pos, {name = v1, param2 = o_p2_v1 })
|
|
comboblock.give_drop(digger, v2)
|
|
else
|
|
minetest.swap_node(pos, {name = v2, param2 = o_p2_v2 })
|
|
comboblock.give_drop(digger, v1)
|
|
end
|
|
|
|
elseif outcome == "bt" then
|
|
if tonumber(exact_nor_string) == nil or
|
|
tonumber(exact_nor_string) < 0 then
|
|
minetest.swap_node(pos, {name = v2, param2 = o_p2_v2})
|
|
comboblock.give_drop(digger, v1)
|
|
else
|
|
minetest.swap_node(pos, {name = v1, param2 = o_p2_v1 })
|
|
comboblock.give_drop(digger, v2)
|
|
end
|
|
else
|
|
local name = digger:get_player_name()
|
|
minetest.chat_send_player(name ,"Hmm...something has gone wrong, everything has crumbled!?!")
|
|
minetest.swap_node(pos, {name = "air"})
|
|
end
|
|
end
|
|
|
|
----------------------------
|
|
-- Main Code --
|
|
----------------------------
|
|
|
|
-- moreblocks code part borrowed from Linuxdirk MT forums
|
|
-- Im directly updating these on the fly not using override_item
|
|
-- Not the best practice and maybe slower - review later
|
|
|
|
local mblocks = minetest.get_modpath("moreblocks") -- used to establish if moreblocks is loaded
|
|
|
|
if mblocks ~= nil then
|
|
minetest.debug("moreblocks present")
|
|
|
|
for name, def in pairs(minetest.registered_nodes) do
|
|
local slab_name = string.sub (def.description, -6)
|
|
if slab_name == "(8/16)" then -- The only way Ive found of identifying moreblocks half slabs
|
|
def.groups.slab = 1 -- Add any slabs in moreblocks that are 8/16 to the slab group
|
|
|
|
for index,_ in pairs (def.tiles)do -- Part borrowed from Linuxdirk
|
|
if type(def.tiles[index]) == 'table' then
|
|
def.tiles[index].align_style = 'world'
|
|
else
|
|
def.tiles[index] = {
|
|
name = def.tiles[index],
|
|
align_style = 'world'
|
|
}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- creates an index of any node name in the group "slab"
|
|
local slab_index = registered_nodes_by_group("slab")
|
|
|
|
-- Calculate max permutations, this over estimates as we
|
|
-- don't mix glass and non-glass - in-built error margin
|
|
local max_perm = #slab_index*(#slab_index-1)
|
|
local existing_node_count = node_count
|
|
|
|
for _,v1 in pairs(slab_index) do
|
|
|
|
-- set from v2_tiles node registration count
|
|
if to_many_nodes then
|
|
break
|
|
|
|
else
|
|
local v1_def = minetest.registered_nodes[v1] -- Makes a copy of the relevant node settings
|
|
local v1_groups = table.copy(v1_def.groups) -- Takes the above and places the groups into its own seperate copy
|
|
local v1_tiles -- v1 tiles table
|
|
v1_groups.not_in_creative_inventory = 1 -- Don't want comboblocks cluttering inventory
|
|
v1_groups.slab = nil -- They aren't slabs so remove slab group
|
|
|
|
if type(v1_def.tiles) ~= "table" then -- Check tiles are stored as table some old mods just have tiles = "texture.png"
|
|
v1_tiles = {v1_def.tiles} -- construct table as {"texture.png"}
|
|
else
|
|
v1_tiles = table.copy(v1_def.tiles) -- copy of the node texture images
|
|
end
|
|
|
|
for i = 2, 6, 1 do -- Checks for image names for each side, If not image name
|
|
if not v1_tiles[i] then -- then copy previous image name in: 1 = Top, 2 = Bottom, 3-6 = Sides
|
|
v1_tiles[i] = v1_tiles[i-1]
|
|
elseif mblocks ~= nil and i >= 5 then
|
|
v1_tiles[i].name = v1_tiles[i].name:gsub("%^%[transformR90", "") -- v1 R90 not needed as applied at V2 stage needed for moreblocks
|
|
end
|
|
end
|
|
|
|
|
|
for _,v2 in pairs(slab_index) do -- every slab has to be done with every other slab including itself
|
|
|
|
if node_count > 32668 then -- Prevent registering more than the max 32768 - limit set 100 less than max
|
|
minetest.debug("WARNING:Comboblock - Max nodes"..
|
|
" registered: "..(max_perm+existing_node_count)-node_count..
|
|
" slab combos not registered")
|
|
to_many_nodes = true -- Outer loop break trigger
|
|
break
|
|
|
|
else
|
|
|
|
local v2_def = minetest.registered_nodes[v2] -- this creates a second copy of all slabs and is identical to v1
|
|
local v2_tiles
|
|
|
|
if type(v2_def.tiles) ~= "table" then -- Check tiles are stored as table some old mods just have tiles = "texture.png"
|
|
v2_tiles = {v2_def.tiles} -- construct table as {"texture.png"}
|
|
else
|
|
v2_tiles = table.copy(v2_def.tiles) -- copy of the node texture images
|
|
end
|
|
|
|
for i = 2, 6, 1 do -- Checks for image names for each side, If not image name
|
|
if not v2_tiles[i] and i <= 2 then -- then copy previous image name in: 1 = Top, 2 = Bottom, 3-6 = Sides
|
|
v2_tiles[i] = v2_tiles[i-1]
|
|
|
|
elseif i >= 3 then
|
|
|
|
if not v2_tiles[i] then
|
|
v2_tiles[i] = table.copy(v2_tiles[i-1]) -- must be table copy as we don't want a pointer
|
|
v2_tiles[i].name = add_lowpart(v2_tiles[i]) -- only need to do this once as 4,5,6 are basically copy of 3
|
|
else
|
|
v2_tiles[i].name = add_lowpart(v2_tiles[i]) -- If node has images specified for each slot have to add string to the front of those
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Register nodes --
|
|
|
|
-- Very strange behaviour with orginal mod when placing glass and normal slabs ontop of each other.
|
|
-- Removed the ability to place glass slabs on non-glass slabs.
|
|
-- Original Behaviour summary:
|
|
-- Normal slab on glass slab - slab appears as top slab with some strange graphic overlay, Unknown why - guess drawtype conflict with graphic
|
|
-- Glass slab on normal slab - slab appears as top glass slab ie full glass block, Unknown why - guess drawtype conflict with graphic
|
|
-- For example of above place "glass" slab on "obsidian glass" slab and vice versa this seemed minimal issue so left this combo okay
|
|
-- Glass slab on Glass slab - black box inside this is due to orginal code having drawtype = normal for glassslab on glassslab combo
|
|
|
|
local v1_is_glass = string.find(string.lower(tostring(v1)), "glass") -- Slabs dont use drawtype "glasslike" in stairs due to nodebox requirement,
|
|
local v2_is_glass = string.find(string.lower(tostring(v2)), "glass") -- so using name string match but this pretty unreliable.
|
|
-- returns value nil if not otherwise returns integar see lua string.find
|
|
|
|
if v1_is_glass and v2_is_glass then -- glass_glass nodes so drawtype = glasslike
|
|
minetest.register_node("comboblock:"..v1:split(":")[2].."_onc_"..v2:split(":")[2], { -- registering the new combo node
|
|
description = v1_def.description.." on "..v2_def.description,
|
|
tiles = {v1_tiles[1].name.."^[resize:"..cs.."x"..cs,
|
|
v2_tiles[2].name.."^[resize:"..cs.."x"..cs,
|
|
v1_tiles[3].name.."^[resize:"..cs.."x"..cs..v2_tiles[3].name, -- Stairs registers it's tiles slightly differently now
|
|
v1_tiles[4].name.."^[resize:"..cs.."x"..cs..v2_tiles[4].name, -- in a nested table structure and now makes use of
|
|
v1_tiles[5].name.."^[resize:"..cs.."x"..cs..v2_tiles[5].name, -- align_style = "world" for most slabs....I think
|
|
v1_tiles[6].name.."^[resize:"..cs.."x"..cs..v2_tiles[6].name
|
|
},
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
drawtype = "glasslike",
|
|
sounds = v1_def.sounds,
|
|
groups = v1_groups,
|
|
drop = "",
|
|
comboblock_v1 = tostring(v1),
|
|
comboblock_v2 = tostring(v2),
|
|
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
cb_after_dig_node(pos, oldnode, oldmetadata, digger)
|
|
end })
|
|
|
|
elseif not v1_is_glass and not v2_is_glass then -- normal nodes
|
|
|
|
minetest.register_node("comboblock:"..v1:split(":")[2].."_onc_"..v2:split(":")[2], {
|
|
description = v1_def.description.." on "..v2_def.description,
|
|
tiles = {v1_tiles[1].name.."^[resize:"..cs.."x"..cs,
|
|
v2_tiles[2].name.."^[resize:"..cs.."x"..cs,
|
|
v1_tiles[3].name.."^[resize:"..cs.."x"..cs..v2_tiles[3].name, -- Stairs registers it's tiles slightly differently now
|
|
v1_tiles[4].name.."^[resize:"..cs.."x"..cs..v2_tiles[4].name, -- in a nested table structure and now makes use of
|
|
v1_tiles[5].name.."^[resize:"..cs.."x"..cs..v2_tiles[5].name, -- align_style = "world" for most slabs....I think
|
|
v1_tiles[6].name.."^[resize:"..cs.."x"..cs..v2_tiles[6].name
|
|
},
|
|
paramtype2 = "facedir",
|
|
drawtype = "normal",
|
|
sounds = v1_def.sounds,
|
|
groups = v1_groups,
|
|
drop = "",
|
|
comboblock_v1 = tostring(v1),
|
|
comboblock_v2 = tostring(v2),
|
|
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
cb_after_dig_node(pos, oldnode, oldmetadata, digger)
|
|
end })
|
|
else
|
|
-- Can't have a nodetype as half "glasslike" and half "normal" :(
|
|
end
|
|
|
|
node_count = node_count+1
|
|
end
|
|
end-- v2_tiles for end
|
|
|
|
|
|
-- Override all slabs registered on_place function
|
|
|
|
minetest.override_item(v1, {
|
|
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
local pos = pointed_thing.under
|
|
local placer_pos = placer:get_pos()
|
|
local err_mix = S("Hmmmm... that wont work I can't mix glass slabs and none glass slabs")-- error txt for mixing glass/not glass
|
|
local err_un = S("Hmmmm... The slab wont fit there, somethings in the way") -- error txt for unknown/unexpected
|
|
local pla_is_glass = string.find(string.lower(tostring(itemstack:get_name())), "glass") -- itemstack item glass slab (trying to place item) - cant use drawtype as slabs are all type = nodebox
|
|
local node_c = minetest.get_node({x=pos.x, y=pos.y, z=pos.z}) -- node clicked
|
|
local node_c_is_glass = string.find(string.lower(tostring(node_c.name)), "glass") -- is node clicked glass
|
|
|
|
-- Setup Truth table
|
|
local pgn = "F" -- Place is_Glass Node
|
|
local cgn = "F" -- Click is_Glass Node
|
|
|
|
-- Check truth table variables and switch "T"
|
|
if pla_is_glass then pgn = "T" end
|
|
if node_c_is_glass then cgn = "T" end
|
|
|
|
local comboblock_truthtable_rel_axis_horiz = {
|
|
-- User clicked top/bottom surface slab and slab is Horizontal
|
|
-- Place Glass, Click Glass
|
|
-- [ T , T ] - top record table key spaced out
|
|
["TT"] = {itemstack:get_name(), "clicked"}, -- New: Outcome Two
|
|
["TF"] = {err = err_mix}, -- New: Error Two
|
|
["FT"] = {err = err_mix}, -- New: Error One
|
|
["FF"] = {itemstack:get_name(), "clicked"}} -- New: Outcome One
|
|
|
|
-- Used to identify potential half slab deep axis
|
|
local comboblock_param_side_offset = {
|
|
--xyz -- 1st axis = face dir, 2nd two used for placement
|
|
["100"] = {"x","y","z"},
|
|
["010"] = {"y","x","z"},
|
|
["001"] = {"z","y","x"}}
|
|
|
|
local comboblock_p2_axis = {
|
|
["100"] = {l = 4, r = 10, t = 22, b = 0, m = 15}, -- +X
|
|
["-100"] = {l = 10, r = 4, t = 22, b = 0, m = 17}, -- -X
|
|
["010"] = {l = 4, r = 10, t = 19, b = 13, m = 0}, -- +Y
|
|
["0-10"] = {l = 10, r = 4, t = 19, b = 13, m = 22}, -- -Y
|
|
["001"] = {l = 13, r = 19, t = 22, b = 0, m = 6}, -- +Z
|
|
["00-1"] = {l = 19, r = 13, t = 22, b = 0, m = 8}} -- -Z
|
|
|
|
|
|
-- clicked side for slabs can either be on node boundry or sunk in half
|
|
-- node depth. Need to identify the clicked side and later check if it's
|
|
-- == 0 or not. Doing slabs this way means remaining code can effectively ignore
|
|
-- axis and param2 except for final placement.
|
|
local pointed = combo_raycast(placer)
|
|
local point = vector.subtract(pointed.intersection_point,pointed.under)
|
|
local normal = pointed.intersection_normal
|
|
local nor_string = tostring(math.abs(normal.x)..math.abs(normal.y)..math.abs(normal.z))
|
|
local pot_short_axis = point[comboblock_param_side_offset[nor_string][1]] -- When == 0 large flat side is inside node
|
|
local node_ax_pos = vector.add(pos,normal)
|
|
local node_along_axis = minetest.get_node(node_ax_pos) -- retrieve the node along +- axis for xyz
|
|
local node_ax_is_slab = minetest.registered_nodes[node_along_axis.name].groups.slab -- is node along axis in slab group
|
|
local node_ax_is_build = minetest.registered_nodes[node_along_axis.name].buildable_to -- true/false
|
|
local node_ax_is_glass = string.find(string.lower(tostring(node_along_axis.name)), "glass") -- is node glass
|
|
local is_prot = minetest.is_protected(pos,placer:get_player_name())
|
|
|
|
if pot_short_axis == 0 and not is_prot then -- Clicked inside existing node with slab
|
|
local outcome = comboblock_truthtable_rel_axis_horiz[pgn..cgn]
|
|
local combo_name = cb_get_name(outcome,placer,node_c.name)
|
|
|
|
if outcome.err == nil then -- Cant mix glass and normal slabs
|
|
minetest.swap_node(pos,{name=combo_name, param2=node_c.param2})
|
|
itemstack:take_item(1)
|
|
end
|
|
|
|
elseif node_ax_is_build then -- Clicked surface and node along axis is_buildable
|
|
local hor = comboblock_param_side_offset[nor_string][3]
|
|
local ver = comboblock_param_side_offset[nor_string][2]
|
|
|
|
-- Switchs left/right when -/+ axis face clicked
|
|
local multi = normal[comboblock_param_side_offset[nor_string][1]]
|
|
local p2 = 0
|
|
|
|
-- top(t)/bot(b)/left(l)/right(r) are fairly meaningless just labels - align on X
|
|
if math.abs(point[hor]) < 0.25 and math.abs(point[ver]) < 0.25 then
|
|
p2 = comboblock_p2_axis[tostring(normal.x..normal.y..normal.z)]["m"]
|
|
|
|
elseif multi*point[hor] >= math.abs(point[ver]) then
|
|
p2 = comboblock_p2_axis[tostring(normal.x..normal.y..normal.z)]["r"]
|
|
|
|
elseif multi*-point[hor] >= math.abs(point[ver]) then
|
|
p2 = comboblock_p2_axis[tostring(normal.x..normal.y..normal.z)]["l"]
|
|
|
|
elseif point[ver] >= math.abs(point[hor]) then
|
|
p2 = comboblock_p2_axis[tostring(normal.x..normal.y..normal.z)]["t"]
|
|
|
|
elseif -point[ver] >= math.abs(point[hor]) then
|
|
p2 = comboblock_p2_axis[tostring(normal.x..normal.y..normal.z)]["b"]
|
|
|
|
end
|
|
|
|
minetest.item_place(itemstack, placer, pointed_thing, p2)
|
|
|
|
elseif node_ax_is_slab and not is_prot then -- Clicked surface and node along axis is_slab
|
|
-- use node_along_axis instead of node clicked
|
|
-- recalc our clicked glass node true/false using node_along_axis as sub
|
|
if node_ax_is_glass then cgn = "T" end
|
|
|
|
-- same process as our 1st if now but sub in node_along_axis details
|
|
local outcome = comboblock_truthtable_rel_axis_horiz[pgn..cgn]
|
|
local combo_name = cb_get_name(outcome,placer,node_along_axis.name)
|
|
|
|
if outcome.err == nil then -- Cant mix glass and normal slabs
|
|
minetest.swap_node(node_ax_pos,{name=combo_name, param2=node_along_axis.param2})
|
|
itemstack:take_item(1)
|
|
end
|
|
|
|
else -- Last error catch
|
|
local name = placer:get_player_name()
|
|
minetest.chat_send_player(name ,err_un) -- New:Unknown Case
|
|
|
|
end
|
|
|
|
if not creative.is_enabled_for(placer:get_player_name()) then
|
|
return itemstack
|
|
end
|
|
end })
|
|
end
|
|
end |