Using hopper.lua as a library - umnikos/hopper.lua GitHub Wiki
Basic usage
Hopper.lua can be used within scripts by importing the file as a library. This will give you a function called hopper, which accepts an arguments string with the exact same syntax as the command line interface. This is better than using shell.run() to call hopper.lua because it allows for caching various data and thus way faster transfer. The function passes -once -quiet by default, use -forever if you want to override -once.
Usage of storages and aliases is also supported. Simply use -storage or -alias in a command and the definition will be remembered for all further commands.
Example program to autocraft buckets: (Chest ender_storage_6958 is full of iron ingots and chest ender_storage_6959 is where the finished buckets should go. The program is written in such a way as to not break if the turtle randomly gets rebooted or the source chest runs out of iron ingots)
local hopper = require("hopper")
-- setup aliases for convenience
hopper("-alias iron *storage*_6958")
hopper("-alias output *storage*_6959")
turtle.select(16)
while true do
-- fill inventory with iron
hopper("iron self *:iron_ingot -to-slot 1 -to-slot 3 -to-slot 6 -to-limit 16 -per-slot")
-- check how many slots have at least 1 iron ingot in them
local count = hopper("self void *:iron_ingot -transfer-limit 1 -per-slot")
if count >= 3 then
-- all is good, craft!
turtle.craft(16)
end
-- regardless of success, output the buckets
hopper("self output *bucket* -to-slot-range 1 9")
sleep(1)
end
Intermediate usage
Listing
hopper.list() exists for conveniently fetching the contents of a set of inventories.
Example:
local hopper = require("hopper")
local amounts = hopper.list("*chest*")
print(amounts["minecraft:cobblestone"])
This is currently less flexible than hoppering into void, but it lets you get an entire list of amounts instead of just a single number.
Logging
As a second argument to hopper() you can pass a table of logging functions which will be called as hopper.lua runs. Currently the only hook that exists is the transferred function field, which is called every time a successful transfer happens and is given information about said transfer
Example: The following code is just hopper left right but will print out information about every individual item transfer to the terminal
local hopper = require("hopper")
local pprint = require("cc.pretty").pretty_print
local logging = {
transferred = pprint
}
hopper("left right", logging)
Advanced usage
Instead of passing a string to hopper() it's possible to pass a table describing the desired operation. This is mostly useful for programmatic query construction as it's less convenient but more structured when compared to passing a string.
The following is a description of the table-based api as of v1.4.5, written in the style of TypeScript code:
function hopper(commands: CommandList, logging?: LoggingHooks)
type CommandList = Command[] | Command
type Command = string | {
from: string,
to: string,
filters?: Filters,
limits?: Limits,
from_slot?: SlotSpecifier,
to_slot?: SlotSpecifier,
once?: boolean,
// most flags can be used through this api by using
// their name as the key and then a list of arguments as the value
// if the flag doesn't normally have an argument just pass in a dummy value
[flagname: string]: (string | number)[] | string | number,
}
type Filters = Filter[] | Filter
type Filter = string | FilterTable | FilterFunction
type FilterTable = {
// at least one of these must be supplied
// supplying multiple of these "and"s them together
name?: string,
nbt?: string,
tag?: string, // *without* the "$" at the start
}
type FilterFunction = (FilterFunctionInformation) => boolean
type FilterFunctionInformation = {
chest_name: string,
chest_size: number | nil, // output of .size() if such a method exists
slot_number: number, // 0 if there's none
name: string,
nbt: string, // "" if there's no nbt data or if the data is unknown and assumed to be none
count: number,
type: "i" | "f" | "e", // item, fluid, energy
tags: {[tag: string]: true}, // result of getItemDetail(...).tags
}
type Limits = Limit[] | Limit
type Limit = {
type: "from" | "to" | "transfer",
dir?: "min" | "max",
limit: number,
per_slot?: boolean,
per_chest?: boolean,
per_name?: boolean,
per_nbt?: boolean,
count_all?: boolean,
}
type SlotSpecifier = number | (number | NumberRange)[]
type NumberRange = [number, number]
type LoggingHooks = {
transferred?: (record: TransferRecord) => void,
}
type TransferRecord = {
transferred: number,
from: string,
to: string,
name: string,
displayName: string | nil, // nil if the display name is unknown
nbt: string, // "" if there's no nbt data or if the data is unknown and assumed to be none
type: "i" | "f" | "e", // item, fluid, energy
}