hopper.containers = {} hopper.groups = {} hopper.neighbors = {} local function parse_group(target_node) local number local identifier local equals_index = string.find(target_node, "=") if equals_index ~= nil then identifier = string.sub(target_node, 7, equals_index-1) -- it's possible that the string was of the form "group:blah = 1", in which case we want to trim spaces off the end of the group identifier local space_index = string.find(identifier, " ") if space_index ~= nil then identifier = string.sub(identifier, 1, space_index-1) end number = tonumber(string.sub(target_node, equals_index+1, -1)) else identifier = string.sub(target_node, 7, -1) number = "all" -- special value to indicate no number was provided end return identifier, number end local function is_already_in_neighbors(neighbor_node) for _, value in pairs(hopper.neighbors) do if value == neighbor_node then return true end end return false end -- global function to add new containers function hopper:add_container(list) for _, entry in pairs(list) do local target_node = entry[2] local neighbor_node if string.sub(target_node, 1, 6) == "group:" then local group_identifier, group_number = parse_group(target_node) if hopper.groups[group_identifier] == nil then hopper.groups[group_identifier] = {} end local group = hopper.groups[group_identifier][group_number] if group == nil then group = {} end if group[entry[1]] == nil then group[entry[1]] = {} end group[entry[1]]["inventory_name"] = entry[3] if entry["get_inventory"] then group[entry[1]]["get_inventory"] = entry["get_inventory"] end hopper.groups[group_identifier][group_number] = group neighbor_node = "group:"..group_identifier -- result is a table of the form: -- groups[group_identifier][group_number][relative_position]{"inventory_name","get_inventory"} else local node_info = hopper.containers[target_node] if node_info == nil then node_info = {} end if node_info[entry[1]] == nil then node_info[entry[1]] = {} end node_info[entry[1]]["inventory_name"] = entry[3] if entry["get_inventory"] then node_info[entry[1]]["get_inventory"] = entry["get_inventory"] end hopper.containers[target_node] = node_info neighbor_node = target_node -- result is a table of the form: -- containers[target_node_name][relative_position]{"inventory_name","get_inventory"} end if not is_already_in_neighbors(neighbor_node) then table.insert(hopper.neighbors, neighbor_node) end end end -- global function for additional information about containers function hopper:set_extra_container_info(list) for _, entry in pairs(list) do local target_node = entry[1] table.remove(entry, 1) -- only extra information if string.sub(target_node, 1, 6) == "group:" then local group_identifier, group_number = parse_group(target_node) if not is_already_in_neighbors("group:" .. group_identifier) then minetest.log("error","An attempt to add extra information for " .. target_node .. " in the absence of the main one") break end hopper.groups[group_identifier][group_number].extra = entry -- result is a table of the form: -- groups[group_identifier][group_number]["extra"][list of extra information] else if not is_already_in_neighbors(target_node) then minetest.log("error","An attempt to add extra information for " .. target_node .. " in the absence of the main one") break end hopper.containers[target_node].extra = entry -- result is a table of the form: -- containers[target_node_name]["extra"][list of extra information] end end end -- "top" indicates what inventory the hopper will take items from if this node is located at the hopper's wide end -- "side" indicates what inventory the hopper will put items into if this node is located at the hopper's narrow end and at the same height as the hopper -- "bottom" indicates what inventory the hopper will put items into if this node is located at the hopper's narrow end and either above or below the hopper. hopper:add_container({ {"top", "hopper:hopper", "main"}, {"bottom", "hopper:hopper", "main"}, {"side", "hopper:hopper", "main"}, {"side", "hopper:hopper_side", "main"}, {"bottom", "hopper:chute", "main"}, {"side", "hopper:chute", "main"}, {"bottom", "hopper:sorter", "main"}, {"side", "hopper:sorter", "main"}, }) if minetest.get_modpath("default") then hopper:add_container({ {"top", "default:chest", "main"}, {"bottom", "default:chest", "main"}, {"side", "default:chest", "main"}, {"top", "default:furnace", "dst"}, {"bottom", "default:furnace", "src"}, {"side", "default:furnace", "fuel"}, {"top", "default:furnace_active", "dst"}, {"bottom", "default:furnace_active", "src"}, {"side", "default:furnace_active", "fuel"}, {"top", "default:chest_locked", "main"}, {"bottom", "default:chest_locked", "main"}, {"side", "default:chest_locked", "main"}, }) end -- protector redo mod support if minetest.get_modpath("protector") then hopper:add_container({ {"top", "protector:chest", "main"}, {"bottom", "protector:chest", "main"}, {"side", "protector:chest", "main"}, }) end -- wine mod support if minetest.get_modpath("wine") then hopper:add_container({ {"top", "wine:wine_barrel", "dst"}, {"bottom", "wine:wine_barrel", "src"}, {"side", "wine:wine_barrel", "src"}, }) end