mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-03-28 14:56:24 +01:00
created agent, refactored queries/skills
This commit is contained in:
parent
1b09360172
commit
a153316623
7 changed files with 347 additions and 154 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
|||
node_modules/
|
||||
package-lock.json
|
||||
temp.js
|
||||
scratch.js
|
78
agent.js
Normal file
78
agent.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
import { createBot } from 'mineflayer';
|
||||
import { pathfinder } from 'mineflayer-pathfinder';
|
||||
import { plugin } from 'mineflayer-collectblock';
|
||||
import { sendRequest } from './utils/gpt.js';
|
||||
import { History } from './utils/history.js';
|
||||
import { getQuery, containsQuery, getQueryDocs } from './utils/queries.js';
|
||||
import { getSkillDocs, containsCodeBlock, executeSkill } from './utils/skill_library.js';
|
||||
|
||||
|
||||
export class Agent {
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
|
||||
this.system_message = `You are a playful Minecraft bot named '${name}' that can communicate with players, see, move, mine, build, and interact with the world by writing and executing code.
|
||||
Act human-like as if you were a typical Minecraft player, rather than an AI. Be curt and brief in your responses, and do not give instructions unless asked.`;
|
||||
this.system_message += getQueryDocs();
|
||||
this.system_message += getSkillDocs();
|
||||
console.log(this.system_message);
|
||||
this.bot = createBot({
|
||||
host: 'localhost',
|
||||
port: 55916,
|
||||
username: name,
|
||||
});
|
||||
this.bot.loadPlugin(pathfinder)
|
||||
this.bot.loadPlugin(plugin)
|
||||
|
||||
this.history = new History(this);
|
||||
this.bot.on('login', () => {
|
||||
this.bot.chat('Hello world! I am ' + this.name);
|
||||
console.log(`${this.name} logged in.`);
|
||||
});
|
||||
|
||||
this.bot.on('chat', (username, message) => {
|
||||
if (username === this.name) return;
|
||||
console.log('received message from', username, ':', message);
|
||||
|
||||
this.respond(username, message);
|
||||
});
|
||||
}
|
||||
|
||||
async respond(username, message) {
|
||||
this.history.add(username, message);
|
||||
for (let i=0; i<5; i++) {
|
||||
let res = await sendRequest(this.history.getHistory(), this.system_message);
|
||||
this.history.add(this.name, res);
|
||||
let query_cmd = containsQuery(res);
|
||||
console.log(containsCodeBlock(res))
|
||||
if (query_cmd) { // contains query
|
||||
let message = res.substring(0, res.indexOf(query_cmd)).trim();
|
||||
if (message)
|
||||
this.bot.chat(message);
|
||||
console.log('Agent used query:', query_cmd);
|
||||
let query = getQuery(query_cmd);
|
||||
let query_res = query.perform(this.bot);
|
||||
this.history.add(this.name, query_res);
|
||||
}
|
||||
else if (containsCodeBlock(res)) { // contains code block
|
||||
let message = res.substring(0, res.indexOf('```')).trim();
|
||||
if (message)
|
||||
this.bot.chat(message);
|
||||
else
|
||||
this.bot.chat("Executing code...");
|
||||
let code = res.substring(res.indexOf('```')+3, res.lastIndexOf('```'));
|
||||
if (code) {
|
||||
console.log('executing code: ' + code);
|
||||
executeSkill(this.bot, code);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else { // conversation response
|
||||
this.bot.chat(res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Agent('andy');
|
13
utils/gpt.js
13
utils/gpt.js
|
@ -15,16 +15,9 @@ if (process.env.OPENAI_ORG_ID) {
|
|||
const openai = new OpenAIApi(openAiConfig);
|
||||
|
||||
|
||||
export async function sendRequest(turns, systemMessage, stop_seq) {
|
||||
export async function sendRequest(turns, systemMessage, stop_seq='***') {
|
||||
|
||||
let messages = [{'role': 'system', 'content': systemMessage}];
|
||||
for (let i = 0; i < turns.length; i++) {
|
||||
if (i % 2 == 0) {
|
||||
messages.push({'role': 'user', 'content': turns[i]});
|
||||
} else {
|
||||
messages.push({'role': 'assistant', 'content': turns[i]});
|
||||
}
|
||||
}
|
||||
let messages = [{'role': 'system', 'content': systemMessage}].concat(turns);
|
||||
|
||||
let res = null;
|
||||
try {
|
||||
|
@ -37,7 +30,7 @@ export async function sendRequest(turns, systemMessage, stop_seq) {
|
|||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
res = 'I am sorry, I do not know how to respond to that.';
|
||||
res = 'My brain disconnected, try again.';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -1,67 +1,43 @@
|
|||
var messages = [
|
||||
{'source': 'all', 'message': 'Hey! What are you up to?'},
|
||||
{'source': 'bot', 'message': `!action
|
||||
\`\`\`
|
||||
await skills.ExploreToFind(bot, 'coal_ore');
|
||||
await skills.EquipItem(bot, 'wooden_pickaxe');
|
||||
await skills.CollectBlock(bot, 'coal_ore', 10);
|
||||
\`\`\`
|
||||
let converse_examples = [
|
||||
{'role': 'user', 'content': '(from "miner_32") Hey! What are you up to?'},
|
||||
{'role': 'assistant', 'content': 'Nothing much miner_32, what do you need?'},
|
||||
|
||||
I'm looking for coal. Have you seen any?`},
|
||||
{'source': 'all', 'message': 'No, but can you help me collect wood?'},
|
||||
{'source': 'bot', 'message': `!blocks
|
||||
\`\`\`
|
||||
NEARBY_BLOCKS
|
||||
- oak_log
|
||||
- dirt
|
||||
- cobblestone
|
||||
- birch_log
|
||||
\`\`\`
|
||||
{'role': 'user', 'content': '(from "grombo_Xx") What do you see?'},
|
||||
{'role': 'assistant', 'content': 'Let me see... !blocks'},
|
||||
{'role': 'assistant', 'content': 'NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone'},
|
||||
{'role': 'assistant', 'content': 'I see some oak logs, dirt, and cobblestone.'},
|
||||
|
||||
Sure, do you want oak or birch?`},
|
||||
{'source': 'all', 'message': 'Thanks! Either is fine.'},
|
||||
{'source': 'bot', 'message': `I'll do that now.
|
||||
{'role': 'user', 'content': '(from "zZZn98") come here'},
|
||||
{'role': 'assistant', 'content': '```// I am going to navigate to zZZn98.\nawait skills.goToPlayer(bot, "zZZn98");```'},
|
||||
|
||||
!execute
|
||||
\`\`\`
|
||||
while (true) {
|
||||
await skills.CollectBlock(bot, 'oak_log', 1);
|
||||
await skills.goToPlayer(bot, 'username');
|
||||
await skills.DropItem(bot, 'oak_log', 1);
|
||||
}
|
||||
\`\`\``},
|
||||
{'source': 'all', 'message': 'come here'},
|
||||
{'source': 'bot', 'message': `Sure! I'm on my way.
|
||||
{'role': 'user', 'content': '(from "hanky") collect some sand for me please'},
|
||||
{'role': 'assistant', 'content': 'Collecting sand...```// I am going to collect 3 sand and give to hanky.\n\
|
||||
await skills.collectBlock(bot, "sand");\nawait skills.giveToPlayer(bot, "sand", "hanky");```'},
|
||||
|
||||
!execute
|
||||
\`\`\`
|
||||
await skills.goToPlayer(bot, 'user42');
|
||||
\`\`\``},
|
||||
];
|
||||
{'role': 'user', 'content': '(from "sarah_O.o") can you do a dance for me?'},
|
||||
{'role': 'assistant', 'content': "I don't know how to do that."},
|
||||
|
||||
{'role': 'user', 'content': '(from "hanky") kill that zombie!'},
|
||||
{'role': 'assistant', 'content': "I'm attacking! ```//I'm going to attack the nearest zombie.\n\
|
||||
let success = await skills.attackMob(bot, 'zombie');\n if (!success) { return 'I could not find a zombie to attack.'; }```"},
|
||||
]
|
||||
|
||||
export function addEvent(source, message) {
|
||||
messages.push({source, message});
|
||||
}
|
||||
|
||||
|
||||
export function getHistory(source) {
|
||||
let res = [];
|
||||
let lastSource = null;
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
if (lastSource != source && (messages[i].source == source || messages[i].source == 'all')) {
|
||||
res.push(messages[i].message);
|
||||
lastSource = source;
|
||||
} else if (lastSource == source && (messages[i].source == source || messages[i].source == 'all')) {
|
||||
res[-1] += '\n\n' + messages[i].message;
|
||||
} else if (lastSource == source && messages[i].source == 'bot') {
|
||||
res.push(messages[i].message);
|
||||
lastSource = 'bot';
|
||||
} else if (lastSource == 'bot' && messages[i].source == 'bot') {
|
||||
res[-1] += '\n\n' + messages[i].message;
|
||||
} else {
|
||||
lastSource = null;
|
||||
}
|
||||
export class History {
|
||||
constructor(agent) {
|
||||
this.agent = agent;
|
||||
this.turns = converse_examples;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
getHistory() {
|
||||
return this.turns;
|
||||
}
|
||||
|
||||
add(name, content) {
|
||||
let role = 'assistant';
|
||||
if (name !== this.agent.name) {
|
||||
role = 'user';
|
||||
content = `(from "${name}") ${content}`;
|
||||
}
|
||||
this.turns.push({role, content});
|
||||
}
|
||||
}
|
77
utils/queries.js
Normal file
77
utils/queries.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
import { getStats, getInventory, getBlocks, getNearbyEntities, getCraftable } from './context.js';
|
||||
|
||||
const pad = (str) => {
|
||||
return '\n' + str + '\n';
|
||||
}
|
||||
|
||||
const queryList = [
|
||||
{
|
||||
name: "!stats",
|
||||
description: "Get your bot's stats",
|
||||
perform: function (bot) {
|
||||
return pad(getStats(bot));
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "!inventory",
|
||||
description: "Get your bot's inventory.",
|
||||
perform: function (bot) {
|
||||
return pad(getInventory(bot));
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "!blocks",
|
||||
description: "Get the blocks near the bot.",
|
||||
perform: function (bot) {
|
||||
return pad(getBlocks(bot));
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "!craftable",
|
||||
description: "Get the craftable items with the bot's inventory.",
|
||||
perform: function (bot) {
|
||||
return pad(getCraftable(bot));
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "!entities",
|
||||
description: "Get the nearby players and entities.",
|
||||
perform: function (bot) {
|
||||
return pad(getNearbyEntities(bot));
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "!action",
|
||||
description: "Get the currently executing code.",
|
||||
perform: function (bot) {
|
||||
return pad(currentCode(bot));
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
const queryMap = {};
|
||||
for (let query of queryList) {
|
||||
queryMap[query.name] = query;
|
||||
}
|
||||
|
||||
export function getQuery(name) {
|
||||
return queryMap[name];
|
||||
}
|
||||
|
||||
export function containsQuery(message) {
|
||||
for (let query of queryList) {
|
||||
if (message.includes(query.name)) {
|
||||
return query.name;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getQueryDocs() {
|
||||
let docs = `\n*QUERY DOCS\n You can use the following commands to query for information about the world.
|
||||
Use the query name in your response and the next input will have the requested information.\n`;
|
||||
for (let query of queryList) {
|
||||
docs += query.name + ': ' + query.description + '\n';
|
||||
}
|
||||
return docs + '*\n';
|
||||
}
|
48
utils/skill_library.js
Normal file
48
utils/skill_library.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
import * as skills from './skills.js';
|
||||
import { writeFile } from 'fs';
|
||||
|
||||
let skillDict = {};
|
||||
for (let skill of Object.values(skills)) {
|
||||
skillDict[skill.name] = skill;
|
||||
}
|
||||
|
||||
export function getSkillDocs() {
|
||||
let docstring = '\n*SKILL DOCS\nThese skills are javascript functions that can be called with a js function by writing a code block. Ex: "```// write description comment and code here```" \n';
|
||||
for (let skillFunc of Object.values(skills)) {
|
||||
let str = skillFunc.toString();
|
||||
docstring += skillFunc.name;
|
||||
docstring += str.substring(str.indexOf('/**')+3, str.indexOf('**/')) + '\n';
|
||||
}
|
||||
return docstring + '*\n';
|
||||
}
|
||||
|
||||
export function containsCodeBlock(message) {
|
||||
console.log(message, message.indexOf('```'), message.indexOf('```') !== -1);
|
||||
return message.indexOf('```') !== -1;
|
||||
}
|
||||
|
||||
export async function executeSkill(bot, code) {
|
||||
let src = "import * as skills from './utils/skills.js';";
|
||||
src += "\nimport * as world from './utils/world.js';"
|
||||
src += `\n\nexport async function main(bot) {\n`;
|
||||
for (let line of code.split('\n')) {
|
||||
src += ` ${line}\n`;
|
||||
}
|
||||
src += `}\n`;
|
||||
console.log(src)
|
||||
|
||||
writeFile('./temp.js', src, (err) => {
|
||||
if (err) throw err;
|
||||
});
|
||||
|
||||
try {
|
||||
let execution_file = await import('../temp.js');
|
||||
//log execution_file contents
|
||||
console.log(execution_file);
|
||||
await execution_file.main(bot);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return false;
|
||||
}
|
||||
}
|
188
utils/skills.js
188
utils/skills.js
|
@ -3,15 +3,15 @@ import { getCraftingTable, getInventoryCounts, getInventoryStacks, getNearbyMobs
|
|||
import pf from 'mineflayer-pathfinder';
|
||||
|
||||
|
||||
/**
|
||||
* Attempt to craft the given item.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} item_name, the item name to craft.
|
||||
* @returns {Promise<boolean>} true if the item was crafted, false otherwise.
|
||||
* @example
|
||||
* await skills.craftItem(bot, "wooden_pickaxe");
|
||||
**/
|
||||
export async function craftItem(bot, itemName) {
|
||||
/**
|
||||
* Attempt to craft the given item.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} item_name, the item name to craft.
|
||||
* @returns {Promise<boolean>} true if the item was crafted, false otherwise.
|
||||
* @example
|
||||
* await skills.craftItem(bot, "wooden_pickaxe");
|
||||
**/
|
||||
const table = getCraftingTable(bot);
|
||||
let recipes = bot.recipesFor(getItemId(itemName), null, 1, table);
|
||||
await bot.craft(recipes[0], 1, null);
|
||||
|
@ -19,15 +19,15 @@ export async function craftItem(bot, itemName) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attack mob of the given type.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} mobType, the type of mob to attack.
|
||||
* @returns {Promise<boolean>} true if the mob was attacked, false if the mob type was not found.
|
||||
* @example
|
||||
* await skills.attackMob(bot, "zombie");
|
||||
**/
|
||||
export async function attackMob(bot, mobType) {
|
||||
/**
|
||||
* Attack mob of the given type.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} mobType, the type of mob to attack.
|
||||
* @returns {Promise<boolean>} true if the mob was attacked, false if the mob type was not found.
|
||||
* @example
|
||||
* await skills.attackMob(bot, "zombie");
|
||||
**/
|
||||
const mobs = getNearbyMobs(bot);
|
||||
for (let i = 0; i < mobs.length; i++) {
|
||||
if (mobs[i].mobType == mobType) {
|
||||
|
@ -39,15 +39,15 @@ export async function attackMob(bot, mobType) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collect one of the given block type.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} blockType, the type of block to collect.
|
||||
* @returns {Promise<boolean>} true if the block was collected, false if the block type was not found.
|
||||
* @example
|
||||
* await skills.collectBlock(bot, "oak_log");
|
||||
**/
|
||||
export async function collectBlock(bot, blockType) {
|
||||
/**
|
||||
* Collect one of the given block type.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} blockType, the type of block to collect.
|
||||
* @returns {Promise<boolean>} true if the block was collected, false if the block type was not found.
|
||||
* @example
|
||||
* await skills.collectBlock(bot, "oak_log");
|
||||
**/
|
||||
const blocks = getNearbyBlocks(bot);
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
if (blocks[i].name == blockType) {
|
||||
|
@ -59,18 +59,18 @@ export async function collectBlock(bot, blockType) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Break the block at the given position. Will use the bot's equipped item.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {number} x, the x coordinate of the block to break.
|
||||
* @param {number} y, the y coordinate of the block to break.
|
||||
* @param {number} z, the z coordinate of the block to break.
|
||||
* @returns {Promise<boolean>} true if the block was broken, false otherwise.
|
||||
* @example
|
||||
* let position = getPosition(bot);
|
||||
* await skills.breakBlockAt(bot, position.x, position.y - 1, position.x);
|
||||
**/
|
||||
export async function breakBlockAt(bot, x, y, z) {
|
||||
/**
|
||||
* Break the block at the given position. Will use the bot's equipped item.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {number} x, the x coordinate of the block to break.
|
||||
* @param {number} y, the y coordinate of the block to break.
|
||||
* @param {number} z, the z coordinate of the block to break.
|
||||
* @returns {Promise<boolean>} true if the block was broken, false otherwise.
|
||||
* @example
|
||||
* let position = getPosition(bot);
|
||||
* await skills.breakBlockAt(bot, position.x, position.y - 1, position.x);
|
||||
**/
|
||||
let current = bot.blockAt({ x: x, y: y, z: z });
|
||||
if (current.name != 'air')
|
||||
await bot.dig(current, true);
|
||||
|
@ -78,20 +78,19 @@ export async function breakBlockAt(bot, x, y, z) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Place the given block type at the given position.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} blockType, the type of block to place.
|
||||
* @param {number} x, the x coordinate to place the block at.
|
||||
* @param {number} y, the y coordinate to place the block at.
|
||||
* @param {number} z, the z coordinate to place the block at.
|
||||
* @returns {Promise<boolean>} true if the block was placed, false otherwise.
|
||||
* @example
|
||||
* let position = getPosition(bot);
|
||||
* await skills.placeBlock(bot, "oak_log", position.x + 1, position.y, position.x);
|
||||
**/
|
||||
export async function placeBlock(bot, blockType, x, y, z) {
|
||||
|
||||
/**
|
||||
* Place the given block type at the given position.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} blockType, the type of block to place.
|
||||
* @param {number} x, the x coordinate to place the block at.
|
||||
* @param {number} y, the y coordinate to place the block at.
|
||||
* @param {number} z, the z coordinate to place the block at.
|
||||
* @returns {Promise<boolean>} true if the block was placed, false otherwise.
|
||||
* @example
|
||||
* let position = getPosition(bot);
|
||||
* await skills.placeBlock(bot, "oak_log", position.x + 1, position.y, position.x);
|
||||
**/
|
||||
let referenceBlock = null;
|
||||
let refVec = null;
|
||||
if (bot.blockAt({ x: x + 1, y: y, z: z }).name != "air") {
|
||||
|
@ -133,15 +132,15 @@ export async function placeBlock(bot, blockType, x, y, z) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Equip the given item or block.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} itemName, the item or block name to equip.
|
||||
* @returns {Promise<boolean>} true if the item was equipped, false otherwise.
|
||||
* @example
|
||||
* await skills.equipItem(bot, "wooden_pickaxe");
|
||||
**/
|
||||
export async function equipItem(bot, itemName) {
|
||||
/**
|
||||
* Equip the given item or block.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} itemName, the item or block name to equip.
|
||||
* @returns {Promise<boolean>} true if the item was equipped, false otherwise.
|
||||
* @example
|
||||
* await skills.equipItem(bot, "wooden_pickaxe");
|
||||
**/
|
||||
let item = null;
|
||||
for (let stack of getInventoryStacks(bot)) {
|
||||
if (stack.name == itemName) {
|
||||
|
@ -156,18 +155,18 @@ export async function equipItem(bot, itemName) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Navigate to the given position.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {number} x, the x coordinate to navigate to. If null, the bot's current x coordinate will be used.
|
||||
* @param {number} y, the y coordinate to navigate to. If null, the bot's current y coordinate will be used.
|
||||
* @param {number} z, the z coordinate to navigate to. If null, the bot's current z coordinate will be used.
|
||||
* @returns {Promise<boolean>} true if the position was reached, false otherwise.
|
||||
* @example
|
||||
* let position = getPosition(bot);
|
||||
* await skills.goToPosition(bot, position.x, position.y, position.x + 20);
|
||||
**/
|
||||
export async function goToPosition(bot, x, y, z) {
|
||||
/**
|
||||
* Navigate to the given position.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {number} x, the x coordinate to navigate to. If null, the bot's current x coordinate will be used.
|
||||
* @param {number} y, the y coordinate to navigate to. If null, the bot's current y coordinate will be used.
|
||||
* @param {number} z, the z coordinate to navigate to. If null, the bot's current z coordinate will be used.
|
||||
* @returns {Promise<boolean>} true if the position was reached, false otherwise.
|
||||
* @example
|
||||
* let position = getPosition(bot);
|
||||
* await skills.goToPosition(bot, position.x, position.y, position.x + 20);
|
||||
**/
|
||||
if (x == null) x = bot.entity.position.x;
|
||||
if (y == null) y = bot.entity.position.y;
|
||||
if (z == null) z = bot.entity.position.z;
|
||||
|
@ -178,16 +177,16 @@ export async function goToPosition(bot, x, y, z) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Give one of the specified item to the specified player
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} itemType, the name of the item to give.
|
||||
* @param {string} username, the username of the player to give the item to.
|
||||
* @returns {Promise<boolean>} true if the item was given, false otherwise.
|
||||
* @example
|
||||
* await skills.giveToPlayer(bot, "oak_log", "player1");
|
||||
**/
|
||||
export async function giveToPlayer(bot, itemType, username) {
|
||||
/**
|
||||
* Give one of the specified item to the specified player
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} itemType, the name of the item to give.
|
||||
* @param {string} username, the username of the player to give the item to.
|
||||
* @returns {Promise<boolean>} true if the item was given, false otherwise.
|
||||
* @example
|
||||
* await skills.giveToPlayer(bot, "oak_log", "player1");
|
||||
**/
|
||||
let player = bot.players[username].entity
|
||||
if (!player)
|
||||
return false;
|
||||
|
@ -201,15 +200,15 @@ export async function giveToPlayer(bot, itemType, username) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Navigate to the given player.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} username, the username of the player to navigate to.
|
||||
* @returns {Promise<boolean>} true if the player was found, false otherwise.
|
||||
* @example
|
||||
* await skills.goToPlayer(bot, "player");
|
||||
**/
|
||||
export async function goToPlayer(bot, username) {
|
||||
/**
|
||||
* Navigate to the given player.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} username, the username of the player to navigate to.
|
||||
* @returns {Promise<boolean>} true if the player was found, false otherwise.
|
||||
* @example
|
||||
* await skills.goToPlayer(bot, "player");
|
||||
**/
|
||||
let player = bot.players[username].entity
|
||||
if (!player)
|
||||
return false;
|
||||
|
@ -219,3 +218,24 @@ export async function goToPlayer(bot, username) {
|
|||
bot.pathfinder.setGoal(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 3));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
export async function followPlayer(bot, username) {
|
||||
/**
|
||||
* Follow the given player endlessly.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} username, the username of the player to follow.
|
||||
* @returns {Promise<boolean>} true if the player was found, false otherwise.
|
||||
* @example
|
||||
* await skills.followPlayer(bot, "player");
|
||||
**/
|
||||
let player = bot.players[username].entity
|
||||
if (!player)
|
||||
return false;
|
||||
|
||||
bot.pathfinder.setMovements(new pf.Movements(bot));
|
||||
let pos = player.position;
|
||||
bot.pathfinder.setGoal(new pf.goals.GoalFollow(player, 3), true);
|
||||
return true;
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue