mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-06-08 10:15:55 +02:00
history and action refactor
This commit is contained in:
parent
a5442d554d
commit
c53777977d
10 changed files with 294 additions and 171 deletions
|
@ -19,4 +19,4 @@ Start minecraft server on localhost port `55916`
|
|||
|
||||
Add `OPENAI_API_KEY` (and optionally `OPENAI_ORG_ID`) to your environment variables.
|
||||
|
||||
run `npm main.py`
|
||||
run `npm main.js`
|
||||
|
|
122
act.js
122
act.js
|
@ -1,32 +1,13 @@
|
|||
import { writeFile } from 'fs';
|
||||
|
||||
import { getStats, getInventory, getNearbyBlocks, getNearbyPlayers, getNearbyEntities, getCraftable, getDetailedSkills } from './utils/context.js';
|
||||
import { getDetailedSkills, getWorldFunctions } from './utils/context.js';
|
||||
import { sendRequest } from './utils/gpt.js';
|
||||
|
||||
|
||||
function buildSystemMessage(bot) {
|
||||
let message = 'You are a helpful Minecraft bot. Given the dialogue and currently running program, reflect on what you are doing and generate javascript code to accomplish that goal. If your new code is empty, no change will be made to your currently running program. Use only functions listed below to write your code.';
|
||||
let stats = getStats(bot);
|
||||
if (stats)
|
||||
message += "\n\n" + stats;
|
||||
let inventory = getInventory(bot);
|
||||
if (inventory)
|
||||
message += "\n\n" + inventory;
|
||||
let nearbyBlocks = getNearbyBlocks(bot);
|
||||
if (nearbyBlocks)
|
||||
message += "\n\n" + nearbyBlocks;
|
||||
let nearbyPlayers = getNearbyPlayers(bot);
|
||||
if (nearbyPlayers)
|
||||
message += "\n\n" + nearbyPlayers;
|
||||
let nearbyEntities = getNearbyEntities(bot);
|
||||
if (nearbyEntities)
|
||||
message += "\n\n" + nearbyEntities;
|
||||
let craftable = getCraftable(bot);
|
||||
if (craftable)
|
||||
message += "\n\n" + craftable;
|
||||
let skills = getDetailedSkills();
|
||||
if (skills)
|
||||
message += "\n\n" + skills;
|
||||
let message = 'You are a helpful Minecraft bot. Given the dialogue, reflect on what you are doing and generate javascript code to accomplish that goal. Use only functions listed below to write your code.';
|
||||
message += "\n\n" + getDetailedSkills();
|
||||
message += "\n\n" + getWorldFunctions();
|
||||
return message;
|
||||
}
|
||||
|
||||
|
@ -34,38 +15,64 @@ function buildSystemMessage(bot) {
|
|||
function buildExamples() {
|
||||
return[
|
||||
`mr_steve2: Will you help me collect wood?
|
||||
You: I'd be glad to help you collect wood.
|
||||
Current code:
|
||||
|
||||
!blocks
|
||||
\`\`\`
|
||||
await skills.ExploreToFind(bot, 'iron_ore');
|
||||
\`\`\``,
|
||||
`I'm going to help mr_steve2 collect wood rather than look for iron ore. The type of wood block nearby is 'oak_log'. I'll adjust my code to collect 'oak_log' for mr_steve2 until told to stop.
|
||||
NEARBY_BLOCKS
|
||||
- oak_log
|
||||
- dirt
|
||||
- cobblestone
|
||||
\`\`\`
|
||||
while (true) {
|
||||
await skills.CollectBlock(bot, 'oak_log', 1);
|
||||
await skills.GoToPlayer(bot, 'mr_steve2');
|
||||
await skills.DropItem(bot, 'oak_log', 1);
|
||||
}
|
||||
|
||||
Me: I'd be glad to help you collect wood.`,
|
||||
`I'm going to help mr_steve2 collect wood. The type of wood block nearby is 'oak_log'. I'll adjust my code to collect 10 'oak_log' for mr_steve2.
|
||||
\`\`\`
|
||||
await skills.CollectBlock(bot, 'oak_log', 10);
|
||||
await skills.GoToPlayer(bot, 'mr_steve2');
|
||||
await skills.DropItem(bot, 'oak_log', 10);
|
||||
\`\`\``,
|
||||
`sally32: What are you doing?
|
||||
You: I'm looking for coal. Have you seen any?
|
||||
Current code:
|
||||
|
||||
!action
|
||||
\`\`\`
|
||||
await skills.ExploreToFind(bot, 'coal_ore');
|
||||
await skills.EquipItem(bot, 'wooden_pickaxe');
|
||||
await skills.CollectBlock(bot, 'coal_ore', 10);
|
||||
\`\`\``,
|
||||
`I responded to a question. I do not need to change my code.
|
||||
\`\`\`
|
||||
|
||||
Me: I'm looking for coal. Have you seen any?
|
||||
|
||||
sally32: Yes, there's some in this cave, follow me.`,
|
||||
`I'm going to follow sally32 to the cave and collect coal. I'll adjust my code to follow sally32 until I find coal_ore and then I'll mine it.
|
||||
\`\`\`
|
||||
while (true) {
|
||||
await skills.GoToPlayer(bot, 'sally32');
|
||||
if (world.getNearbyBlocks(bot).includes('coal_ore')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
await skills.EquipItem(bot, 'wooden_pickaxe');
|
||||
await skills.CollectBlock(bot, 'coal_ore', 10);
|
||||
\`\`\``,
|
||||
`user42: come here
|
||||
|
||||
Me: Sure! I'm on my way.`,
|
||||
`I'm going to navigate to user42.
|
||||
\`\`\`
|
||||
await skills.GoToPlayer(bot, 'user42');
|
||||
\`\`\``,
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
async function executeCode(bot, code) {
|
||||
let src = `import * as skills from './utils/skills.js';\n\n`;
|
||||
src += `export async function main(bot) {\n`;
|
||||
for (let line of code.split('\n')) {
|
||||
export var currentCode = '';
|
||||
|
||||
|
||||
export async function executeCode(bot) {
|
||||
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 currentCode.split('\n')) {
|
||||
src += ` ${line}\n`;
|
||||
}
|
||||
src += `}\n`;
|
||||
|
@ -73,14 +80,38 @@ async function executeCode(bot, code) {
|
|||
writeFile('./temp.js', src, (err) => {
|
||||
if (err) throw err;
|
||||
});
|
||||
await (await import('./temp.js')).main(bot);
|
||||
|
||||
console.log('executing code...\n' + currentCode);
|
||||
try {
|
||||
await (await import('./temp.js')).main(bot);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
var currentCode = '';
|
||||
export async function actIfNeeded(bot, username, message, res) {
|
||||
export async function writeCode(bot, username, messages) {
|
||||
let turns = buildExamples();
|
||||
turns.push(`${username}: ${message}\nYou: ${res}\nCurrent Code:\`\`\`\n${currentCode}\n\`\`\``);
|
||||
|
||||
// For now, get rid of the first 6 example messages
|
||||
messages = messages.slice(6);
|
||||
|
||||
let startIndex = messages.length - 6;
|
||||
if (startIndex < 0)
|
||||
startIndex = 0;
|
||||
|
||||
turns.push('');
|
||||
for (let i = startIndex; i < messages.length; i++) {
|
||||
if (i % 2 == 0) {
|
||||
turns[turns.length - 1] += `\n\n${username}: ${messages[i]}`;
|
||||
} else {
|
||||
turns[turns.length - 1] += `\n\nMe: ${messages[i]}`;
|
||||
}
|
||||
}
|
||||
turns[turns.length - 1] = turns[turns.length - 1].trim();
|
||||
let systemMessage = buildSystemMessage(bot);
|
||||
let actResponse = await sendRequest(turns, systemMessage);
|
||||
console.log(actResponse);
|
||||
|
@ -95,6 +126,5 @@ export async function actIfNeeded(bot, username, message, res) {
|
|||
if (currentCode.slice(0, 10) == 'javascript')
|
||||
currentCode = currentCode.slice(10).trim();
|
||||
|
||||
await executeCode(bot, currentCode);
|
||||
return true;
|
||||
}
|
||||
|
|
117
chat.js
117
chat.js
|
@ -1,67 +1,72 @@
|
|||
import { sendRequest } from './utils/gpt.js';
|
||||
import { getHistory, addEvent } from './utils/history.js';
|
||||
import { getStats, getInventory, getNearbyBlocks, getNearbyPlayers, getNearbyEntities, getCraftable } from './utils/context.js';
|
||||
import { getStats, getInventory, getBlocks, getNearbyPlayers, getNearbyEntities, getCraftable } from './utils/context.js';
|
||||
import { currentCode, executeCode, writeCode } from './act.js';
|
||||
|
||||
|
||||
function buildSystemMessage(bot) {
|
||||
let message = 'You are a helpful Minecraft bot that can communicate with players and execute actions in the environment. Act human-like as if you were a typical Minecraft player, rather than an AI. Do not give instructions unless asked.';
|
||||
let stats = getStats(bot);
|
||||
if (stats)
|
||||
message += "\n\n" + stats;
|
||||
let inventory = getInventory(bot);
|
||||
if (inventory)
|
||||
message += "\n\n" + inventory;
|
||||
let nearbyBlocks = getNearbyBlocks(bot);
|
||||
if (nearbyBlocks)
|
||||
message += "\n\n" + nearbyBlocks;
|
||||
let nearbyPlayers = getNearbyPlayers(bot);
|
||||
if (nearbyPlayers)
|
||||
message += "\n\n" + nearbyPlayers;
|
||||
let nearbyEntities = getNearbyEntities(bot);
|
||||
if (nearbyEntities)
|
||||
message += "\n\n" + nearbyEntities;
|
||||
let craftable = getCraftable(bot);
|
||||
if (craftable)
|
||||
message += "\n\n" + craftable;
|
||||
let message = 'You are a playful Minecraft bot that can communicate with players and move within and interact with the world.';
|
||||
message += ' Act human-like as if you were a typical Minecraft player, rather than an AI.';
|
||||
message += ' Do not give instructions unless asked, and always be brief in your responses.';
|
||||
message += '\n\nYou can use the following commands followed by to query for information about the world.';
|
||||
message += ' The query response will be returned between sets of "\`\`\`":';
|
||||
message += '\n!stats - get your current health and other player stats';
|
||||
message += '\n!inventory - get your current inventory';
|
||||
message += '\n!blocks - get a list of nearby blocks';
|
||||
message += '\n!craftable - get a list of craftable items with your current inventory';
|
||||
message += '\n!entities - get a list of nearby players and entities';
|
||||
message += '\n!action - prints the currently executing code';
|
||||
message += '\n\nYou can also execute actions in Minecraft by writing javascript code.';
|
||||
message += ' To do so, simply begin a codeblock with the "!execute" command. For example:';
|
||||
message += '\n!execute\n\`\`\`\nCODE\n\`\`\`';
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
function buildTurns(user, message) {
|
||||
let history = getHistory();
|
||||
|
||||
let turns = [];
|
||||
let lastSource = null;
|
||||
for (let i = 0; i < history.length; i++) {
|
||||
|
||||
if (history[i].source == 'bot' && lastSource == null) {
|
||||
turns.push('(You spawn into the word.)');
|
||||
turns.push(history[i].message);
|
||||
|
||||
} else if (history[i].source == 'bot' && lastSource != 'bot') {
|
||||
turns.push(history[i].message);
|
||||
|
||||
} else if (history[i].source == 'bot' && lastSource == 'bot') {
|
||||
turns[turns.length - 1] += '\n\n' + history[i].message;
|
||||
|
||||
} else if (history[i].source != 'bot' && lastSource == 'bot') {
|
||||
turns.push(history[i].message);
|
||||
|
||||
} else if (history[i].source != 'bot' && lastSource != 'bot') {
|
||||
turns[turns.length - 1] += '\n\n' + history[i].message;
|
||||
}
|
||||
lastSource = history[i].source;
|
||||
}
|
||||
return turns;
|
||||
}
|
||||
|
||||
|
||||
export async function getChatResponse(bot, user, message) {
|
||||
addEvent(user, user + ': ' + message);
|
||||
let turns = buildTurns(user, message);
|
||||
addEvent(user, message);
|
||||
let turns = getHistory(user);
|
||||
let systemMessage = buildSystemMessage(bot);
|
||||
let res = await sendRequest(turns, systemMessage);
|
||||
console.log('sending chat:', res);
|
||||
addEvent('bot', res);
|
||||
return res;
|
||||
}
|
||||
|
||||
let botResponse = '';
|
||||
let botEvent = '';
|
||||
let res = null;
|
||||
for (let i = 0; i < 5; i++) {
|
||||
|
||||
res = await sendRequest(turns, systemMessage, '\`\`\`');
|
||||
console.log('received chat:', res);
|
||||
|
||||
let queryRes = null;
|
||||
if (res.trim().slice(res.length - 7) == '!stats') {
|
||||
botResponse += '\n' + res.trim().slice(0, res.length - 7).trim();
|
||||
queryRes = '\n\n!stats\n\`\`\`\n' + getStats(bot) + '\n\`\`\`';
|
||||
} else if (res.trim().slice(res.length - 11) == '!inventory') {
|
||||
botResponse += '\n' + res.trim().slice(0, res.length - 11).trim();
|
||||
queryRes = '\n\n!inventory\n\`\`\`\n' + getInventory(bot) + '\n\`\`\`';
|
||||
} else if (res.trim().slice(res.length - 8) == '!blocks') {
|
||||
botResponse += '\n' + res.trim().slice(0, res.length - 8).trim();
|
||||
queryRes = '\n\n!blocks\n\`\`\`\n' + getBlocks(bot) + '\n\`\`\`';
|
||||
} else if (res.trim().slice(res.length - 11) == '!craftable') {
|
||||
botResponse += '\n' + res.trim().slice(0, res.length - 11).trim();
|
||||
queryRes = '\n\n!craftable\n\`\`\`\n' + getCraftable(bot) + '\n\`\`\`';
|
||||
} else if (res.trim().slice(res.length - 10) == '!entities') {
|
||||
botResponse += '\n' + res.trim().slice(0, res.length - 10).trim();
|
||||
queryRes = '\n\n!entities\n\`\`\`\n' + getNearbyPlayers(bot) + '\n' + getNearbyEntities(bot) + '\n\`\`\`';
|
||||
} else if (res.trim().slice(res.length - 8) == '!action') {
|
||||
botResponse += '\n' + res.trim().slice(0, res.length - 8).trim();
|
||||
queryRes = '\n\n!action\n\`\`\`\n' + currentCode + '\n\`\`\`';
|
||||
} else if (res.trim().slice(res.length - 9) == '!execute') {
|
||||
botResponse += '\n' + res.trim().slice(0, res.length - 9).trim();
|
||||
queryRes = '\n\n!execute\n\`\`\`\n' + await writeCode(bot, user, turns.concat(botResponse), botResponse) + '\n\`\`\`';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
botEvent += queryRes;
|
||||
turns[turns.length - 1] += queryRes
|
||||
}
|
||||
|
||||
console.log('sending chat:', botResponse);
|
||||
addEvent('bot', botEvent);
|
||||
return botResponse.trim();
|
||||
}
|
||||
|
|
10
main.js
10
main.js
|
@ -3,7 +3,7 @@ import { pathfinder } from 'mineflayer-pathfinder';
|
|||
import { plugin } from 'mineflayer-collectblock';
|
||||
|
||||
import { getChatResponse } from './chat.js';
|
||||
import { actIfNeeded } from './act.js';
|
||||
import { executeCode, writeCode } from './act.js';
|
||||
|
||||
|
||||
async function handleMessage(username, message) {
|
||||
|
@ -13,7 +13,7 @@ async function handleMessage(username, message) {
|
|||
let chat = await getChatResponse(bot, username, message);
|
||||
bot.chat(chat);
|
||||
|
||||
let actResult = await actIfNeeded(bot, username, message, chat);
|
||||
let actResult = await executeCode(bot);
|
||||
if (actResult) {
|
||||
console.log('completed action');
|
||||
}
|
||||
|
@ -27,10 +27,10 @@ const bot = createBot({
|
|||
})
|
||||
bot.loadPlugin(pathfinder)
|
||||
bot.loadPlugin(plugin)
|
||||
|
||||
// await writeCode(bot, 'all', ['all: Now, you should set your own personal goal.']);
|
||||
// executeCode(bot);
|
||||
console.log('bot created')
|
||||
|
||||
|
||||
bot.on('chat', handleMessage);
|
||||
|
||||
|
||||
bot.on('whisper', handleMessage);
|
||||
|
|
|
@ -1,55 +1,72 @@
|
|||
import { getDocstrings } from './skills.js';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
import { getNearbyBlocks } from './world.js';
|
||||
|
||||
|
||||
export function getStats(bot) {
|
||||
return "";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
export function getInventory(bot) {
|
||||
return "";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
export function getNearbyBlocks(bot) {
|
||||
return "";
|
||||
export function getBlocks(bot) {
|
||||
let res = 'NEARBY_BLOCKS\n';
|
||||
let blocks = getNearbyBlocks(bot);
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
res += `- ${blocks[i]}\n`;
|
||||
}
|
||||
return res.trim();
|
||||
}
|
||||
|
||||
|
||||
export function getNearbyEntities(bot) {
|
||||
return "";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
export function getNearbyPlayers(bot) {
|
||||
return "";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
export function getCraftable(bot) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
export function getSkills() {
|
||||
let res = '';
|
||||
let docs = getDocstrings();
|
||||
let lines = null;
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
lines = docs[i].trim().split('\n');
|
||||
res += lines[lines.length - 1] + '\n';
|
||||
}
|
||||
res = res.slice(0, res.length - 1);
|
||||
return res;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
export function getDetailedSkills() {
|
||||
let res = 'namespace skills {';
|
||||
let docs = getDocstrings();
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
res += '\t' + docs[i] + '\n\n';
|
||||
let contents = readFileSync("./utils/skills.js", "utf-8").split('\n');
|
||||
for (let i = 0; i < contents.length; i++) {
|
||||
if (contents[i].slice(0, 3) == '/**') {
|
||||
res += '\t' + contents[i];
|
||||
} else if (contents[i].slice(0, 2) == ' *') {
|
||||
res += '\t' + contents[i];
|
||||
} else if (contents[i].slice(0, 4) == ' **/') {
|
||||
res += '\t' + contents[i] + '\n\n';
|
||||
}
|
||||
}
|
||||
res += '}';
|
||||
res = res.trim() + '\n}'
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
export function getWorldFunctions() {
|
||||
let res = 'namespace world {';
|
||||
let contents = readFileSync("./utils/world.js", "utf-8").split('\n');
|
||||
for (let i = 0; i < contents.length; i++) {
|
||||
if (contents[i].slice(0, 3) == '/**') {
|
||||
res += '\t' + contents[i];
|
||||
} else if (contents[i].slice(0, 2) == ' *') {
|
||||
res += '\t' + contents[i];
|
||||
} else if (contents[i].slice(0, 4) == ' **/') {
|
||||
res += '\t' + contents[i] + '\n\n';
|
||||
}
|
||||
}
|
||||
res = res.trim() + '\n}'
|
||||
return res;
|
||||
}
|
||||
|
|
15
utils/gpt.js
15
utils/gpt.js
|
@ -1,4 +1,4 @@
|
|||
import { Configuration, OpenAIApi } from "openai";
|
||||
import { Configuration, OpenAIApi } from 'openai';
|
||||
|
||||
|
||||
var openAiConfig = null;
|
||||
|
@ -15,28 +15,29 @@ if (process.env.OPENAI_ORG_ID) {
|
|||
const openai = new OpenAIApi(openAiConfig);
|
||||
|
||||
|
||||
export async function sendRequest(turns, systemMessage) {
|
||||
export async function sendRequest(turns, systemMessage, stop_seq) {
|
||||
|
||||
let messages = [{"role": "system", "content": systemMessage}];
|
||||
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]});
|
||||
messages.push({'role': 'user', 'content': turns[i]});
|
||||
} else {
|
||||
messages.push({"role": "assistant", "content": turns[i]});
|
||||
messages.push({'role': 'assistant', 'content': turns[i]});
|
||||
}
|
||||
}
|
||||
|
||||
let res = null;
|
||||
try {
|
||||
let completion = await openai.createChatCompletion({
|
||||
model: "gpt-3.5-turbo",
|
||||
model: 'gpt-3.5-turbo',
|
||||
messages: messages,
|
||||
stop: stop_seq,
|
||||
});
|
||||
res = completion.data.choices[0].message.content;
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
res = "I'm sorry, I don't know how to respond to that.";
|
||||
res = 'I amm sorry, I do not know how to respond to that.';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,36 @@
|
|||
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);
|
||||
\`\`\`
|
||||
|
||||
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
|
||||
\`\`\`
|
||||
|
||||
Sure, do you want oak or birch?`},
|
||||
{'source': 'all', 'message': 'Thanks! Either is fine.'},
|
||||
{'source': 'bot', 'message': `I'll do that now.
|
||||
|
||||
var messages = [];
|
||||
!execute
|
||||
\`\`\`
|
||||
while (true) {
|
||||
await skills.CollectBlock(bot, 'oak_log', 1);
|
||||
await skills.GoToPlayer(bot, 'username');
|
||||
await skills.DropItem(bot, 'oak_log', 1);
|
||||
}
|
||||
\`\`\``}
|
||||
];
|
||||
|
||||
|
||||
export function addEvent(source, message) {
|
||||
|
@ -9,6 +38,23 @@ export function addEvent(source, message) {
|
|||
}
|
||||
|
||||
|
||||
export function getHistory() {
|
||||
return messages;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,18 @@ import minecraftData from 'minecraft-data';
|
|||
var mcdata = minecraftData("1.19.3");
|
||||
|
||||
|
||||
|
||||
export function getItemId(item) {
|
||||
return mcdata.itemsByName[item_type].id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function getAllBlockIds(ignore) {
|
||||
let blocks = []
|
||||
for (let i = 0; i < mcdata.blocks.length; i++) {
|
||||
if (!ignore.includes(mcdata.blocks[i].name)) {
|
||||
blocks.push(mcdata.blocks[i].id);
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,30 +2,14 @@ import { getItemId } from "./mcdata.js";
|
|||
import pf from 'mineflayer-pathfinder';
|
||||
|
||||
|
||||
export function getDocstrings() {
|
||||
return [
|
||||
`/**
|
||||
* 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");
|
||||
**/
|
||||
async function CraftItem(bot: MinecraftBot, item_name: string): Promise<boolean>`,
|
||||
`/**
|
||||
* 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");
|
||||
**/
|
||||
async function GoToPlayer(bot: MinecraftBot, username: string): Promise<boolean>`
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
let recipes = bot.recipesFor(getItemId(itemName), null, 1, null); // TODO add crafting table as final arg
|
||||
await bot.craft(recipes[0], 1, null);
|
||||
|
@ -33,6 +17,14 @@ export async function CraftItem(bot, itemName) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
let player = bot.players[username].entity
|
||||
if (!player)
|
||||
|
@ -40,6 +32,6 @@ export async function GoToPlayer(bot, username) {
|
|||
|
||||
bot.pathfinder.setMovements(new pf.Movements(bot));
|
||||
let pos = player.position;
|
||||
bot.pathfinder.setGoal(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 1));
|
||||
bot.pathfinder.setGoal(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 3));
|
||||
return true;
|
||||
}
|
||||
|
|
21
utils/world.js
Normal file
21
utils/world.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { getAllBlockIds } from './mcdata.js';
|
||||
|
||||
|
||||
/**
|
||||
* Get a list of all nearby blocks.
|
||||
* @param {Bot} bot - The bot to get nearby blocks for.
|
||||
* @returns {string[]} - A list of all nearby blocks.
|
||||
* @example
|
||||
* let blocks = world.getNearbyBlocks(bot);
|
||||
**/
|
||||
export function getNearbyBlocks(bot) {
|
||||
let positions = bot.findBlocks({'matching': getAllBlockIds(['air']), 'maxDistance': 16, 'count': 4096});
|
||||
let found = [];
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
let block = bot.blockAt(positions[i]);
|
||||
if (!found.includes(block.name)) {
|
||||
found.push(block.name);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
Loading…
Add table
Reference in a new issue