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

View File

@ -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

View File

@ -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)

View File

@ -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))
local def = minetest.registered_nodes[node.name]
local pane_num = def and def.groups.pane or 0
if pane_num > 0 or not def or (def.walkable ~= false and
def.drawtype ~= "nodebox") then
sum = sum + 2 ^ (i - 1)
end
end
if sum == 0 then
sum = 15
end
minetest.set_node(pos, {name = "xpanes:"..name.."_"..sum})
end end
local function update_nearby(pos, node) local function update_pane(pos)
node = node or minetest.get_node(pos) if not is_pane(pos) then
return
end
local node = minetest.get_node(pos)
local name = node.name local name = node.name
if not name or node.name:sub(1, 7) ~= "xpanes:" then if name:sub(-5) == "_flat" then
return name = name:sub(1, -6)
end end
local underscore_pos = string.find(name, "_[^_]*$") or 0
local len = name:len() local any = node.param2
local num = tonumber(name:sub(underscore_pos+1, len)) local c = {}
if not num or num < 1 or num > 15 then local count = 0
name = name:sub(8) for dir = 0, 3 do
c[dir] = connects_dir(pos, name, dir)
if c[dir] then
any = dir
count = count + 1
end
end
if count == 0 then
swap(pos, node, name .. "_flat", any)
elseif count == 1 then
swap(pos, node, name .. "_flat", (any + 1) % 4)
elseif count == 2 then
if (c[0] and c[2]) or (c[1] and c[3]) then
swap(pos, node, name .. "_flat", (any + 1) % 4)
else else
name = name:sub(8, underscore_pos - 1) swap(pos, node, name, 0)
end end
for i, dir in pairs(directions) do else
update_pane(vector.add(pos, dir), name) swap(pos, node, name, 0)
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 = { xpanes = {}
{-0.5, -0.5, -1/32, 0.5, 0.5, 1/32}, function xpanes.register_pane(name, def)
{-1/32, -0.5, -0.5, 1/32, 0.5, 0.5} for i = 1, 15 do
} minetest.register_alias("xpanes:" .. name .. "_" .. i, "xpanes:" .. name .. "_flat")
end
local sb_half_boxes = { local flatgroups = table.copy(def.groups)
{0, -0.5, -0.06, 0.5, 0.5, 0.06}, flatgroups.pane = 1
{-0.06, -0.5, 0, 0.06, 0.5, 0.5}, minetest.register_node(":xpanes:" .. name .. "_flat", {
{-0.5, -0.5, -0.06, 0, 0.5, 0.06}, description = def.description,
{-0.06, -0.5, -0.5, 0.06, 0.5, 0} drawtype = "nodebox",
}
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", paramtype = "light",
is_ground_content = false, is_ground_content = false,
sunlight_propagates = true, sunlight_propagates = true,
walkable = false, inventory_image = def.inventory_image,
pointable = false, wield_image = def.wield_image,
diggable = false, paramtype2 = "facedir",
buildable_to = true, tiles = {def.textures[3], def.textures[3], def.textures[1]},
air_equivalent = true, groups = flatgroups,
} drop = "xpanes:" .. name .. "_flat",
function xpanes.register_pane(name, def)
for i = 1, 15 do
local need = {}
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, sounds = def.sounds,
node_box = { node_box = {
type = "fixed", type = "fixed",
fixed = take fixed = {{-1/2, -1/2, -1/32, 1/2, 1/2, 1/32}},
}, },
selection_box = { selection_box = {
type = "fixed", type = "fixed",
fixed = take2 fixed = {{-1/2, -1/2, -1/32, 1/2, 1/2, 1/32}},
} },
connect_sides = { "left", "right" },
}) })
end
for k, v in pairs(pane_def_fields) do local groups = table.copy(def.groups)
def[k] = def[k] or v groups.pane = 1
end groups.not_in_creative_inventory = 1
minetest.register_node(":xpanes:" .. name, {
def.on_construct = function(pos) drawtype = "nodebox",
update_pane(pos, name) paramtype = "light",
end is_ground_content = false,
sunlight_propagates = true,
minetest.register_node(":xpanes:"..name, def) 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
})

View File

@ -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