embark-ai 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mc-server/bot/bot.js +30 -13
- package/mc-server/bot/tasks.js +5 -0
- package/package.json +1 -1
package/mc-server/bot/bot.js
CHANGED
|
@@ -555,6 +555,22 @@ function replaceTask(goalName, fn, opts) {
|
|
|
555
555
|
return runTask(goalName, fn, opts)
|
|
556
556
|
}
|
|
557
557
|
|
|
558
|
+
// When the user assigns Ember a new task while she's following, drop the follow
|
|
559
|
+
// so the agent-loop auto-resume does not re-engage it after the task finishes.
|
|
560
|
+
function interruptFollow() {
|
|
561
|
+
if (!state.followTarget) return
|
|
562
|
+
movement.stop('follow')
|
|
563
|
+
state.followTarget = null
|
|
564
|
+
setGoal('idle', { source: 'interrupt_follow', reason: 'new_task' })
|
|
565
|
+
log.info('follow_interrupted_by_task')
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Wrapper for fallbackCommand task dispatches: preempts follow, then runs the task.
|
|
569
|
+
function taskCmd(goalName, fn, opts) {
|
|
570
|
+
interruptFollow()
|
|
571
|
+
return runTask(goalName, fn, opts)
|
|
572
|
+
}
|
|
573
|
+
|
|
558
574
|
// Track recent path failures by goal — repeated explore timeouts mean we're stuck.
|
|
559
575
|
const taskFailureCounts = new Map() // goalName -> consecutive failure count
|
|
560
576
|
const EXPLORE_FAIL_THRESHOLD = 3
|
|
@@ -1222,6 +1238,7 @@ function executeAction(result, username, groundedState) {
|
|
|
1222
1238
|
result.say = "Still busy — give me a sec."
|
|
1223
1239
|
return
|
|
1224
1240
|
}
|
|
1241
|
+
if (taskActions.includes(result.action)) interruptFollow()
|
|
1225
1242
|
|
|
1226
1243
|
switch (result.action) {
|
|
1227
1244
|
|
|
@@ -1323,28 +1340,28 @@ function fallbackCommand(username, message) {
|
|
|
1323
1340
|
if (cmd === 'follow me') { if (state.energy < 25) { safeChat('Too tired.'); return }; state.followTarget = username; setGoal('following', { source: 'fallback_cmd', reason: 'follow_me' }); safeChat('Following.') }
|
|
1324
1341
|
else if (cmd === 'stop') { cancelCurrentTask(); state.followTarget = null; safeChat('Stopped.') }
|
|
1325
1342
|
else if (cmd === 'status') { safeChat(`Goal: ${state.goal} | E:${state.energy.toFixed(0)} H:${state.hunger.toFixed(0)} | anger:${anger.size}`) }
|
|
1326
|
-
else if (cmd === 'explore') { if (!
|
|
1327
|
-
else if (cmd === 'get wood' || cmd === 'chop tree'){ if (!
|
|
1328
|
-
else if (cmd === 'make planks') { if (!
|
|
1329
|
-
else if (cmd === 'attack' || cmd === 'fight') { if (!
|
|
1330
|
-
else if (cmd === 'collect' || cmd === 'pick up') { if (!
|
|
1331
|
-
else if (cmd === 'build house') { if (!
|
|
1343
|
+
else if (cmd === 'explore') { if (!taskCmd('exploring', tasks.taskExplore)) safeChat("Busy.") }
|
|
1344
|
+
else if (cmd === 'get wood' || cmd === 'chop tree'){ if (!taskCmd('gathering', tasks.taskGatherWood)) safeChat("Busy.") }
|
|
1345
|
+
else if (cmd === 'make planks') { if (!taskCmd('crafting', tasks.taskCraftPlanks)) safeChat("Busy.") }
|
|
1346
|
+
else if (cmd === 'attack' || cmd === 'fight') { if (!taskCmd('attacking', tasks.taskAttackMobs)) safeChat("Busy.") }
|
|
1347
|
+
else if (cmd === 'collect' || cmd === 'pick up') { if (!taskCmd('collecting', tasks.taskCollectNearby)) safeChat("Busy.") }
|
|
1348
|
+
else if (cmd === 'build house') { if (!taskCmd('building', tasks.taskBuildHouseSmart)) safeChat("Busy.") }
|
|
1332
1349
|
else if (cmd === 'inventory') { const it = bot.inventory.items(); safeChat(it.length ? it.map(i=>`${i.name}x${i.count}`).join(', ') : 'Empty.') }
|
|
1333
1350
|
else if (cmd === 'look around') { const gs = buildGroundedState(bot, state, memory, anger, envPerception); safeChat(`I see: ${chatSummary(gs) || 'nothing'}`) }
|
|
1334
1351
|
else {
|
|
1335
|
-
const m = cmd.match(/^craft (.+)$/); if (m) { if (!
|
|
1336
|
-
const p = cmd.match(/^place (.+)$/); if (p) { if (!
|
|
1352
|
+
const m = cmd.match(/^craft (.+)$/); if (m) { if (!taskCmd('crafting', () => tasks.taskCraftItem(m[1]))) safeChat("Busy."); return }
|
|
1353
|
+
const p = cmd.match(/^place (.+)$/); if (p) { if (!taskCmd('placing', () => tasks.taskPlaceBlock(p[1].trim()))) safeChat("Busy."); return }
|
|
1337
1354
|
const mn = cmd.match(/^mine (.+)$/); if (mn) {
|
|
1338
1355
|
const parts = mn[1].trim().match(/^(.+?)\s+(\d+)$/)
|
|
1339
1356
|
const name = parts ? parts[1] : mn[1].trim()
|
|
1340
1357
|
const cnt = parts ? Math.min(parseInt(parts[2]), 16) : 1
|
|
1341
|
-
if (!
|
|
1358
|
+
if (!taskCmd('mining', () => tasks.taskMineBlock(name, cnt))) safeChat("Busy."); return
|
|
1342
1359
|
}
|
|
1343
|
-
if (cmd === 'eat') { if (!
|
|
1344
|
-
if (cmd === 'flee' || cmd === 'run') { if (!
|
|
1345
|
-
if (cmd === 'escape' || cmd === 'climb out' || cmd === 'get out') { if (!
|
|
1360
|
+
if (cmd === 'eat') { if (!taskCmd('eating', tasks.taskEatFood)) safeChat("Busy."); return }
|
|
1361
|
+
if (cmd === 'flee' || cmd === 'run') { if (!taskCmd('fleeing', tasks.taskFlee)) safeChat("Busy."); return }
|
|
1362
|
+
if (cmd === 'escape' || cmd === 'climb out' || cmd === 'get out') { if (!taskCmd('escaping', tasks.taskEscape)) safeChat("Busy."); return }
|
|
1346
1363
|
const w = cmd.match(/^where is (.+)$/); if (w) { const loc = recallLocation(memory, w[1].trim()); safeChat(loc ? `${w[1]}: ${loc.pos.x}, ${loc.pos.y}, ${loc.pos.z}` : `Don't know.`); return }
|
|
1347
|
-
const g = cmd.match(/^go to (.+)$/); if (g) { if (!
|
|
1364
|
+
const g = cmd.match(/^go to (.+)$/); if (g) { if (!taskCmd('going_to', () => tasks.taskGoTo(g[1].trim()))) safeChat("Busy."); else safeChat(`Going to ${g[1]}.`) }
|
|
1348
1365
|
}
|
|
1349
1366
|
}
|
|
1350
1367
|
|
package/mc-server/bot/tasks.js
CHANGED
|
@@ -238,6 +238,9 @@ module.exports = function createTasks(deps) {
|
|
|
238
238
|
const fresh = bot.blockAt(logBlock.position)
|
|
239
239
|
if (fresh && ids.includes(fresh.type) && bot.canDigBlock(fresh)) {
|
|
240
240
|
await safeDig(bot, fresh)
|
|
241
|
+
// Step into the drop so the item entity is auto-collected
|
|
242
|
+
await new Promise(r => setTimeout(r, 300))
|
|
243
|
+
try { await navNear(logBlock.position.x, logBlock.position.y, logBlock.position.z, 0) } catch {}
|
|
241
244
|
safeChat('Got wood.')
|
|
242
245
|
rememberEvent(memory, 'gathered_wood', {})
|
|
243
246
|
}
|
|
@@ -909,6 +912,8 @@ module.exports = function createTasks(deps) {
|
|
|
909
912
|
const fresh = bot.blockAt(logBlock.position)
|
|
910
913
|
if (fresh && ids.includes(fresh.type)) {
|
|
911
914
|
await safeDig(bot, fresh)
|
|
915
|
+
await new Promise(r => setTimeout(r, 300))
|
|
916
|
+
try { await navNear(logBlock.position.x, logBlock.position.y, logBlock.position.z, 0) } catch {}
|
|
912
917
|
chopped++
|
|
913
918
|
} else { break }
|
|
914
919
|
} catch (e) {
|