side is a string: "U" = +Y = up/top "D" = -Y = down/bottom "N" = +Z = north "S" = -Z = south "E" = +X = east "W" = -X = west API has utility functions to get a node's side node_io.get_target_side(pos, target_pos) -> side -- pos is position of transfer node and target_pos is position of inventory node -- returns the side on inventory node node_io.get_pointed_side(pointer, pointed_thing) -> side -- pointer is player and pointed_thing is the node player is pointing at -- returns the side of node the player is pointing at node definition implements all or some of these functions: node_io_can_put_item(pos, node, side) -> bool node_io_can_put_liquid(pos, node, side) -> bool node_io_can_take_item(pos, node, side) -> bool node_io_can_take_liquid(pos, node, side) -> bool node_io_accepts_millibuckets(pos, node, side) -> bool -- if false, transfer node should only put and take in 1000 increments -- inventory nodes that don't accept milibuckets should: -- return zero in node_io_room_for_liquid() if non-1000 increment -- return millibuckets parameter in node_io_put_liquid() if non-1000 increment -- only return upto a 1000 increment in node_io_take_liquid() -- transfer nodes that can put non-1000 increments should always check this or the inventory node might pretend to be full node_io_put_item(pos, node, side, putter, itemstack) -- returns itemstack with leftovers or cleared -- putter is a fake player node_io_put_liquid(pos, node, side, putter, liquid, millibuckets) -- returns millibuckets with leftovers or zero if all was stored -- liquid should be the name of a source liquid (in bucket.liquids of bucket mod) -- 1 bucket or source block is 1000 millibuckets node_io_room_for_item(pos, node, side, itemstack, count) -> int -- ignore count in itemstack, only use the count parameter -- returns count if inventory can hold entire stack, else returns amount the inventory can hold -- use count=1 to check if not full, then call put_item() with actual amount to transfer -- the non-zero return count is needed by transfer nodes that take from one inventory node and put in another inventory node node_io_room_for_liquid(pos, node, side, liquid, millibuckets) -> int -- returns millibuckets if inventory can hold entire amount, else returns amount the inventory can hold -- use millibuckets=1 to check if not full, then call put_liquid() with actual amount to transfer -- use millibuckets=1000 with room_for_liquid() and put_liquid() to only insert full buckets node_io_take_item(pos, node, side, taker, want_item, want_count) -- returns an itemstack with <= want_count or nil if inventory is empty or doesn't have want_item -- taker is a fake player -- want_item should be nil for any item, contain a string with item name to filter by name or contain an itemstack to filter by name, wear and metadata -- want_count should be greater than zero -- returned itemstack shouldn't exceed max stack size, even if want_count does node_io_take_liquid(pos, node, side, taker, want_liquid, want_millibuckets) -- returns {name:string, millibuckets:int} with <= want_millibuckets or nil if inventory is empty or doesn't have want_liquid -- want_liquid should be the name of a source liquid (in bucket.liquids of bucket mod) -- items and liquid should not be put back after taken -- use the following API to check if taken item can be used/stored before taking it node_io_get_item_size(pos, node, side) -> number of item inventory slots -- can be used to iterate over an inventory -- for i = 1, size do ... end node_io_get_liquid_size(pos, node, side) -> number of liquid inventory slots -- this is always 1 unless inventory can hold multiple liquid types node_io_get_item_name(pos, node, side, index) -> item name -- can be used to get the name of the stack in inventory slot, and determine if it will fit in local inventory before taking it -- want_count parameter for take_*() can be adjusted to only take what will fit in local inventory -- return value should be a string with name or empty string node_io_get_liquid_name(pos, node, side, index) -> liquid name node_io_get_item_stack(pos, node, side, index) -> item itemstack -- can be used to get a copy of the itemstack in inventory slot, and determine if it will fit in local inventory before taking it -- want_count parameter for take_*() can be adjusted to only take what will fit in local inventory -- return value should be an itemstack with count=1 or nil node_io_get_liquid_stack(pos, node, side, index) -> liquid itemstack -- TODO: support power and signals API has utility functions for transfer nodes to easily call every node function above -- node_io.can_put_item() calls ndef.node_io_can_put_item() -- the can_put_* functions should always be called before using the room_for_* or put_* functions on an inventory node -- the can_take_* functions should always be called before using the get_*_size, get_*_name, get_*_stack or take_* functions on an inventory node API has utility functions for standard inventory nodes to easily implement the API -- pos parameter can be: -- {x=, y=, z=} -- {type="node", pos={x=, y=, z=}} -- {type="detached", name=""} -- {type="player", name=""} node_io.compare_itemstack(itemstack1, itemstack2) -> bool -- returns true if both itemstacks are identical, excluding count node_io.room_for_item_in_inventory(inv, inv_name, itemstack, count) -> int -- call from node_io_room_for_item() node_io.get_inventory_size(pos, inv_name) -- call from node_io_get_item_size() node_io.get_inventory_name(pos, inv_name, index) -- call from node_io_get_item_name() node_io.get_inventory_stack(pos, inv_name, index) -- call from node_io_get_item_stack() node_io.put_item_in_inventory(pos, node, inv_name, putter, itemstack) -- call from node_io_put_item() node_io.take_item_from_inventory(pos, node, inv_name, taker, want_item, want_count) -- call from node_io_take_item() node_io.init_main_inventory(node_name, allow_take) -- implement the API for standard inventory nodes that have a single "main" inventory See default_support.lua for API implementation in default:chest and default:furnace inventory nodes. See patches/hopper-tenplus1.patch for example API use by the hopper:hopper transfer node.