added defend, improved gotoplayer

This commit is contained in:
MaxRobinsonTheGreat 2024-01-13 12:11:04 -06:00
parent 4f48dea4f6
commit ff9c241876
2 changed files with 75 additions and 19 deletions

View file

@ -3,6 +3,7 @@ import * as world from '../world.js';
function wrapExecution(func) {
return async function (agent, ...args) {
await agent.coder.stop();
agent.bot.output = '';
agent.coder.executing = true;
let res = await func(agent, ...args);
@ -13,7 +14,6 @@ function wrapExecution(func) {
}
}
// const actionsList = [
export const actionsList = [
{
name: '!newAction',
@ -34,7 +34,7 @@ export const actionsList = [
},
{
name: '!goToPlayer',
description: 'Go to the nearest player. Ex: !goToPlayer("steve")',
description: 'Go to the given player. Ex: !goToPlayer("steve")',
params: {'player_name': '(string) The name of the player to go to.'},
perform: wrapExecution(async (agent, player_name) => {
return await skills.goToPlayer(agent.bot, player_name);
@ -42,7 +42,7 @@ export const actionsList = [
},
{
name: '!followPlayer',
description: 'Endlessly follow the nearest player. Ex: !followPlayer("stevie")',
description: 'Endlessly follow the given player. Ex: !followPlayer("stevie")',
params: {'player_name': '(string) The name of the player to follow.'},
perform: wrapExecution(async (agent, player_name) => {
await skills.followPlayer(agent.bot, player_name);
@ -66,5 +66,13 @@ export const actionsList = [
perform: wrapExecution(async (agent, type) => {
await skills.attackMob(agent.bot, type, true);
})
},
{
name: '!defend',
description: 'Follow the given player and attack any nearby monsters.',
params: {'player_name': '(string) The name of the player to defend.'},
perform: wrapExecution(async (agent, player_name) => {
await skills.defendPlayer(agent.bot, player_name);
})
}
];

View file

@ -44,13 +44,15 @@ export async function smeltItem(bot, itemName, num=1) {
/**
* Puts 1 coal in furnace and smelts the given item name, waits until the furnace runs out of fuel or input items.
* @param {MinecraftBot} bot, reference to the minecraft bot.
* @param {string} itemName, the item name to smelt. Must contain "raw"
* @param {string} itemName, the item name to smelt. Ores must contain "raw" like raw_iron.
* @param {number} num, the number of items to smelt. Defaults to 1.
* @returns {Promise<boolean>} true if the item was smelted, false otherwise. Fail
* @example
* await skills.smeltItem(bot, "raw_iron");
* await skills.smeltItem(bot, "beef");
**/
if (!itemName.includes('raw')) {
const foods = ['beef', 'chicken', 'cod', 'mutton', 'porkchop', 'rabbit', 'salmon', 'tropical_fish'];
if (!itemName.includes('raw') && !foods.includes(itemName)) {
log(bot, `Cannot smelt ${itemName}, must be a "raw" item, like "raw_iron".`);
return false;
} // TODO: allow cobblestone, sand, clay, etc.
@ -166,6 +168,13 @@ export async function clearNearestFurnace(bot) {
}
function equipHighestAttack(bot) {
let weapons = bot.inventory.items().filter(item => item.name.includes('sword') || item.name.includes('axe') || item.name.includes('pickaxe') || item.name.includes('shovel'));
let weapon = weapons.sort((a, b) => b.attackDamage - a.attackDamage)[0];
if (weapon)
bot.equip(weapon, 'hand');
}
export async function attackMob(bot, mobType, kill=true) {
/**
* Attack mob of the given type.
@ -177,16 +186,11 @@ export async function attackMob(bot, mobType, kill=true) {
* await skills.attackMob(bot, "zombie", true);
**/
const mob = bot.nearestEntity(entity => entity.name && entity.name.toLowerCase() === mobType.toLowerCase());
const attackable = ['animal', 'monster', 'mob'];
if (mob && attackable.includes(mob.type)) {
if (mob) {
let pos = mob.position;
console.log(bot.entity.position.distanceTo(pos))
// equip highest damage weapon
let weapons = bot.inventory.items().filter(item => item.name.includes('sword') || item.name.includes('axe') || item.name.includes('pickaxe') || item.name.includes('shovel'));
let weapon = weapons.sort((a, b) => b.attackDamage - a.attackDamage)[0];
if (weapon)
await bot.equip(weapon, 'hand');
equipHighestAttack(bot)
if (!kill) {
if (bot.entity.position.distanceTo(pos) > 5) {
@ -542,13 +546,10 @@ export async function goToPlayer(bot, username) {
return false;
}
let arrived = await goToPosition(bot, player.position.x, player.position.y, player.position.z);
if (!arrived) {
log(bot, `Failed to reach ${username}.`);
return false;
}
log(bot, `You have reached the player at position ${player.position}.`);
return true;
bot.pathfinder.setMovements(new pf.Movements(bot));
await bot.pathfinder.goto(new pf.goals.GoalFollow(player, 2), true);
log(bot, `You have reached ${username}.`);
}
@ -573,5 +574,52 @@ export async function followPlayer(bot, username) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
return true;
}
export async function defendPlayer(bot, username) {
/**
* Defend the given player endlessly, attacking any nearby monsters. Will not return until the code is manually stopped.
* @param {MinecraftBot} bot, reference to the minecraft bot.
* @param {string} username, the username of the player to defend.
* @returns {Promise<boolean>} true if the player was found, false otherwise.
* @example
* await skills.defendPlayer(bot, "bob");
**/
let player = bot.players[username].entity
if (!player)
return false;
bot.pathfinder.setMovements(new pf.Movements(bot));
bot.pathfinder.setGoal(new pf.goals.GoalFollow(player, 5), true);
log(bot, `Actively defending player ${username}.`);
while (!bot.interrupt_code) {
if (bot.entity.position.distanceTo(player.position) < 10) {
const mobs = getNearbyMobs(bot, 8).filter(mob => mob.type === 'mob' || mob.type === 'hostile');
const mob = mobs.sort((a, b) => a.position.distanceTo(player.position) - b.position.distanceTo(player.position))[0]; // get closest to player
if (mob) {
bot.pathfinder.stop();
log(bot, `Found ${mob.name}, attacking!`);
bot.chat(`Found ${mob.name}, attacking!`);
equipHighestAttack(bot);
bot.pvp.attack(mob);
while (getNearbyMobs(bot, 8).includes(mob)) {
await new Promise(resolve => setTimeout(resolve, 500));
console.log('attacking...')
if (bot.interrupt_code || bot.entity.position.distanceTo(player.position) > 16) {
console.log('stopping pvp...');
bot.pvp.stop();
break;
}
}
console.log('resuming pathfinder...')
bot.pathfinder.setMovements(new pf.Movements(bot));
bot.pathfinder.setGoal(new pf.goals.GoalFollow(player, 5), true);
}
}
await new Promise(resolve => setTimeout(resolve, 500));
}
return true;
}