Page 1 of 1

Get All Nodes in a Group

PostPosted: Thu Jul 07, 2016 19:28
by octacian
Is there a way to get all the nodes in a group as a table? I'm trying for a simpler way to override trees and leaves for my hardtrees mod. Currently I have to manually add an entry for every tree, leaves node, and sapling. If I could get all the nodes in a group as a table, I could then iterate over each redefining needed properties.

Re: Get All Nodes in a Group

PostPosted: Thu Jul 07, 2016 19:44
by blert2112
Simple enough. Spin through the registered nodes and look for the groups you require. When you find one add it to a table.

Re: Get All Nodes in a Group

PostPosted: Thu Jul 07, 2016 19:45
by octacian
And how do I do that?

Re: Get All Nodes in a Group

PostPosted: Thu Jul 07, 2016 23:40
by blert2112
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local function registered_nodes_by_group(group)
   local result = {}
   for name, def in pairs(minetest.registered_nodes) do
      if def.groups[group] then
         result[#result+1] = name
      end
   end
   return result
end

Re: Get All Nodes in a Group

PostPosted: Fri Jul 08, 2016 00:13
by octacian
This is what I tried:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
-- get nodes in group and store in result table
function hardtrees.get_nodes(group)
  local result = {} -- define blank table
  local i = 1 -- for variable
  for name, def in pairs(minetest.registered_nodes) do
    if def.groups[group] then
      result[i] = name
      i = i + 1
    end
  end
  return result -- return result table
end

-- override tree nodes
local tree = hardtrees.get_nodes("tree")
-- for loop to override tree nodes
for i, tree in pairs(tree) do
  hardtrees.override.tree(tree[i])
end

-- override leaves nodes
local leaf = hardtrees.get_nodes("leaves") -- get leaves
local sapling = hardtrees.get_nodes("sapling") -- get sapling
-- for loop to override nodes
for i,leaf,sapling in pairs(leaf,sapling) do
  hardtrees.override.leaf(leaf[i], sapling[i])
end


I get an error on hardtrees.override.tree(tree[i]) (a function defined to override the trees). I don't think I'm structuring the for loop properly, however, that's one thing I am really new to. Thanks for your help.

Re: Get All Nodes in a Group

PostPosted: Fri Jul 08, 2016 02:15
by blert2112
I don't know what your other functions are doing but, the example I posted simply returns a table of node names.
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local function registered_nodes_by_group(group)
   local result = {}
   for name, def in pairs(minetest.registered_nodes) do
      if def.groups[group] then
         result[#result+1] = name
      end
   end
   return result
end

local grouped_trees = registered_nodes_by_group("tree")

for i = 1, #grouped_trees do
   minetest.override_item(grouped_trees[i], {
      -- override stuff here
   })
end

In your code above you are probably looking to use 'ipairs' instead of 'pairs'. You should also avoid using globals unless the object is to be used by other mods. Registration stuff rarely needs globals. Globals are slow compared to locals, and more importantly, are never cleared from memory.

Re: Get All Nodes in a Group

PostPosted: Sat Jul 09, 2016 02:36
by blert2112
I fiddled around with the function. You can send this one all three groups (or more, or less) at once and it will return a grouped table. This way you only have to loop through the registered nodes once instead of three times.
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local function registered_nodes_by_group(groups, allow_duplicates)
   if type(groups) ~= "table" then
      return nil
   end

   allow_duplicates = allow_duplicates or false

   local g_cnt = #groups

   local result = {}
   for i = 1, g_cnt do
      result[groups[i]] = {}
   end

   for name, def in pairs(minetest.registered_nodes) do
      for i = 1, g_cnt do
         local grp = groups[i]
         if def.groups[grp] then
            result[grp][#result[grp]+1] = name
            if allow_duplicates == false then
               break
            end
         end
      end
   end

   return result
end

local grouped_nodes = registered_nodes_by_group({"tree", "leaves", "sapling"})

The following is what is returned from vanilla Minetest_Game:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
return {
   ["leaves"] = {"default:leaves", "default:pine_needles", "default:acacia_leaves", "default:jungleleaves", "default:aspen_leaves"},
   ["sapling"] = {"default:sapling", "default:junglesapling", "default:pine_sapling", "default:aspen_sapling", "default:acacia_sapling"},
   ["tree"] = {"default:pine_tree", "default:acacia_tree", "default:tree", "default:aspen_tree", "default:jungletree"}
}

Note: If 'allow_duplicates' = true then nodes that match two or more groups will be added to all matching sub-tables. If false, or not sent, then nodes will be added to the sub-table of the first group it matches.