Lewati ke konten utama

Fishing

Fishing automation lives under client.automation, alongside the tutorial driver. The flow is persistent — once armed, the runtime warps, walks, equips the rod, and casts. On every reconnect the resume watcher rearms the same config until you explicitly stop it.

Why persistent? A fishing session is a long-lived intent ("keep this bot fishing in MANCINGNIH at (20, 30) until I say stop"), not a one-shot action. The Auto-Resume UI in the desktop app uses the exact same arm path — Lua and the UI write to one shared config slot per bot.

FishingConfig table

armFishing and fishingConfig both speak this shape:

FieldTypeRequiredDescription
worldstringyesUppercase world name, e.g. "MANCINGNIH".
portalstring?noPortal entry-point id within the world. Omit to spawn at WorldStartPoint.
rodnumberyesBlock id of the rod to equip (2406-2421, 4196, 4622).
baitnumberyesBlock id of the bait (2462-2482, plus 3353 / 3774 / 4561 / 4585).
baitNamestring?noFriendly bait name. Falls back to "Lure#<id>" when omitted.
anchorVector2iyes*Anchor tile the bot walks to before casting.
anchorXnumber?yes*Alternative to anchor. armFishing accepts either; fishingConfig returns both.
anchorYnumber?yes*See anchorX.
directionstringyes"left" or "right" — picks the water tile adjacent to anchor.
createdAtnumber?outputUnix-epoch seconds when the config was armed. Set by the runtime, ignored on input.

* Provide either anchor (a Vector2i) or the anchorX + anchorY pair. anchor wins when both are present.

The bot must already own the chosen rod and bait in inventory. armFishing doesn't buy them. Use client:buy("FishingRod…") / client:buy("LureBooster") first.


Drivers

client.automation:armFishing(cfg)

Arm persistent fishing. The runtime executes:

  1. Warp to cfg.world (skipped when already in that world).
  2. Walk to cfg.anchor.
  3. Equip cfg.rod from inventory.
  4. Enter the cast loop using cfg.direction + cfg.bait.
FieldType
Signature(self: Automation, cfg: FishingConfig) → string?
Returnsstring?nil on success, or an Errors.* code on bad input / busy / disconnected
Common errorsErrors.INVALID_WORLD (missing world field), Errors.NOT_CONNECTED, Errors.DISCONNECTED, Errors.OTHER (missing required field)
Idempotentno — calling twice replaces the previous config
Asyncyes — yields until the queue accepts the command
local err = c.automation:armFishing({
world = "MANCINGNIH",
rod = 2410, -- FishingRodFiberglassBasic
bait = 2462, -- LureWorm
baitName = "LureWorm",
anchor = Vector2i.new(20, 30),
direction = "left",
})
if err then print("arm failed:", err) end

client.automation:stopFishing()

Stop the in-flight cast and clear the persistent flag so the resume watcher won't rearm. Idempotent — safe to call on a non-fishing bot.

FieldType
Signature(self: Automation) → string?
Returnsstring?nil on success, or an Errors.* code
c.automation:stopFishing()

For transient pauses (e.g. "stop now but rearm on reconnect"), let the runtime auto-stop on disconnect — the watcher will rearm. stopFishing is the "Stop & Clear" semantic, not the "pause" one.


State queries

client.automation:isFishing()

FieldType
Signature(self: Automation) → boolean
Returnsbooleantrue when fishing is actively casting OR armed (config set, between reconnects)

Mirrors the desktop UI's "is the toggle on" state. Use this to gate other automation:

if c.automation:isFishing() then
return -- fishing owns this bot, don't queue auto-mine
end

client.automation:fishingStatus()

FieldType
Signature(self: Automation) → string?
Returnsstring? — human-readable status, or nil when no driver is armed
Possible values"Warping to <WORLD>…", "Walking to (x, y)…", "Casting", "Reeling", … (non-exhaustive — labels are advisory, don't == compare in production)
print(c.automation:fishingStatus()) -- "Casting"

client.automation:fishingConfig()

FieldType
Signature(self: Automation) → FishingConfig?
ReturnsFishingConfig? — snapshot of the persistent config, or nil when no config is armed

The returned table is a fresh snapshot — mutating it does not affect the running config. To change the config, call armFishing again with the new shape.

local cfg = c.automation:fishingConfig()
if cfg then
print(string.format("fishing %s with rod=%d at (%d, %d)",
cfg.world, cfg.rod, cfg.anchorX, cfg.anchorY))
end

Block id reference

Rods (family → tier ladder)

FamilyBasicFineSuperiorFlawlessEvent variants
Bamboo24062407240824094622 (Reinforced)
Fiberglass2410241124122413
Carbon Fiber24142415241624174196 (Dark)
Titanium2418241924202421

Lures

The standard 21-lure ladder is contiguous: 2462..2482. Event variants: 3353 (Radioactive Worm), 3774 (Lucky Lure), 4561 (Noob), 4585 (Crab Bait).


End-to-end recipe

local c = getClient()
local a = c.automation

-- Wait until the bot is in-world and tutorial is done.
while a:tutorialState() == nil do task.wait(0.2) end
if a:isInTutorial() then a:tutorial() end

-- Arm fishing — runtime does the warp + walk + rod-equip.
local err = a:armFishing({
world = "MANCINGNIH",
rod = 2410,
bait = 2462,
baitName = "LureWorm",
anchor = Vector2i.new(20, 30),
direction = "left",
})
if err then
print("arm failed:", err)
return
end

-- Babysit — log every status transition.
local last = nil
while a:isFishing() do
local s = a:fishingStatus()
if s ~= last then
print("[fishing]", s)
last = s
end
task.wait(1)
end

See script_fishing_basic.lua for the canonical example with cleanup.


Gotchas

  • Inventory check is the runtime's job, not yours. Calling armFishing with a rod the bot doesn't own returns nil (queued OK) but the equip step fails later — watch fishingStatus for the error.
  • stopFishing clears the persistent flag. If you only want to pause the cast loop without breaking auto-resume, just disconnect the bot — the watcher will rearm on reconnect.
  • anchor vs water tile. The anchor is where the bot stands; the actual fishing tile is one step direction-ward of it (a water block). Set the anchor on solid ground next to water, not on the water itself.
  • The desktop UI and Lua share one config slot. Arming via Lua overwrites whatever the Auto-Resume Fishing panel shows, and vice-versa.

See also