hopper/api.lua
Ajrat Makhmutov df5f8d8379 Add multi-node containers support
+ remove trailing spaces
+ add new api for extra information about containers
2024-08-17 09:20:43 +02:00

170 lines
5.3 KiB
Lua

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