Xpanes: Convert to connected nodeboxes

I've rewritten this to use connected nodeboxes, but with a caveat. In
order to make flat nodes look better, I'm keeping one non-connected
pane that is flat around to convert flat sections to the flat nodes
instead of connected, as these look better and are easier to work
with. Once more sides are needed we convert the panes on the fly to
connected nodes and recalculate the shape.

We don't paint any of the half-panes that the previous generation of
xpanes did. There's no need and it's harder to work with. Updating the
nodes also seems more natural and placement and removal works straight
forward.

The conversion of old panes relies on an LBM, and does a reasonable
conversion job, but it's not exact, since the panes behave slightly
different now.

The game API documentation was wrong to begin with. We discard param
nr. 2 of the API entirely, and correct the tile usage text.
This commit is contained in:
Auke Kok 2016-03-17 00:40:30 -07:00 committed by paramat
parent 992f295880
commit 54235f3276
4 changed files with 137 additions and 134 deletions

@ -421,7 +421,7 @@ Creates panes that automatically connect to each other
### Pane definition ### Pane definition
{ {
textures = {"texture_Bottom_top", "texture_left_right", "texture_front_back"}, -- More tiles aren't supported textures = {"texture for sides", (unused), "texture for top and bottom"}, -- More tiles aren't supported
groups = {group = rating}, -- Uses the known node groups, see [Known damage and digging time defining groups] groups = {group = rating}, -- Uses the known node groups, see [Known damage and digging time defining groups]
sounds = SoundSpec, -- See [#Default sounds] sounds = SoundSpec, -- See [#Default sounds]
recipe = {{"","","","","","","","",""}}, -- Recipe field only recipe = {{"","","","","","","","",""}}, -- Recipe field only

@ -6,6 +6,7 @@ Authors of source code
---------------------- ----------------------
Originally by xyz (MIT) Originally by xyz (MIT)
BlockMen (MIT) BlockMen (MIT)
sofar (MIT)
Various Minetest developers and contributors (MIT) Various Minetest developers and contributors (MIT)
Authors of media (textures) Authors of media (textures)

@ -1,156 +1,146 @@
xpanes = {}
local function rshift(x, by) local function is_pane(pos)
return math.floor(x / 2 ^ by) return minetest.get_item_group(minetest.get_node(pos).name, "pane") > 0
end end
local directions = { local function connects_dir(pos, name, dir)
{x = 1, y = 0, z = 0}, local aside = vector.add(pos, minetest.facedir_to_dir(dir))
{x = 0, y = 0, z = 1}, if is_pane(aside) then
{x = -1, y = 0, z = 0}, return true
{x = 0, y = 0, z = -1}, end
}
local function update_pane(pos, name) local connects_to = minetest.registered_nodes[name].connects_to
if not minetest.get_node(pos).name:find("^xpanes:"..name) then if not connects_to then
return false
end
local list = minetest.find_nodes_in_area(aside, aside, connects_to)
if #list > 0 then
return true
end
return false
end
local function swap(pos, node, name, param2)
if node.name == name and node.param2 == param2 then
return return
end end
local sum = 0
for i, dir in pairs(directions) do minetest.set_node(pos, {name = name, param2 = param2})
local node = minetest.get_node(vector.add(pos, dir)) end
local def = minetest.registered_nodes[node.name]
local pane_num = def and def.groups.pane or 0 local function update_pane(pos)
if pane_num > 0 or not def or (def.walkable ~= false and if not is_pane(pos) then
def.drawtype ~= "nodebox") then return
sum = sum + 2 ^ (i - 1) end
local node = minetest.get_node(pos)
local name = node.name
if name:sub(-5) == "_flat" then
name = name:sub(1, -6)
end
local any = node.param2
local c = {}
local count = 0
for dir = 0, 3 do
c[dir] = connects_dir(pos, name, dir)
if c[dir] then
any = dir
count = count + 1
end end
end end
if sum == 0 then
sum = 15
end
minetest.set_node(pos, {name = "xpanes:"..name.."_"..sum})
end
local function update_nearby(pos, node) if count == 0 then
node = node or minetest.get_node(pos) swap(pos, node, name .. "_flat", any)
local name = node.name elseif count == 1 then
if not name or node.name:sub(1, 7) ~= "xpanes:" then swap(pos, node, name .. "_flat", (any + 1) % 4)
return elseif count == 2 then
end if (c[0] and c[2]) or (c[1] and c[3]) then
local underscore_pos = string.find(name, "_[^_]*$") or 0 swap(pos, node, name .. "_flat", (any + 1) % 4)
local len = name:len() else
local num = tonumber(name:sub(underscore_pos+1, len)) swap(pos, node, name, 0)
if not num or num < 1 or num > 15 then end
name = name:sub(8)
else else
name = name:sub(8, underscore_pos - 1) swap(pos, node, name, 0)
end
for i, dir in pairs(directions) do
update_pane(vector.add(pos, dir), name)
end end
end end
minetest.register_on_placenode(update_nearby) minetest.register_on_placenode(function(pos, node)
minetest.register_on_dignode(update_nearby) if minetest.get_item_group(node, "pane") then
update_pane(pos)
end
for i = 0, 3 do
local dir = minetest.facedir_to_dir(i)
update_pane(vector.add(pos, dir))
end
end)
local half_boxes = { minetest.register_on_dignode(function(pos)
{0, -0.5, -1/32, 0.5, 0.5, 1/32}, for i = 0, 3 do
{-1/32, -0.5, 0, 1/32, 0.5, 0.5}, local dir = minetest.facedir_to_dir(i)
{-0.5, -0.5, -1/32, 0, 0.5, 1/32}, update_pane(vector.add(pos, dir))
{-1/32, -0.5, -0.5, 1/32, 0.5, 0} end
} end)
local full_boxes = {
{-0.5, -0.5, -1/32, 0.5, 0.5, 1/32},
{-1/32, -0.5, -0.5, 1/32, 0.5, 0.5}
}
local sb_half_boxes = {
{0, -0.5, -0.06, 0.5, 0.5, 0.06},
{-0.06, -0.5, 0, 0.06, 0.5, 0.5},
{-0.5, -0.5, -0.06, 0, 0.5, 0.06},
{-0.06, -0.5, -0.5, 0.06, 0.5, 0}
}
local sb_full_boxes = {
{-0.5, -0.5, -0.06, 0.5, 0.5, 0.06},
{-0.06, -0.5, -0.5, 0.06, 0.5, 0.5}
}
local pane_def_fields = {
drawtype = "airlike",
paramtype = "light",
is_ground_content = false,
sunlight_propagates = true,
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
air_equivalent = true,
}
xpanes = {}
function xpanes.register_pane(name, def) function xpanes.register_pane(name, def)
for i = 1, 15 do for i = 1, 15 do
local need = {} minetest.register_alias("xpanes:" .. name .. "_" .. i, "xpanes:" .. name .. "_flat")
local cnt = 0
for j = 1, 4 do
if rshift(i, j - 1) % 2 == 1 then
need[j] = true
cnt = cnt + 1
end
end
local take = {}
local take2 = {}
if need[1] == true and need[3] == true then
need[1] = nil
need[3] = nil
table.insert(take, full_boxes[1])
table.insert(take2, sb_full_boxes[1])
end
if need[2] == true and need[4] == true then
need[2] = nil
need[4] = nil
table.insert(take, full_boxes[2])
table.insert(take2, sb_full_boxes[2])
end
for k in pairs(need) do
table.insert(take, half_boxes[k])
table.insert(take2, sb_half_boxes[k])
end
local texture = def.textures[1]
if cnt == 1 then
texture = def.textures[1].."^"..def.textures[2]
end
minetest.register_node(":xpanes:"..name.."_"..i, {
drawtype = "nodebox",
tiles = {def.textures[3], def.textures[3], texture},
paramtype = "light",
groups = def.groups,
drop = "xpanes:"..name,
sounds = def.sounds,
node_box = {
type = "fixed",
fixed = take
},
selection_box = {
type = "fixed",
fixed = take2
}
})
end end
for k, v in pairs(pane_def_fields) do local flatgroups = table.copy(def.groups)
def[k] = def[k] or v flatgroups.pane = 1
end minetest.register_node(":xpanes:" .. name .. "_flat", {
description = def.description,
drawtype = "nodebox",
paramtype = "light",
is_ground_content = false,
sunlight_propagates = true,
inventory_image = def.inventory_image,
wield_image = def.wield_image,
paramtype2 = "facedir",
tiles = {def.textures[3], def.textures[3], def.textures[1]},
groups = flatgroups,
drop = "xpanes:" .. name .. "_flat",
sounds = def.sounds,
node_box = {
type = "fixed",
fixed = {{-1/2, -1/2, -1/32, 1/2, 1/2, 1/32}},
},
selection_box = {
type = "fixed",
fixed = {{-1/2, -1/2, -1/32, 1/2, 1/2, 1/32}},
},
connect_sides = { "left", "right" },
})
def.on_construct = function(pos) local groups = table.copy(def.groups)
update_pane(pos, name) groups.pane = 1
end groups.not_in_creative_inventory = 1
minetest.register_node(":xpanes:" .. name, {
minetest.register_node(":xpanes:"..name, def) drawtype = "nodebox",
paramtype = "light",
is_ground_content = false,
sunlight_propagates = true,
description = def.description,
tiles = {def.textures[3], def.textures[3], def.textures[1]},
groups = groups,
drop = "xpanes:" .. name .. "_flat",
sounds = def.sounds,
node_box = {
type = "connected",
fixed = {{-1/32, -1/2, -1/32, 1/32, 1/2, 1/32}},
connect_front = {{-1/32, -1/2, -1/2, 1/32, 1/2, -1/32}},
connect_left = {{-1/2, -1/2, -1/32, -1/32, 1/2, 1/32}},
connect_back = {{-1/32, -1/2, 1/32, 1/32, 1/2, 1/2}},
connect_right = {{1/32, -1/2, -1/32, 1/2, 1/2, 1/32}},
},
connects_to = {"group:pane", "group:stone", "group:glass", "group:wood", "group:tree"},
})
minetest.register_craft({ minetest.register_craft({
output = "xpanes:"..name.." 16", output = "xpanes:" .. name .. "_flat 16",
recipe = def.recipe recipe = def.recipe
}) })
end end
@ -161,7 +151,7 @@ xpanes.register_pane("pane", {
inventory_image = "default_glass.png", inventory_image = "default_glass.png",
wield_image = "default_glass.png", wield_image = "default_glass.png",
sounds = default.node_sound_glass_defaults(), sounds = default.node_sound_glass_defaults(),
groups = {snappy=2, cracky=3, oddly_breakable_by_hand=3, pane=1}, groups = {snappy=2, cracky=3, oddly_breakable_by_hand=3},
recipe = { recipe = {
{"default:glass", "default:glass", "default:glass"}, {"default:glass", "default:glass", "default:glass"},
{"default:glass", "default:glass", "default:glass"} {"default:glass", "default:glass", "default:glass"}
@ -173,7 +163,7 @@ xpanes.register_pane("bar", {
textures = {"xpanes_bar.png","xpanes_bar.png","xpanes_space.png"}, textures = {"xpanes_bar.png","xpanes_bar.png","xpanes_space.png"},
inventory_image = "xpanes_bar.png", inventory_image = "xpanes_bar.png",
wield_image = "xpanes_bar.png", wield_image = "xpanes_bar.png",
groups = {cracky=2, pane=1}, groups = {cracky=2},
sounds = default.node_sound_stone_defaults(), sounds = default.node_sound_stone_defaults(),
recipe = { recipe = {
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
@ -181,3 +171,14 @@ xpanes.register_pane("bar", {
} }
}) })
minetest.register_lbm({
name = "xpanes:gen2",
nodenames = {"group:pane"},
action = function(pos, node)
update_pane(pos)
for i = 0, 3 do
local dir = minetest.facedir_to_dir(i)
update_pane(vector.add(pos, dir))
end
end
})

@ -4,6 +4,7 @@ License of source code
The MIT License (MIT) The MIT License (MIT)
Copyright (C) 2014-2016 xyz Copyright (C) 2014-2016 xyz
Copyright (C) 2014-2016 BlockMen Copyright (C) 2014-2016 BlockMen
Copyright (C) 2016 Auke Kok <sofar@foo-projects.org>
Copyright (C) 2014-2016 Various Minetest developers and contributors Copyright (C) 2014-2016 Various Minetest developers and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this Permission is hereby granted, free of charge, to any person obtaining a copy of this