From 126537be67f66a6a40447dc35a8e1d6155354e14 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Thu, 19 Oct 2023 22:20:19 -0500 Subject: [PATCH] refactored commands into map of objects/funcs --- chat.js | 77 +++++++++++++++++++-------------------------- main.js | 7 ++++- utils/commands.js | 80 +++++++++++++++++++++++++++++++++++++++++++++++ utils/world.js | 2 +- 4 files changed, 119 insertions(+), 47 deletions(-) create mode 100644 utils/commands.js diff --git a/chat.js b/chat.js index 4d0e490..e7a5e0c 100644 --- a/chat.js +++ b/chat.js @@ -1,67 +1,54 @@ import { sendRequest } from './utils/gpt.js'; import { getHistory, addEvent } from './utils/history.js'; -import { getStats, getInventory, getBlocks, getNearbyEntities, getCraftable } from './utils/context.js'; -import { currentCode, writeCode } from './act.js'; +import { getStats, getInventory, getBlocks, getNearbyPlayers, getNearbyEntities, getCraftable } from './utils/context.js'; +import { currentCode, executeCode, writeCode } from './act.js'; +import { getCommand, getCommandDocs } from './utils/commands.js'; -function buildSystemMessage() { - 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 player and world stats (current health, time of day, etc.)'; - 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 - get the currently executing code'; - message += '\n\nYou can also execute actions such as moving and mining 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\`\`\`'; +function buildSystemMessage(bot) { + let message = `You are a playful Minecraft bot that can communicate with players and move within and interact with the world.'; + Act human-like as if you were a typical Minecraft player, rather than an AI.'; + Do not give instructions unless asked, and always be brief in your responses.\n`; + message += getCommandDocs(); return message; } + +const MAX_TURNS = 5; export async function getChatResponse(bot, user, message) { addEvent(user, message); let turns = getHistory(user); let systemMessage = buildSystemMessage(); - let botResponse = ''; + let botFinalRes = ''; let botEvent = ''; - let res = null; - for (let i = 0; i < 5; i++) { + let botRes = null; + console.log("*recieved chat:", message) + for (let i = 0; i < MAX_TURNS; i++) { + botRes = await sendRequest(turns, systemMessage, '\`\`\`'); + console.log(`bot response ${i}:`, botRes); - res = await sendRequest(turns, systemMessage, '\`\`\`'); - console.log('received chat:', res); - - let queryRes = null; - if (res.includes('!stats')) { - queryRes = '\n\n!stats\n\`\`\`\n' + getStats(bot) + '\n\`\`\`'; - } else if (res.includes('!inventory')) { - queryRes = '\n\n!inventory\n\`\`\`\n' + getInventory(bot) + '\n\`\`\`'; - } else if (res.includes('!blocks')) { - queryRes = '\n\n!blocks\n\`\`\`\n' + getBlocks(bot) + '\n\`\`\`'; - } else if (res.includes('!craftable')) { - queryRes = '\n\n!craftable\n\`\`\`\n' + getCraftable(bot) + '\n\`\`\`'; - } else if (res.includes('!entities')) { - queryRes = '\n\n!entities\n\`\`\`\n' + getNearbyEntities(bot) + '\n\`\`\`'; - } else if (res.includes('!action')) { - queryRes = '\n\n!action\n\`\`\`\n' + currentCode + '\n\`\`\`'; - } else if (res.includes('!execute')) { - queryRes = '\n\n!execute\n\`\`\`\n' + await writeCode(bot, user, turns.concat(botResponse), botResponse) + '\n\`\`\`'; + let commandRes = null; + let firstword = botRes.trim().split(/\s+/)[0]; + let command = getCommand(firstword); + if (command) { + console.log('Executing command:', command.name) + commandRes = await command.perform(bot); + + botEvent += `/n${command.name}/n${commandRes}`; + if (i == 0) + turns.push(botEvent); + else + turns[turns.length - 1] += botEvent; } else { - botResponse += '\n' + res.trim(); + botFinalRes = botRes; break; } - - console.log('query response:', queryRes); - botEvent += queryRes; - turns[turns.length - 1] += queryRes } - console.log('sending chat:', botResponse.trim()); + console.log('*bot response', botFinalRes); + console.log('*bot event', botEvent); addEvent('bot', botEvent); - return botResponse.trim(); + return botFinalRes.trim(); } diff --git a/main.js b/main.js index f90043a..4f68414 100644 --- a/main.js +++ b/main.js @@ -6,6 +6,7 @@ import { getChatResponse } from './chat.js'; import { executeCode } from './act.js'; + async function handleMessage(username, message) { if (username === bot.username) return; console.log('received message from', username, ':', message); @@ -23,7 +24,7 @@ async function handleMessage(username, message) { const bot = createBot({ host: '127.0.0.1', port: 55916, - username: 'andi' + username: 'andy' }) bot.loadPlugin(pathfinder) bot.loadPlugin(plugin) @@ -32,3 +33,7 @@ console.log('bot created') bot.on('chat', handleMessage); bot.on('whisper', handleMessage); + +bot.once("login", () => { + bot.chat('hello world!') +}); \ No newline at end of file diff --git a/utils/commands.js b/utils/commands.js new file mode 100644 index 0000000..5167a8a --- /dev/null +++ b/utils/commands.js @@ -0,0 +1,80 @@ +import { getStats, getInventory, getBlocks, getNearbyPlayers, getNearbyEntities, getCraftable } from './context.js'; +import { currentCode, executeCode, writeCode } from '../act.js'; + +const pad = (str) => { + return '\n\`\`\`\n' + str + '\n\`\`\`'; +} + +const commandsList = [ + { + name: "!stats", + description: "Get the bot's stats (name, health, food, saturation, armor, held item, position, velocity, gamemode, experience, level, effects).", + perform: function (bot) { + return pad(getStats(bot)); + } + }, + { + name: "!inventory", + description: "Get the 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(getNearbyPlayers(bot) + '\n' + getNearbyEntities(bot)); + } + }, + { + name: "!action", + description: "Get the currently executing code.", + perform: function (bot) { + return pad(currentCode(bot)); + } + }, + { + name: "!execute", + description: "Execute actions in the game by writing and calling javascript code with the following command: \n!execute\n\`\`\`\nCODE\n\`\`\`", + perform: function (bot) { + return writeCode(bot, user, turns.concat(botResponse), botResponse); + } + } +]; + +const commandsMap = {}; +for (let command of commandsList) { + commandsMap[command.name] = command; +} + +export function getCommand(name) { + return commandsMap[name]; +} + +export function commandExists(name) { + return commandsMap[name] != undefined; +} + +export function getCommandDocs() { + let docs = `COMMAND DOCS\n***\n You can use the following commands followed by to query for information about the world. + Some are not implemented yet and will return null. Respond with only the command name to request information.\n`; + for (let command of commandsList) { + docs += command.name + ': ' + command.description + '\n'; + } + return docs + '\n***\n'; +} \ No newline at end of file diff --git a/utils/world.js b/utils/world.js index 0b7129a..b6c474f 100644 --- a/utils/world.js +++ b/utils/world.js @@ -179,5 +179,5 @@ export function getNearbyBlockTypes(bot) { found.push(blocks[i].name); } } - return found; + return Array.from(blockNames); }