mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-04 06:15:32 +02:00
reworked mode interrupts, added equip and discard
This commit is contained in:
parent
e95c082786
commit
d44c99356f
5 changed files with 71 additions and 29 deletions
|
@ -10,7 +10,6 @@ export class Coder {
|
||||||
this.generating = false;
|
this.generating = false;
|
||||||
this.code_template = '';
|
this.code_template = '';
|
||||||
this.timedout = false;
|
this.timedout = false;
|
||||||
this.interruptible = true;
|
|
||||||
this.cur_action_name = '';
|
this.cur_action_name = '';
|
||||||
|
|
||||||
readFile('./bots/template.js', 'utf8', (err, data) => {
|
readFile('./bots/template.js', 'utf8', (err, data) => {
|
||||||
|
@ -159,14 +158,14 @@ export class Coder {
|
||||||
}
|
}
|
||||||
|
|
||||||
async executeResume(func=null, timeout=10) {
|
async executeResume(func=null, timeout=10) {
|
||||||
if (func != null) {
|
if (func != null) { // start new resume
|
||||||
this.resume_func = func;
|
this.resume_func = func;
|
||||||
|
this.resume_name = this.cur_action_name;
|
||||||
}
|
}
|
||||||
if (this.resume_func != null && this.agent.isIdle() && !this.agent.self_prompter.on) {
|
if (this.resume_func != null && this.agent.isIdle() && !this.agent.self_prompter.on) {
|
||||||
console.log('resuming code...')
|
this.cur_action_name = this.resume_name;
|
||||||
this.interruptible = true;
|
|
||||||
let res = await this.execute(this.resume_func, timeout);
|
let res = await this.execute(this.resume_func, timeout);
|
||||||
this.interruptible = false;
|
this.cur_action_name = '';
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
return {success: false, message: null, interrupted: false, timedout: false};
|
return {success: false, message: null, interrupted: false, timedout: false};
|
||||||
|
@ -175,6 +174,7 @@ export class Coder {
|
||||||
|
|
||||||
cancelResume() {
|
cancelResume() {
|
||||||
this.resume_func = null;
|
this.resume_func = null;
|
||||||
|
this.resume_name = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurActionName(name) {
|
setCurActionName(name) {
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import * as skills from '../library/skills.js';
|
import * as skills from '../library/skills.js';
|
||||||
import settings from '../../../settings.js';
|
import settings from '../../../settings.js';
|
||||||
|
|
||||||
function wrapExecution(func, timeout=-1, resume_name=null) {
|
function wrapExecution(func, resume=false, timeout=-1) {
|
||||||
return async function (agent, ...args) {
|
return async function (agent, ...args) {
|
||||||
let code_return;
|
let code_return;
|
||||||
if (resume_name != null) {
|
const wrappedFunction = async () => {
|
||||||
code_return = await agent.coder.executeResume(async () => {
|
await func(agent, ...args);
|
||||||
await func(agent, ...args);
|
};
|
||||||
}, resume_name, timeout);
|
if (resume) {
|
||||||
|
code_return = await agent.coder.executeResume(wrappedFunction, timeout);
|
||||||
} else {
|
} else {
|
||||||
code_return = await agent.coder.execute(async () => {
|
code_return = await agent.coder.execute(wrappedFunction, timeout);
|
||||||
await func(agent, ...args);
|
|
||||||
}, timeout);
|
|
||||||
}
|
}
|
||||||
if (code_return.interrupted && !code_return.timedout)
|
if (code_return.interrupted && !code_return.timedout)
|
||||||
return;
|
return;
|
||||||
|
@ -88,7 +87,7 @@ export const actionsList = [
|
||||||
},
|
},
|
||||||
perform: wrapExecution(async (agent, player_name, follow_dist) => {
|
perform: wrapExecution(async (agent, player_name, follow_dist) => {
|
||||||
await skills.followPlayer(agent.bot, player_name, follow_dist);
|
await skills.followPlayer(agent.bot, player_name, follow_dist);
|
||||||
}, -1, 'followPlayer')
|
}, true)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '!goToBlock',
|
name: '!goToBlock',
|
||||||
|
@ -145,6 +144,28 @@ export const actionsList = [
|
||||||
await skills.giveToPlayer(agent.bot, item_name, player_name, num);
|
await skills.giveToPlayer(agent.bot, item_name, player_name, num);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: '!equip',
|
||||||
|
description: 'Equip the given item.',
|
||||||
|
params: {'item_name': '(string) The name of the item to equip.'},
|
||||||
|
perform: wrapExecution(async (agent, item_name) => {
|
||||||
|
await skills.equip(agent.bot, item_name);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '!discard',
|
||||||
|
description: 'Discard the given item from the inventory.',
|
||||||
|
params: {
|
||||||
|
'item_name': '(string) The name of the item to discard.',
|
||||||
|
'num': '(number) The number of items to discard.',
|
||||||
|
},
|
||||||
|
perform: wrapExecution(async (agent, item_name, num) => {
|
||||||
|
const start_loc = agent.bot.entity.position;
|
||||||
|
await skills.moveAway(agent.bot, 5);
|
||||||
|
await skills.discard(agent.bot, item_name, num);
|
||||||
|
await skills.goToPosition(agent.bot, start_loc.x, start_loc.y, start_loc.z, 0);
|
||||||
|
})
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: '!collectBlocks',
|
name: '!collectBlocks',
|
||||||
description: 'Collect the nearest blocks of a given type.',
|
description: 'Collect the nearest blocks of a given type.',
|
||||||
|
@ -154,7 +175,7 @@ export const actionsList = [
|
||||||
},
|
},
|
||||||
perform: wrapExecution(async (agent, type, num) => {
|
perform: wrapExecution(async (agent, type, num) => {
|
||||||
await skills.collectBlock(agent.bot, type, num);
|
await skills.collectBlock(agent.bot, type, num);
|
||||||
}, 10) // 10 minute timeout
|
}, false, 10) // 10 minute timeout
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '!collectAllBlocks',
|
name: '!collectAllBlocks',
|
||||||
|
@ -166,7 +187,7 @@ export const actionsList = [
|
||||||
let success = await skills.collectBlock(agent.bot, type, 1);
|
let success = await skills.collectBlock(agent.bot, type, 1);
|
||||||
if (!success)
|
if (!success)
|
||||||
agent.coder.cancelResume();
|
agent.coder.cancelResume();
|
||||||
}, 10, 'collectAllBlocks') // 10 minute timeout
|
}, true, 3) // 3 minute timeout
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '!craftRecipe',
|
name: '!craftRecipe',
|
||||||
|
|
|
@ -82,6 +82,7 @@ export async function executeCommand(agent, message) {
|
||||||
let parsed = parseCommandMessage(message);
|
let parsed = parseCommandMessage(message);
|
||||||
if (parsed) {
|
if (parsed) {
|
||||||
const command = getCommand(parsed.commandName);
|
const command = getCommand(parsed.commandName);
|
||||||
|
const is_action = isAction(command.name);
|
||||||
let numArgs = 0;
|
let numArgs = 0;
|
||||||
if (parsed.args) {
|
if (parsed.args) {
|
||||||
numArgs = parsed.args.length;
|
numArgs = parsed.args.length;
|
||||||
|
@ -89,8 +90,14 @@ export async function executeCommand(agent, message) {
|
||||||
console.log('parsed command:', parsed);
|
console.log('parsed command:', parsed);
|
||||||
if (numArgs !== numParams(command))
|
if (numArgs !== numParams(command))
|
||||||
return `Command ${command.name} was given ${numArgs} args, but requires ${numParams(command)} args.`;
|
return `Command ${command.name} was given ${numArgs} args, but requires ${numParams(command)} args.`;
|
||||||
else
|
else {
|
||||||
return await command.perform(agent, ...parsed.args);
|
if (is_action)
|
||||||
|
agent.coder.setCurActionName(command.name);
|
||||||
|
const result = await command.perform(agent, ...parsed.args);
|
||||||
|
if (is_action)
|
||||||
|
agent.coder.setCurActionName(command.name);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return `Command is incorrectly formatted`;
|
return `Command is incorrectly formatted`;
|
||||||
|
|
|
@ -648,23 +648,35 @@ export async function placeBlock(bot, blockType, x, y, z, placeOn='bottom', dont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function equip(bot, itemName, bodyPart) {
|
export async function equip(bot, itemName) {
|
||||||
/**
|
/**
|
||||||
* Equip the given item to the given body part, like tools or armor.
|
* Equip the given item to the proper body part, like tools or armor.
|
||||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||||
* @param {string} itemName, the item or block name to equip.
|
* @param {string} itemName, the item or block name to equip.
|
||||||
* @param {string} bodyPart, the body part to equip the item to.
|
|
||||||
* @returns {Promise<boolean>} true if the item was equipped, false otherwise.
|
* @returns {Promise<boolean>} true if the item was equipped, false otherwise.
|
||||||
* @example
|
* @example
|
||||||
* await skills.equip(bot, "iron_pickaxe", "hand");
|
* await skills.equip(bot, "iron_pickaxe");
|
||||||
* await skills.equip(bot, "diamond_chestplate", "torso");
|
|
||||||
**/
|
**/
|
||||||
let item = bot.inventory.items().find(item => item.name === itemName);
|
let item = bot.inventory.items().find(item => item.name === itemName);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
log(bot, `You do not have any ${itemName} to equip.`);
|
log(bot, `You do not have any ${itemName} to equip.`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
await bot.equip(item, bodyPart);
|
if (itemName.includes('leggings')) {
|
||||||
|
await bot.equip(item, 'legs');
|
||||||
|
}
|
||||||
|
else if (itemName.includes('boots')) {
|
||||||
|
await bot.equip(item, 'feet');
|
||||||
|
}
|
||||||
|
else if (itemName.includes('helmet')) {
|
||||||
|
await bot.equip(item, 'head');
|
||||||
|
}
|
||||||
|
else if (itemName.includes('chestplate')) {
|
||||||
|
await bot.equip(item, 'torso');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await bot.equip(item, 'hand');
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,17 +73,18 @@ const modes = [
|
||||||
{
|
{
|
||||||
name: 'unstuck',
|
name: 'unstuck',
|
||||||
description: 'Attempt to get unstuck when in the same place for a while. Interrupts some actions.',
|
description: 'Attempt to get unstuck when in the same place for a while. Interrupts some actions.',
|
||||||
interrupts: ['collectBlocks', 'goToPlayer', 'collectAllBlocks'],
|
interrupts: ['collectBlocks', 'goToPlayer', 'collectAllBlocks', 'goToPlace'],
|
||||||
on: true,
|
on: true,
|
||||||
active: false,
|
active: false,
|
||||||
prev_location: null,
|
prev_location: null,
|
||||||
|
distance: 2,
|
||||||
stuck_time: 0,
|
stuck_time: 0,
|
||||||
last_time: Date.now(),
|
last_time: Date.now(),
|
||||||
max_stuck_time: 10,
|
max_stuck_time: 20,
|
||||||
update: async function (agent) {
|
update: async function (agent) {
|
||||||
if (agent.isIdle()) return;
|
if (agent.isIdle()) return;
|
||||||
const bot = agent.bot;
|
const bot = agent.bot;
|
||||||
if (this.prev_location && this.prev_location.distanceTo(bot.entity.position) < 1) {
|
if (this.prev_location && this.prev_location.distanceTo(bot.entity.position) < this.distance) {
|
||||||
this.stuck_time += (Date.now() - this.last_time) / 1000;
|
this.stuck_time += (Date.now() - this.last_time) / 1000;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -159,7 +160,8 @@ const modes = [
|
||||||
noticed_at: -1,
|
noticed_at: -1,
|
||||||
update: async function (agent) {
|
update: async function (agent) {
|
||||||
let item = world.getNearestEntityWhere(agent.bot, entity => entity.name === 'item', 8);
|
let item = world.getNearestEntityWhere(agent.bot, entity => entity.name === 'item', 8);
|
||||||
if (item && item !== this.prev_item && await world.isClearPath(agent.bot, item)) {
|
let empty_inv_slots = agent.bot.inventory.emptySlotCount();
|
||||||
|
if (item && item !== this.prev_item && await world.isClearPath(agent.bot, item) && empty_inv_slots > 1) {
|
||||||
if (this.noticed_at === -1) {
|
if (this.noticed_at === -1) {
|
||||||
this.noticed_at = Date.now();
|
this.noticed_at = Date.now();
|
||||||
}
|
}
|
||||||
|
@ -310,7 +312,7 @@ class ModeController {
|
||||||
this.unPauseAll();
|
this.unPauseAll();
|
||||||
}
|
}
|
||||||
for (let mode of this.modes_list) {
|
for (let mode of this.modes_list) {
|
||||||
let interruptible = this.agent.coder.interruptible && (mode.interrupts.includes('all') || mode.interrupts.some(i => i === this.agent.coder.cur_action_name));
|
let interruptible = mode.interrupts.some(i => i === 'all') || mode.interrupts.some(i => i === this.agent.coder.cur_action_name);
|
||||||
if (mode.on && !mode.paused && !mode.active && (this.agent.isIdle() || interruptible)) {
|
if (mode.on && !mode.paused && !mode.active && (this.agent.isIdle() || interruptible)) {
|
||||||
await mode.update(this.agent);
|
await mode.update(this.agent);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue