-
Notifications
You must be signed in to change notification settings - Fork 710
feat: add auto_sleep and fall_protection modes #702
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -87,6 +87,58 @@ const modes_list = [ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: 'fall_protection', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: 'Use water bucket to break a long fall (MLG water). Requires a water bucket in inventory.', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interrupts: ['all'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| active: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fallStartY: null, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update: async function (agent) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const bot = agent.bot; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const pos = bot.entity.position; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const vel = bot.entity.velocity; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Detect if falling (negative Y velocity) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (vel.y < -0.5) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (this.fallStartY === null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.fallStartY = pos.y; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const fallDistance = this.fallStartY - pos.y; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // If falling more than 10 blocks and accelerating, try MLG water | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (fallDistance > 10 && vel.y < -0.8) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const waterBucket = bot.inventory.items().find(item => item.name === 'water_bucket'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (waterBucket && !this.active) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Check if ground is near (within 4 blocks below) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const groundBlock = bot.blockAt(pos.offset(0, -4, 0)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (groundBlock && groundBlock.name !== 'air' && groundBlock.name !== 'water') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| execute(this, agent, async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| say(agent, 'MLG water!'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await bot.equip(waterBucket, 'hand'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await bot.lookAt(pos.offset(0, -3, 0)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| say(agent, 'MLG water!'); | |
| try { | |
| await bot.equip(waterBucket, 'hand'); | |
| await bot.lookAt(pos.offset(0, -3, 0)); | |
| const currentPos = bot.entity.position.clone(); | |
| say(agent, 'MLG water!'); | |
| try { | |
| await bot.equip(waterBucket, 'hand'); | |
| await bot.lookAt(currentPos.offset(0, -3, 0)); |
Outdated
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 500ms wait after placing water may not be sufficient for the bot to land in the water and stop falling. Depending on fall speed and distance, the bot might still be falling when it tries to pick up the water block. This could result in the bot not landing safely or picking up the water too early. Consider waiting for the bot to actually land (checking velocity or ground contact) before attempting to pick up the water.
| await new Promise(r => setTimeout(r, 500)); | |
| // Wait until the bot has actually landed or a timeout is reached | |
| await new Promise(resolve => { | |
| const start = Date.now(); | |
| const checkLanding = () => { | |
| const entity = bot.entity; | |
| // Consider landed if onGround or vertical velocity is no longer negative | |
| if (entity.onGround || entity.velocity.y >= 0) { | |
| return resolve(); | |
| } | |
| // Safety timeout to avoid waiting forever (e.g., in unusual situations) | |
| if (Date.now() - start > 2000) { | |
| return resolve(); | |
| } | |
| setTimeout(checkLanding, 50); | |
| }; | |
| checkLanding(); | |
| }); |
Outdated
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The night time check uses time >= 13000 && time <= 23000, but Minecraft's time cycle wraps from 23999 to 0. This means times from 23001-23999 (about 50 seconds of night) will be missed. In Minecraft, you can sleep in a bed during times 12542-23459, and monsters spawn when time >= 13000. Consider changing to time >= 13000 without an upper bound check, since the bot will stop checking once it's sleeping, or add proper wrap-around handling with (time >= 13000 && time < 24000) || time < 1000.
| // Check if it's nighttime (13000-23000 ticks) and we're not already sleeping | |
| const time = bot.time.timeOfDay; | |
| const isNight = time >= 13000 && time <= 23000; | |
| // Check if it's nighttime (time >= 13000) and we're not already sleeping | |
| const time = bot.time.timeOfDay; | |
| const isNight = time >= 13000; |
Outdated
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error handling only checks for 'occupied' in the error message, but silently swallows all other errors. If the bed is too far, blocks are in the way, or other pathfinding issues occur, the bot will fail silently without informing the user. Consider either logging all errors or handling specific common error cases (e.g., pathfinding failures, missing beds after the search).
| if (e.message && e.message.includes('occupied')) { | |
| say(agent, 'The bed is occupied.'); | |
| if (e && e.message && e.message.includes('occupied')) { | |
| say(agent, 'The bed is occupied.'); | |
| } else { | |
| console.error('Failed to sleep in bed:', e); | |
| const errorMessage = e && e.message ? e.message : 'unknown reason'; | |
| say(agent, `I couldn\'t reach the bed to sleep (${errorMessage}).`); |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bed finding logic here duplicates the same search that skills.goToBed() performs (see skills.js lines 1551-1557). This means the bed search happens twice: once here to check if a bed exists, and again inside skills.goToBed(). Consider removing the bed search here and letting skills.goToBed() handle it, or check the return value from skills.goToBed() to determine if a bed was found.
| // Look for a bed within 32 blocks using block name matching (beds are named like 'white_bed', 'red_bed', etc.) | |
| const beds = bot.findBlocks({ | |
| matching: (block) => block.name.includes('bed'), | |
| maxDistance: 32, | |
| count: 1 | |
| }); | |
| if (beds.length > 0) { | |
| execute(this, agent, async () => { | |
| say(agent, 'It\'s getting dark, I should sleep.'); | |
| try { | |
| await skills.goToBed(bot); | |
| } catch (e) { | |
| if (e.message && e.message.includes('occupied')) { | |
| say(agent, 'The bed is occupied.'); | |
| } | |
| } | |
| }); | |
| } | |
| // Let skills.goToBed handle finding a suitable bed | |
| execute(this, agent, async () => { | |
| try { | |
| await skills.goToBed(bot); | |
| say(agent, 'It\'s getting dark, I should sleep.'); | |
| } catch (e) { | |
| if (e && e.message && e.message.includes('occupied')) { | |
| say(agent, 'The bed is occupied.'); | |
| } | |
| } | |
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check
vel.y < -0.8on line 111 is more restrictive than the initial falling checkvel.y < -0.5on line 103. This means the fallStartY can be set during a slower fall, but won't trigger MLG water placement. Consider using the same velocity threshold for both checks, or resetting fallStartY when velocity is between -0.5 and -0.8 to ensure accurate fall distance calculation.