Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const mineflayer = require('mineflayer');
- const { pathfinder, Movements, goals } = require('mineflayer-pathfinder')
- const GoalFollow = goals.GoalFollow
- const { OpenAI } = require('openai'); // Убедись, что правильно импортируешь
- const Vec3 = require('vec3');
- const bot = mineflayer.createBot({
- host: 'localhost',
- port: 54546,
- username: 'GPTChel',
- auth: 'offline',
- });
- bot.loadPlugin(pathfinder)
- const client = new OpenAI({
- apiKey: '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', // Заменить на свой ключ
- });
- let playerIntervals = {};
- let interval; // Объявляем переменную interval в глобальной области видимости
- let lastMinedHeight = null; // Глобальная переменная для хранения высоты последнего добытого блока
- let history = [{ role: 'system', content: 'Вы бот задача которого играть в игру майнкрафт на разных серверах. Вас зовут GPTChel. Вы не должны отвечать на сообщения адресованные не вам. Вы написаны на mineflayer и javascript.' }];
- let functions = [
- {
- "name": "chat",
- "description": "Выводит в игровой чат сообщение от вашего имени.",
- "parameters": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "description": "Сообщение."
- }
- },
- "required": ["message"]
- }
- },
- {
- "name": "forward",
- "description": "Заставляет вашего персонажа идти вперед до того момента как вы используете функцию stop.",
- "parameters": {
- "type": "object",
- "properties": {},
- }
- },
- {
- "name": "stop",
- "description": "Заставляет вашего персонажа остановится до того момента как вы используете функцию forward. Желательно использовать после CollectBlock",
- "parameters": {
- "type": "object",
- "properties": {},
- }
- },
- {
- "name": "toplayer",
- "description": "Заставляет вашего персонажа идти к игроку до того момента как расстояние между игроком и персонажем будет меньше или равно 2 блокам после чего персонаж остановится, по этому вы должны отправить функцию toplayer лишь раз.",
- "parameters": {
- "type": "object",
- "properties": {
- "user": {
- "type": "string",
- "description": "Имя игрока."
- }
- },
- "required": ["user"]
- }
- },
- {
- "name": "followplayer",
- "description": "Заставляет вашего персонажа следовать игроком до того момента как вы отправите функцию stop.",
- "parameters": {
- "type": "object",
- "properties": {
- "user": {
- "type": "string",
- "description": "Имя игрока."
- }
- },
- "required": ["user"]
- }
- },
- {
- "name": "none",
- "description": "Пустышка, ничего не делает но позволяет просто пропустить интерацию.",
- "parameters": {
- "type": "object",
- "properties": {},
- }
- },
- {
- "name": "collectblock",
- "description": "Позволяет собрать определенное количество определенного блока. ! Отправляйте новую функцию collectblock только после получения соообщения Вы успешно добыли блоки:... ЕСЛИ ПОСЛЕ collectblock ВЫ НЕ ДОЖИДАЯСЬ ОТВЕТА Вы успешно добыли блоки:... ВВЕДЕТЕ collectblock ТО БОТ НАЧНЕТ КОПАТЬ ЕГО ЗАНОГО И НИКОГДА НЕ ВЫКАПАЕТ БЛОК ! если нужно добыть деревесину пишите не wood а log",
- "parameters": {
- "type": "object",
- "properties": {
- "block": {
- "type": "string",
- "description": "Название блока. Писать по английски!"
- },
- "amount": {
- "type": "number",
- "description": "Количество."
- }
- },
- }
- },
- {
- "name": "giveplayer",
- "description": "Позволяет кинуть определенный блок в определенном количестве определенному игроку.",
- "parameters": {
- "type": "object",
- "properties": {
- "block": {
- "type": "string",
- "description": "Название блока. Писать по английски!"
- },
- "amount": {
- "type": "number",
- "description": "Количество."
- },
- "user": {
- "type": "string",
- "description": "Имя игрока."
- }
- },
- }
- },
- {
- "name": "coordinates",
- "description": "Позволяет вам узнать свои координаты в мире.",
- "parameters": {
- "type": "object",
- "properties": {},
- }
- },
- {
- "name": "placeblock",
- "description": "Позволяет заставить бота поставить определенный блок в определенные координаты x y z. ! обязательно перед использованием испольуйте coordinates",
- "parameters": {
- "type": "object",
- "properties": {
- "block": {
- "type": "string",
- "description": "Название блока. Писать по английски!"
- },
- "x": {
- "type": "number",
- "description": "Координата x"
- },
- "y": {
- "type": "number",
- "description": "Координата y."
- },
- "z": {
- "type": "number",
- "description": "Координата z."
- }
- },
- }
- },
- {
- "name": "craft",
- "description": "Позволяет скрафтить предмет ! убедитесь что у вас есть необходимые материалы в инвентаре.",
- "parameters": {
- "type": "object",
- "properties": {
- "item": {
- "type": "string",
- "description": "Название предмета. Писать по английски!"
- },
- "amount": {
- "type": "number",
- "description": "Количество предмета"
- },
- }
- },
- },
- {
- "name": "inventory",
- "description": "Позволяет посмотреть содержимое вашего инвентаря.",
- "parameters": {
- "type": "object",
- "properties": {}
- },
- },
- ];
- async function gpt () {
- try {
- const chatCompletion = await client.chat.completions.create({
- messages: history,
- functions: functions,
- function_call: 'auto',
- model: 'gpt-4o-mini', // Модель, которая точно существует
- });
- console.log("Ответ от GPT:", JSON.stringify(chatCompletion, null, 2)); // Логируем весь ответ от GPT
- handle_response(chatCompletion);
- } catch (e) {
- console.error(`Error: ${e}`);
- }
- }
- function chat (message) {
- bot.chat(message);
- }
- function forward () {
- bot.setControlState('forward', true)
- }
- function stop () {
- bot.setControlState('forward', false)
- bot.pathfinder.setGoal(null); // Останавливаем pathfinder
- clearInterval(interval); // Очищаем интервал
- history.push({ role: "system", content: "Вы остановились." });
- }
- function toplayer(user) {
- const playerCI = bot.players[user];
- if (!playerCI || !playerCI.entity) return;
- const mcData = require('minecraft-data')(bot.version);
- const movements = new Movements(bot, mcData);
- bot.pathfinder.setMovements(movements);
- const goal = new GoalFollow(playerCI.entity, 1);
- bot.pathfinder.setGoal(goal, true);
- // Проверка расстояния с помощью уникального идентификатора интервала
- if (playerIntervals[user]) {
- clearInterval(playerIntervals[user]); // Если уже есть интервал для этого игрока, очистим его
- }
- playerIntervals[user] = setInterval(() => {
- const distance = bot.entity.position.distanceTo(playerCI.entity.position);
- if (distance <= 2) {
- bot.pathfinder.setGoal(null); // Останавливаем pathfinder
- clearInterval(playerIntervals[user]); // Очищаем интервал для этого игрока
- delete playerIntervals[user]; // Удаляем интервал из памяти
- }
- }, 100); // Проверяем расстояние каждые 100 миллисекунд
- }
- async function safeGoto(x, y, z) {
- return new Promise((resolve, reject) => {
- const goal = new goals.GoalNear(x, y, z, 1);
- bot.pathfinder.setGoal(goal);
- // Проверяем, что цель достигнута
- const checkGoal = setInterval(() => {
- if (bot.pathfinder.goal === null) {
- clearInterval(checkGoal);
- resolve();
- }
- }, 100);
- // Если цель изменится, выходим с ошибкой
- bot.once('goal_reached', () => {
- clearInterval(checkGoal);
- resolve();
- });
- bot.once('goal_changed', () => {
- clearInterval(checkGoal);
- reject(new Error('Goal changed before completion'));
- });
- });
- }
- function findNearestBlock(blockName, radius, prioritizeSameHeight = false) {
- const mcData = require('minecraft-data')(bot.version);
- const blockType = mcData.blocksByName[blockName].id;
- // Сначала ищем блоки на той же высоте, что и предыдущий добытый блок
- if (prioritizeSameHeight && lastMinedHeight !== null) {
- const sameHeightBlocks = bot.findBlocks({
- matching: blockType,
- maxDistance: radius,
- count: 1,
- filter: block => block.y === lastMinedHeight // Ищем только на той же высоте
- });
- if (sameHeightBlocks.length > 0) {
- return bot.blockAt(sameHeightBlocks[0]);
- }
- }
- // Если не нашли на той же высоте, ищем любые другие блоки
- const blocks = bot.findBlocks({
- matching: blockType,
- maxDistance: radius,
- count: 1,
- });
- if (blocks.length === 0) return null;
- return bot.blockAt(blocks[0]);
- }
- async function mineBlocks(blockName, count) {
- for (let i = 0; i < count; i++) {
- const targetBlock = findNearestBlock(blockName, 5, true); // Передаем true для приоритета по высоте
- if (!targetBlock) {
- history.push({ role: "system", content: `Блок ${blockName} не найден в радиусе 5 блоков.` });
- break;
- }
- try {
- await safeGoto(targetBlock.position.x, targetBlock.position.y, targetBlock.position.z);
- } catch (err) {
- console.error("Ошибка при установке цели:", err);
- continue; // Переход к следующему блоку при ошибке
- }
- // Обновляем высоту последнего добытого блока
- lastMinedHeight = targetBlock.position.y;
- // Добыча блока
- try {
- history.push({ role: "system", content: `Вы добываете блоки: ${blockName} на высоте ${lastMinedHeight}` });
- await bot.dig(targetBlock);
- history.push({ role: "system", content: `Вы успешно добыли блоки: ${blockName} на высоте ${lastMinedHeight}` });
- } catch (err) {
- console.log("Ошибка при добыче блока:", err);
- break;
- }
- }
- }
- function coordinates () {
- const position = bot.entity.position;
- history.push({ role: "system", content: `Координаты бота: X: ${position.x}, Y: ${position.y}, Z: ${position.z}`});
- }
- async function placeblock(block, target_pos) {
- const mcData = require('minecraft-data')(bot.version);
- const movements = new Movements(bot, mcData);
- bot.pathfinder.setMovements(movements);
- // Проверяем, есть ли нужный блок в инвентаре
- const blockToPlace = bot.inventory.items().find(item => item.name === block);
- if (!blockToPlace) {
- console.log(`Блок ${block} не найден в инвентаре!`);
- return;
- }
- console.log(`Готовимся поставить блок: ${blockToPlace.displayName}`);
- // Проверка целевой позиции
- console.log(`Целевая позиция для установки блока: X: ${target_pos.x}, Y: ${target_pos.y}, Z: ${target_pos.z}`);
- // Проверяем блок под целевой позицией
- const referenceBlock = bot.blockAt(target_pos.offset(0, -1, 0)); // Получаем блок под целевой позицией
- if (!referenceBlock) {
- console.log('Нет блока под целевой позицией!');
- return;
- }
- // Логируем блок, который будет использоваться для установки
- console.log('Устанавливаем блок на: ', referenceBlock);
- // Подготовка к установке
- try {
- await bot.equip(blockToPlace, 'hand');
- await bot.placeBlock(referenceBlock, new Vec3(0, 1, 0)); // Размещение блока
- console.log('Блок успешно установлен!');
- } catch (err) {
- console.error('Ошибка при установке блока:', err);
- }
- }
- function followplayer (user) {
- const playerCI = bot.players[user]
- if (!playerCI || !playerCI.entity) return;
- const mcData = require('minecraft-data')(bot.version)
- const movements = new Movements(bot, mcData)
- bot.pathfinder.setMovements(movements)
- const goal = new GoalFollow(playerCI.entity, 1)
- bot.pathfinder.setGoal(goal, true)
- }
- async function giveplayer (block, amount, user) {
- const playerCI = bot.players[user];
- if (!playerCI || !playerCI.entity) return;
- await toplayer(user)
- setTimeout(function() {}, 6000); // 1000 миллисекунд = 1 секунда
- // Координаты игрока
- const targetPos = playerCI.entity.position.offset(0, 1.6, 0); // Смотреть на уровень головы
- try {
- // Повернуться к игроку
- await bot.lookAt(targetPos, true);
- // Проверяем инвентарь и выводим его содержимое
- console.log("Текущий инвентарь:", bot.inventory.items());
- const mcData = require('minecraft-data')(bot.version);
- const itemType = mcData.itemsByName[block]?.id; // Используем ID предмета
- const item = bot.inventory.items().find(i => i.type === itemType);
- if (!item) {
- console.log(`У вас нет предмета ${block}.`);
- history.push({ role: "system", content: `У вас нет предмета ${block}.` });
- return;
- }
- if (amount > item.count) {
- console.log(`Недостаточно ${block}. Доступно: ${item.count}`);
- history.push({ role: "system", content: `Недостаточно ${block}. Доступно: ${item.count}` });
- return;
- }
- // Бросаем предмет
- await bot.toss(item.type, null, amount);
- console.log(`GPTChel кинул ${amount} ${block} игроку ${user}`);
- history.push({ role: "system", content: `Вы кинули игроку ${user} блок ${block} в количестве ${amount}` });
- } catch (err) {
- console.log(`Ошибка при передаче предмета: ${err.message}`);
- }
- }
- function craft(recipeName, count) {
- const recipes = bot.recipesFor(recipeName); // Получаем рецепт
- console.log("Найденные рецепты для крафта:", recipes);
- if (recipes.length === 0) {
- history.push({ role: "system", content: 'Рецепт не найден!' });
- console.log("Рецепт не найден!");
- return;
- }
- const recipe = recipes[0]; // Получаем первый рецепт
- console.log("Требуемые ингредиенты рецепта:", recipe.ingredients);
- // Проверка, что у бота есть все необходимые материалы
- const materialsAvailable = Array.isArray(recipe.ingredients) && recipe.ingredients.every(ingredient => {
- const inventoryItem = bot.inventory.items().find(item => item.name === ingredient.name);
- return inventoryItem && inventoryItem.count >= ingredient.count;
- });
- if (!materialsAvailable) {
- console.log(bot.inventory.items());
- console.log('У бота недостаточно материалов для крафта.');
- history.push({ role: "system", content: 'У бота недостаточно материалов для крафта.' });
- return;
- }
- // Открытие крафтового меню (внутреннего окна бота)
- bot.openCraftingTable((err, craftingTable) => {
- if (err) {
- console.log("Ошибка при открытии крафтового меню:", err);
- return;
- }
- console.log("Крафтовое меню открыто.");
- // Заполнение крафтовой сетки (4 слота)
- const grid = craftingTable.slots.slice(0, 4); // Получаем первые 4 слота для ингредиентов
- recipe.ingredients.forEach((ingredient, index) => {
- const inventoryItem = bot.inventory.items().find(item => item.name === ingredient.name);
- if (inventoryItem) {
- bot.putInSlot(grid[index], inventoryItem, (err) => {
- if (err) {
- console.log("Ошибка при размещении ингредиента в сетке:", err);
- }
- });
- }
- });
- // Запуск крафта
- craftingTable.craft(recipe, count, (err) => {
- if (err) {
- console.log("Ошибка при крафте:", err);
- history.push({ role: "system", content: 'Ошибка при крафте!' });
- } else {
- console.log("Крафт завершён успешно.");
- history.push({ role: "system", content: 'Крафт завершён успешно.' });
- }
- });
- });
- }
- function inventory () {
- // Получаем инвентарь
- const inventory = bot.inventory;
- // Проходим по всем слотам инвентаря
- inventory.slots.forEach((item, index) => {
- if (item) {
- history.push({ role: "system", content: `Слот ${index}: ${item.name}, Количество: ${item.count}`});
- }
- })
- }
- async function handle_response(response) {
- if (response.choices[0].message.function_call) {
- const function_name = response.choices[0].message.function_call.name;
- if (function_name === 'chat') {
- const function_call = response.choices[0].message.function_call;
- try {
- const arguments = JSON.parse(function_call.arguments);
- const message = arguments.message;
- chat(message);
- history.push({ role: "system", content: "Вы отправили сообщение: " + message });
- console.log("GPTChel отправил сообщение: " + message)
- } catch (err) {
- console.error('Ошибка при разборе аргументов функции: ', err);
- }
- }
- else if (function_name === 'forward') {
- forward()
- }
- else if (function_name === 'stop') {
- stop()
- }
- else if (function_name === 'coordinates') {
- coordinates()
- }
- else if (function_name === 'toplayer') {
- const function_call = response.choices[0].message.function_call;
- try {
- const arguments = JSON.parse(function_call.arguments);
- const user = arguments.user;
- toplayer(user);
- history.push({ role: "system", content: "Вы идете к игроку: " + user });
- console.log("GPTChel идет к: " + user)
- } catch (err) {
- console.error('Ошибка при разборе аргументов функции: ', err);
- }
- }
- else if (function_name === 'followplayer') {
- const function_call = response.choices[0].message.function_call;
- try {
- const arguments = JSON.parse(function_call.arguments);
- const user = arguments.user;
- followplayer(user);
- history.push({ role: "system", content: "Вы следуете за игроком: " + user });
- console.log("GPTChel следует за: " + user)
- } catch (err) {
- console.error('Ошибка при разборе аргументов функции: ', err);
- }
- }
- else if (function_name === 'collectblock') {
- const function_call = response.choices[0].message.function_call;
- try {
- const arguments = JSON.parse(function_call.arguments);
- const block = arguments.block;
- const amount = arguments.amount;
- await mineBlocks(block, amount);
- console.log("GPTChel добывает: " + block)
- } catch (err) {
- console.error('Ошибка при разборе аргументов функции: ', err);
- }
- }
- else if (function_name === 'giveplayer') {
- const function_call = response.choices[0].message.function_call;
- try {
- const arguments = JSON.parse(function_call.arguments);
- const block = arguments.block;
- const amount = arguments.amount;
- const user = arguments.user;
- giveplayer(block, amount, user);
- history.push({ role: "system", content: `Вы кинули игроку ${user} блок ${block} в количестве ${amount}`});
- console.log("GPTChel выкидывает: " + block)
- } catch (err) {
- console.error('Ошибка при разборе аргументов функции: ', err);
- }
- }
- else if (function_name === 'placeblock') {
- const function_call = response.choices[0].message.function_call;
- try {
- const arguments = JSON.parse(function_call.arguments);
- const block = arguments.block;
- const x = arguments.x;
- const y = arguments.y;
- const z = arguments.z;
- target_pos = new Vec3(x, y, z);
- placeblock(block, target_pos);
- history.push({ role: "system", content: `Вы поставили блок ${block}.`});
- console.log("GPTChel ставит: " + block)
- } catch (err) {
- console.error('Ошибка при разборе аргументов функции: ', err);
- }
- }
- else if (function_name === 'inventory') {
- inventory()
- }
- else if (function_name === 'craft') {
- const function_call = response.choices[0].message.function_call;
- try {
- const arguments = JSON.parse(function_call.arguments);
- const item = arguments.item;
- console.log(item)
- const amount = arguments.amount;
- console.log(amount)
- craft(item, amount);
- console.log("GPTChel крафтит: " + item)
- } catch (err) {
- console.error('Ошибка при разборе аргументов функции: ', err);
- }
- }
- }
- else {
- }
- }
- // Функция для постоянных обращений к GPT с задержкой в 1 секунду
- async function continuousGPT() {
- while (true) {
- await gpt(); // Ждем завершения вызова
- await new Promise(resolve => setTimeout(resolve, 2000)); // Задержка в 2 секунду
- }
- }
- bot.on('spawn', () => {
- console.log('Бот запущен!');
- continuousGPT(); // Запускаем постоянные обращения к GPT
- });
- bot.on('error', (err) => {
- console.log('Ошибка подключения:', err);
- });
- bot.on('end', () => {
- console.log('Бот отключен.');
- });
- bot.on('login', () => {
- console.log('Бот успешно вошел в игру!');
- });
- bot.on('chat', (user, message) => {
- if (user != 'GPTChel') {
- history.push({ role: "system", content: `В игровой чат было отправлено сообщение от ${user}: ${message}` });
- console.log("Получено сообщение: " + message)
- }
- });
Add Comment
Please, Sign In to add comment