Scripts
Your own macros, in Lua 5.4
A script is a text file that tells Prism what to do, step by step: mine logs until night, go home, wait for the morning, put the logs in a chest. It runs inside the game, so it can use everything the client can, and it keeps going while you do something else.
Scripts are written in Lua, a small language made for this. You do not need to know it well: the example at the bottom is a complete script.
Getting started
How a script runs
- It runs from top to bottom, and ends when it reaches the end. Most scripts are one
while true do ... endloop. wait()pauses only the script, never the game. A loop has to wait at least every 200 ms (await(1000)at its end is plenty), or Prism stops the script so the game does not freeze.- When it ends, any Baritone job it started stops too. Pressing a movement key stops Baritone, and with it a script that drives Baritone.
- While a script runs, Minecraft keeps going when you switch to another window or minimize it, and you keep your mouse.
- An error stops the script and shows the line it was on in your chat.
Settings in the header
Shown in the script's panel
The comment lines at the very top name the script and give it settings. Each setting appears in the script's panel in the click GUI (right click its entry), and the script reads it as settings.key, always the value the panel shows right now.
-- @name Block miner
-- @description Mines blocks; goes home at night
-- @text block "Blocks to mine" "oak_log"
-- @bool store "Put them in the chest" true
-- @int free_slots "Store when free slots are at most" 2 0 36
-- @number pause "Seconds between checks" 1.0 0.1 10
-- @point chest "Storage chest" chest@bool key "Label" true: a switch@int key "Label" default min max: a whole-number slider@number key "Label" default min max: a slider with decimals@text key "Label" "default": a text box@point key "Label" block: a place set with a button, like Schematica's supply chest. Look at the block and press Set Label; the last word is the block it has to be (chest, crafting_table). The script gets{ x=, y=, z= }, or nil while it is not set.
Basics
Timing and output
print(...)- Writes to your chat (only you see it) and to the client log.
notify(text)- A client notification in the corner.
wait(ms)- Pauses this script; the game keeps going. sleep(ms) is the same.
wait_until(fn [, timeout_ms])- Pauses until fn() returns true (checked every frame). Returns false if the timeout ran out first.
millis()- A clock in milliseconds, for timing things yourself.
stop()- Ends this script.
settings.<key>- A setting from the script's header, as its panel shows it right now (see Settings below).
chat
Messages and commands
chat.send(text)- Sends a message or a command: chat.send("/home 2"). Text starting with # goes to Prism's own commands ("#mine oak_log").
chat.print(text)- Shows text in your chat only, with Minecraft's § colour codes.
chat.wait_for(text [, timeout_ms])- Pauses until a chat line containing text arrives (any case). Returns the line, or nil on the timeout: chat.wait_for("Teleported", 5000).
chat.last([n])- The last n chat lines (10 if you leave it out), oldest first, colour codes removed.
player
Position, view, health
player.pos()- x, y, z of your feet. Nothing (nil) outside a world.
player.block()- The block position you stand in, as whole numbers.
player.health(), player.food()- Your health and hunger.
player.in_world()- true while you are in a world (false on menus and loading screens).
player.dead()- true on the death screen.
player.target()- x, y, z of the block your crosshair is on.
player.rotation()- yaw, pitch of your view. Yaw 0 faces south (+Z), pitch 90 looks straight down.
player.look(yaw, pitch [, timeout_ms])- Turns your view there the way the mouse does. true once it gets there.
player.look_at(x, y, z [, timeout_ms])- Turns your view to a point. A block's centre is x + 0.5, y + 0.5, z + 0.5.
player.name()- Your name.
world
Time, blocks, players
world.time()- The time of day, 0 to 23999 (nil when the server does not say).
world.is_day(), world.is_night()- Night is 12542 to 23459, the time beds work. Time Changer does not fool these: they read the real time.
world.block(x, y, z)- The block's name ("stone", "oak_log"), or nil when that part of the world is not loaded.
world.find(pattern, radius [, max])- Blocks matching within radius (up to 48) of you, nearest first: { {x=, y=, z=}, ... }. pattern can be a list: {"*_ore", "chest"}. Big searches take a few ticks.
world.dimension()- "overworld", "nether" or "end".
players
Who is around
world.players([radius])- Players loaded near you, nearest first: { {name=, x=, y=, z=, distance=}, ... }.
world.online()- The names on the server's player list (what Tab shows).
inventory
What you carry
inventory.count(pattern)- How many items match: "oak_log", "*_log" (ends with), "oak_*" (starts with), "*" (anything).
inventory.free()- Empty slots.
inventory.items()- Every stack: { {slot=0, name="oak_log", count=12}, ... }. Slots 0 to 8 are the hotbar.
inventory.selected()- The hotbar slot in hand, and its item.
inventory.select(slot)- Picks hotbar slot 0 to 8.
inventory.find(pattern)- The first slot holding a match, and how many are there. nil when there is none.
inventory.equip(pattern)- Puts a matching item in your hand. Brings it up from the inventory when it is not in the hotbar. true if it worked.
inventory.move(from, to [, count])- Moves a stack, or count items of it, to an empty slot or one with the same item. true, or false and why.
inventory.drop(slot [, count])- Drops a stack, or count items of it. true, or false and why.
craft
Crafting by recipe
craft.make(item [, count [, x, y, z]])- Crafts count items from what you carry, the way the recipe book does. Without a position it uses the 2x2 grid in your inventory. With a crafting table's position it walks there and uses it, for 3x3 recipes. Returns the items made, and an error text.
craft.can(item [, table])- How many you could make right now, and whether it needs a crafting table.
craft.recipes(item)- The recipes that make it: { {item=, makes=, table=, ingredients={ {name=, count=, tag=}, ... }}, ... }. tag=true means any item of that kind ("minecraft:planks").
baritone
Walking and mining
baritone.mine(block, ...)- Mines the blocks named, like #mine.
baritone.goto(x, y, z)- Walks there, like #goto.
baritone.goto_near(x, y, z)- Walks to somewhere that block can be reached from.
baritone.stop()- Stops the job.
baritone.busy()- true while a job runs.
baritone.wait([timeout_ms])- Pauses until the job ends.
baritone.status()- The status line, as the menu shows it.
baritone.command(text)- Any Baritone command: "#dig", "#sbuild", "#select".
container
Chests
container.deposit(x, y, z, pattern, ...)- Walks to the chest, opens it, puts every stack that matches in, closes it. Returns how many items went in, and an error text if something failed ("the chest is full").
container.withdraw(x, y, z, pattern [, count])- The other way round: takes matching stacks out into free slots, up to count items. Returns how many came out, and an error text.
container.click(item, ...)- Presses the first matching item in the open menu, as a click there does (a server's confirm panes: "lime_stained_glass_pane"). true once sent, or false and why.
points
Places you saved
points.get(name)- x, y, z of a point saved with #mark <name> (look at a block and type it in chat). nil if there is none.
points.set(name, x, y, z)- Saves a point from the script.
store
Values kept between runs
store.get(key [, default])- A value this script saved earlier, or default.
store.set(key, value)- Saves true/false, a number or text for next time. nil removes it.
module, input
Modules, keys, clicks
module.enable(name), module.disable(name)- Switches a module, by its name in the menu ("Kill Aura", "Fly").
module.toggle(name), module.enabled(name)- Flips it, or tells whether it is on.
module.get(name, setting), module.set(name, setting, value)- Reads or changes a setting, by the name its panel shows: module.set("Kill Aura", "Range", 3.5). An option is set by its name.
module.list()- Every module's name.
input.click("left" | "right")- A mouse click in the game.
input.key("e" | "1" | "escape" | ...)- A key tap: a letter or digit, escape, enter, space, shift, ctrl, tab.
input.down(key), input.up(key)- Holds a key until you let go: input.down("w") walks forward. Keys still held when the script ends are let go.
Examples
Block miner (comes with Prism)
Mines any blocks with Baritone (oak logs by default, several at once if you list them), comes back to store them when the inventory is nearly full (set the chest near where your come-back command takes you), and goes to your night home at night. After the number you set (64 by default) it comes back (/home 1), stores everything and can die there (/kill, pressing the green confirm pane) to start the next trip with full food and health. The moment you take damage it stops and sends your save command, waits there, then goes back to mining. Set the chest with the Set Storage chest button in its settings.
-- @name Block miner
-- @description Mines any blocks with Baritone and stores them in a chest. Comes back after a number mined, and can kill you there to reset food and health. Day: your mining home; night: your night home. Gets hurt: teleports you to your save home.
-- @text block "Blocks to mine (several: spaces between)" "oak_log"
-- @text items "Items to store (empty: the blocks)" ""
-- @text day_home "Command to go mining" "/home 3"
-- @int trip "Come back after mining this many (0: never)" 64 0 2304
-- @text back_home "Command to come back" "/home 1"
-- @bool suicide "Die after coming back (resets food, health)" true
-- @text suicide_cmd "Command to die" "/kill"
-- @text confirm "Press in the menu that asks (empty: none)" "lime_stained_glass_pane green_stained_glass_pane"
-- @bool night_stop "Stop at night" true
-- @text night_home "Command when it is night" "/home 2"
-- @int tp_wait "Seconds to wait after a teleport" 4 1 20
-- @bool store "Put what you mine in the chest" true
-- @point chest "Storage chest" chest
-- @int free_slots "Come back to store when free slots are at most" 2 0 36
-- @bool save "Save me when I get hurt" true
-- @text save_home "Save command" "/home 1"
-- @int save_rest "Seconds to stay there after a save" 30 5 600
-- @bool save_stop "Stop the script after a save" false
-- Set the chest with the button in this script's settings (look at it, press "Set Storage chest"). Bind a key to the
-- script in the Scripts panel: the key starts it and stops it (stopping it stops the mining too).
-- A trip: it mines until it has gathered the number set (counted from your inventory) or your inventory is nearly full,
-- then sends the come-back command, puts everything in the chest (set it near where that command takes you), and with "Die after coming back" sends
-- the die command, presses the green pane in the menu that asks to confirm it (Donut SMP), respawns and goes mining
-- again with full food and health. Dying drops what you carry unless the
-- server keeps inventories: the chest is filled first, but tools and armour go with you.
-- The save: any damage (a mob, a fall, drowning, lava) stops the mining and sends the save command at once; it stays
-- there for the rest time, then goes back to mining (or stops, if you chose that).
local function words(text)
local out = {}
for word in string.gmatch(text or "", "[^%s,]+") do out[#out + 1] = word end
return out
end
local blocks = words(settings.block)
if #blocks == 0 then
print("Name a block to mine in this script's settings")
return
end
local items = words(settings.items)
if #items == 0 then items = blocks end
local mode = nil -- "day" or "night": what was last done (nil: go again)
local last_health = player.health() or 20
-- What you carry of the items, all patterns together.
local function carried()
local total = 0
for _, pattern in ipairs(items) do total = total + (inventory.count(pattern) or 0) end
return total
end
-- This trip: what you carried when it began, and what went into the chest since.
local trip_base = carried()
local trip_stored = 0
local function new_trip()
trip_base = carried()
trip_stored = 0
end
local function trip_mined()
return math.max(0, carried() - trip_base) + trip_stored
end
-- True when you lost health since the last check (and keeps the newest value).
local function hurt()
local health = player.health()
if not health then return false end
local was = last_health
last_health = health
return health < was - 0.01
end
local function send(command)
if command and command ~= "" then chat.send(command) end
end
local function save()
baritone.stop()
print("Hurt (" .. string.format("%.1f", last_health) .. " health): saving you with " .. settings.save_home)
notify("Block miner: hurt, " .. settings.save_home)
send(settings.save_home)
if settings.save_stop then
wait(settings.tp_wait * 1000)
print("Saved: stopping")
stop()
end
-- Damage while it waits there (still burning, the teleport's delay) does not send the command again.
wait(settings.save_rest * 1000)
last_health = player.health() or last_health
mode = nil -- Back to mining from the start
end
-- Waits ms, saving you the moment you get hurt; true if it did.
local function pause(ms)
local finish = millis() + ms
repeat
if hurt() and settings.save then
save()
return true
end
wait(100)
until millis() >= finish
return false
end
local function teleport(command)
baritone.stop()
send(command)
pause(settings.tp_wait * 1000) -- the teleport and the chunks
end
-- The chest must be near where the come-back command takes you: a walk across the world to it never ends.
local kChestReach = 64
local function store()
local chest = settings.chest
if not chest then
print("No storage chest set: look at it and press \"Set Storage chest\" in this script's settings")
return false
end
local x, y, z = player.pos()
if x then
local far = math.sqrt((chest.x + 0.5 - x) ^ 2 + (chest.y + 0.5 - y) ^ 2 + (chest.z + 0.5 - z) ^ 2)
if far > kChestReach then
print(string.format("The storage chest (%d %d %d) is %d blocks from here (%d %d %d): set it near where %s takes you " ..
"(look at it there and press \"Set Storage chest\")", chest.x, chest.y, chest.z, math.floor(far),
math.floor(x), math.floor(y), math.floor(z), settings.back_home))
notify("Block miner: the chest is " .. math.floor(far) .. " blocks away")
return false
end
end
baritone.stop()
local mined_before = trip_mined()
print("Putting " .. table.concat(items, ", ") .. " in the chest")
local moved, err = container.deposit(chest.x, chest.y, chest.z, table.unpack(items))
if err then print("Chest: " .. err) end
print("Stored " .. (moved or 0))
-- The trip's count stays: what it was before is kept, and what is left in the bag counts from here.
trip_stored = mined_before
trip_base = carried()
last_health = player.health() or last_health
return true
end
local function dead()
local health = player.health()
return player.dead and player.dead() or (health ~= nil and health <= 0)
end
-- Sends the die command, presses the confirm item in the menu the server opens for it (again every 1.5 s while that
-- menu stays), and waits through the death and the respawn; false if you did not die.
local function die()
print("Dying with " .. settings.suicide_cmd .. " to reset food and health")
send(settings.suicide_cmd)
local confirm = words(settings.confirm)
local finish = millis() + 10000
local pressed = -1e9
while not dead() and millis() < finish do
if #confirm > 0 and millis() - pressed >= 1500 and container.click(table.unpack(confirm)) then
pressed = millis()
print("Pressed confirm")
end
wait(250)
end
if not dead() then
print("Did not die (the server may not allow " .. settings.suicide_cmd .. ", or nothing to confirm in its menu): going on")
return false
end
print("Dead: respawning")
local since = millis()
while dead() do
if player.respawn then player.respawn() end
wait(1000)
if millis() - since > 60000 then
print("Still dead after a minute: press Respawn")
since = millis()
end
end
wait_until(player.in_world, 30000)
wait(settings.tp_wait * 1000) -- the spawn's chunks
last_health = player.health() or 20
return true
end
-- The trip is over: back, everything in the chest, and (if chosen) a fresh life.
local function come_back(why)
print(why .. ": coming back with " .. settings.back_home)
notify("Block miner: " .. why .. ", coming back")
teleport(settings.back_home)
if mode == nil then return end -- Got hurt on the way: the save handled it
-- Nowhere to put it (no chest, or the chest is not here): it stops rather than die with it or keep coming back.
if settings.store and not store() then
print("Stopping: what you mined is still with you")
stop()
end
if settings.suicide then die() end
new_trip()
mode = nil -- Mining again from the start
end
local time = world.time()
if time then
print("World time " .. time .. (world.is_night() and " (night)" or " (day)"))
else
print("The world time cannot be read here: it counts as day")
end
local chest_missing_told = false
while true do
local night = settings.night_stop and world.is_night()
if night and mode ~= "night" then
mode = "night"
local t = world.time() or 12542
local minutes = math.max(1, math.floor((23460 - t) / 1200 + 0.5))
print("Night: waiting at " .. settings.night_home .. " until day (about " .. minutes .. " min). Switch off 'Stop at night' to mine at night.")
notify("Block miner: night, waiting about " .. minutes .. " min")
teleport(settings.night_home)
elseif not night and mode ~= "day" then
mode = "day"
print("Going to " .. settings.day_home .. " to mine " .. table.concat(blocks, ", ") ..
(settings.trip > 0 and (" (coming back after " .. settings.trip .. ")") or ""))
teleport(settings.day_home)
end
if mode == "day" then
if settings.trip > 0 and trip_mined() >= settings.trip then
come_back("Mined " .. trip_mined())
elseif settings.store and inventory.free() <= settings.free_slots and settings.chest then
-- Stored where the chest is: after the come-back command, never by walking there from the mine.
come_back("Inventory full")
elseif settings.store and inventory.free() <= settings.free_slots and not chest_missing_told then
chest_missing_told = true
print("Inventory full and no storage chest set: look at it and press \"Set Storage chest\" in this script's settings")
elseif not baritone.busy() then
baritone.mine(table.unpack(blocks))
end
end
pause(1000)
endSticks from logs
Both recipes fit the 2x2 grid, so no crafting table is needed. Prism also comes with auto_crafter.lua: it crafts any item until you have enough, fetches the ingredients from a chest and stores what it makes.
-- Turns logs into planks, then planks into sticks, until there are 64 sticks.
while inventory.count("stick") < 64 do
if inventory.count("*_planks") < 2 then
local made, err = craft.make("oak_planks", 4)
if made == 0 then print("No planks: " .. (err or "?")) stop() end
end
local made, err = craft.make("stick", 64 - inventory.count("stick"))
if made == 0 and err then print(err) stop() end
wait(500)
end
print("64 sticks")Twenty diamonds
-- Mines diamonds until you have 20, then goes home.
baritone.mine("diamond_ore", "deepslate_diamond_ore")
wait_until(function() return inventory.count("diamond") >= 20 end)
baritone.stop()
chat.send("/home")
print("20 diamonds: going home")Also there: Lua's string, table, math and utf8 libraries, os.time, os.clock and os.date, and coroutines. Files, other programs and loading code are switched off.