Xpanes: Convert to connected nodeboxes
authorAuke Kok <sofar@foo-projects.org>
Thu, 17 Mar 2016 07:40:30 +0000 (00:40 -0700)
committerparamat <mat.gregory@virginmedia.com>
Sat, 10 Sep 2016 04:18:02 +0000 (05:18 +0100)
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.

game_api.txt
mods/xpanes/README.txt
mods/xpanes/init.lua
mods/xpanes/license.txt

index 2f0715f8d57d1bd9c16e1f2dbb63f3fc4b7babb2..9e8d496388020964bb29825264a759e8943c9f86 100644 (file)
@@ -421,7 +421,7 @@ Creates panes that automatically connect to each other
 ### 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]
                sounds = SoundSpec,        -- See [#Default sounds]
                recipe = {{"","","","","","","","",""}}, -- Recipe field only
index 72dd76e8e4da2abf7ce7c5a0b3674166fddc1c13..b72e19a8aa94ca12aa5485762c3ea0b8080db0eb 100644 (file)
@@ -6,6 +6,7 @@ Authors of source code
 ----------------------
 Originally by xyz (MIT)
 BlockMen (MIT)
+sofar (MIT)
 Various Minetest developers and contributors (MIT)
 
 Authors of media (textures)
index 9189912e629e5d0d709cf9de12ea07c3c9b009a8..dc7428facdbd65b1f93346a05b115a374d68b50e 100644 (file)
-xpanes = {}
 
-local function rshift(x, by)
-       return math.floor(x / 2 ^ by)
+local function is_pane(pos)
+       return minetest.get_item_group(minetest.get_node(pos).name, "pane") > 0
 end
 
-local directions = {
-       {x = 1, y = 0, z = 0},
-       {x = 0, y = 0, z = 1},
-       {x = -1, y = 0, z = 0},
-       {x = 0, y = 0, z = -1},
-}
-
-local function update_pane(pos, name)
-       if not minetest.get_node(pos).name:find("^xpanes:"..name) then
-               return
+local function connects_dir(pos, name, dir)
+       local aside = vector.add(pos, minetest.facedir_to_dir(dir))
+       if is_pane(aside) then
+               return true
        end
-       local sum = 0
-       for i, dir in pairs(directions) do
-               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
+
+       local connects_to = minetest.registered_nodes[name].connects_to
+       if not connects_to then
+               return false
        end
-       if sum == 0 then
-               sum = 15
+       local list = minetest.find_nodes_in_area(aside, aside, connects_to)
+
+       if #list > 0 then
+               return true
        end
-       minetest.set_node(pos, {name = "xpanes:"..name.."_"..sum})
+
+       return false
 end
 
-local function update_nearby(pos, node)
-       node = node or minetest.get_node(pos)
-       local name = node.name
-       if not name or node.name:sub(1, 7) ~= "xpanes:" then
+local function swap(pos, node, name, param2)
+       if node.name == name and node.param2 == param2 then
                return
        end
-       local underscore_pos = string.find(name, "_[^_]*$") or 0
-       local len = name:len()
-       local num = tonumber(name:sub(underscore_pos+1, len))
-       if not num or num < 1 or num > 15 then
-               name = name:sub(8)
-       else
-               name = name:sub(8, underscore_pos - 1)
-       end
-       for i, dir in pairs(directions) do
-               update_pane(vector.add(pos, dir), name)
-       end
+
+       minetest.set_node(pos, {name = name, param2 = param2})
 end
 
-minetest.register_on_placenode(update_nearby)
-minetest.register_on_dignode(update_nearby)
-
-local half_boxes = {
-       {0,     -0.5, -1/32, 0.5,  0.5, 1/32},
-       {-1/32, -0.5, 0,     1/32, 0.5, 0.5},
-       {-0.5,  -0.5, -1/32, 0,    0.5, 1/32},
-       {-1/32, -0.5, -0.5,  1/32, 0.5, 0}
-}
-
-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,
-}
+local function update_pane(pos)
+       if not is_pane(pos) then
+               return
+       end
+       local node = minetest.get_node(pos)
+       local name = node.name
+       if name:sub(-5) == "_flat" then
+               name = name:sub(1, -6)
+       end
 
-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])
+       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
-               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
+
+       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
+                       swap(pos, node, name, 0)
                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
-                       }
-               })
+       else
+               swap(pos, node, name, 0)
+       end
+end
+
+minetest.register_on_placenode(function(pos, node)
+       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)
 
-       for k, v in pairs(pane_def_fields) do
-               def[k] = def[k] or v
+minetest.register_on_dignode(function(pos)
+       for i = 0, 3 do
+               local dir = minetest.facedir_to_dir(i)
+               update_pane(vector.add(pos, dir))
        end
+end)
 
-       def.on_construct = function(pos)
-               update_pane(pos, name)
+xpanes = {}
+function xpanes.register_pane(name, def)
+       for i = 1, 15 do
+               minetest.register_alias("xpanes:" .. name .. "_" .. i, "xpanes:" .. name .. "_flat")
        end
 
-       minetest.register_node(":xpanes:"..name, def)
+       local flatgroups = table.copy(def.groups)
+       flatgroups.pane = 1
+       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" },
+       })
+
+       local groups = table.copy(def.groups)
+       groups.pane = 1
+       groups.not_in_creative_inventory = 1
+       minetest.register_node(":xpanes:" .. name, {
+               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({
-               output = "xpanes:"..name.." 16",
+               output = "xpanes:" .. name .. "_flat 16",
                recipe = def.recipe
        })
 end
@@ -161,7 +151,7 @@ xpanes.register_pane("pane", {
        inventory_image = "default_glass.png",
        wield_image = "default_glass.png",
        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 = {
                {"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"},
        inventory_image = "xpanes_bar.png",
        wield_image = "xpanes_bar.png",
-       groups = {cracky=2, pane=1},
+       groups = {cracky=2},
        sounds = default.node_sound_stone_defaults(),
        recipe = {
                {"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
+})
index ef25be79ba15183e5087cb742e062b6607187fc4..66c6fbfa1ccf10191f1488b08249de93efe36716 100644 (file)
@@ -4,6 +4,7 @@ License of source code
 The MIT License (MIT)
 Copyright (C) 2014-2016 xyz
 Copyright (C) 2014-2016 BlockMen
+Copyright (C) 2016 Auke Kok <sofar@foo-projects.org>
 Copyright (C) 2014-2016 Various Minetest developers and contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this