Содержание
- Вступление
- Основы
- Продвинутым
- ЧаВо
Этот туториал поможет вам начать работать с Mineflayer, даже если вы ничего не знаете о программировании.
Если вы уже знаете что-то о Node и NPM, вы можете сразу переходить к разделу Создание бота.
Следующие разделы посвящены основным понятиям, которые вам необходимо знать, чтобы начать использовать Mineflayer.
В этом разделе вы научитесь основам Javascript, Node и NPM.
Javascript (сокращённо JS) - это язык программирования, созданный для Интернета. Это то, что делает возможным максимальный уровень взаимодействия в Интернете.
Node.js, часто просто Node, позволяет использовать Javascript вне веб-браузеров.
Для начала, вам нужно установить Node. Вы можете это сделать здесь.
После установки откройте командную строку (также известную как терминал) и затем введите node -v
Если вы всё сделали правильно, то вам напишет версию Node. Если вам написало о том, что команда не найдена, попробуйте установить ещё раз.
Теперь у вас есть Node, вы можете начать писать код, но вам нужно кое-что ещё.
Javascript был написан в примитивном текстовом редакторе, но легче использовать Интегрированную среду разработки(IDE)
IDE поможет вам в написании кода, потому что будет давать вам подсказки или указывать на ошибки в коде. Примером хорошей IDE является Visual Studio Code(VSCode)
После того как вы установили VSCode, создайте новый текстовый файл и сохраните его где-нибудь, а затем переименуйте его так, чтобы в конце была приписка .js
. Например: bot.js
Это сообщит VSCode о том, что вы работаете с Javascript, чтобы программа выдавала правильные подсказки.
Начните с этого:
const test = 5
Это создаст переменную с названием test
и выдаст ей значение 5
Переменные используются для хранения данных и использования их в коде.
Сохраните файл, теперь вы можете запустить этот код. Откройте терминал (или новый терминал в VSCode), затем выберите папку с вашим файлом. Для этого можно использовать команду cd
. Например: cd Documents\javascript
Теперь ваш терминал находится в той же папке, где и ваш файл, вы можете запустить его с помощью node filename.js
Если вы всё сделали правильно, то вы ничего не будете видеть.
В следующей главе мы покажем вам, как вы можете выводить данные в терминале.
В общем, использование const
вместо let
является нормальным при определении переменной. Переменная, определённая с помощью const
не может быть изменена, так как является константой.
Javascript сможет заставить ваш код работать более эффективно, потому что он знает, что ему не нужно учитывать изменения значения этой переменной.
Если вы хотите изменяемую переменную, вы можете использовать let
.
const test = 5
// eslint-disable-next-line
test = 10 // Эта строчка неправильная
Вторая строчка неправильная, так как вы не можете перезаписать переменную test
.
Если вы хотите помочь себе и другим людям в понимании вашего кода, то вы можете использовать комментарии.
Чтобы написать комментарий вам нужно использовать //
, всё после этого будет игнорироваться Javascript'ом.
Довольно часто для того чтобы убедиться, что ваша программа работает правильно, вам нужно выводить значения переменных.
Вы можете сделать это отображая переменные в терминале.
В Javascript вы можете это сделать с помощью функции console.log()
.
const test = 5
console.log(test)
Теперь когда вы сохраните и запустите этот код, то наконец увидите:
5
Далее вы узнаете о функциях. Функции - это часть кода, которая может быть использована несколько раз в вашем коде. Это может быть полезно, потому что вам не нужно будет писать что-либо много раз.
const addition = (a, b) => {
return a + b
}
const test1 = addition(5, 10)
const test2 = addition(1, 0)
console.log(test1)
console.log(test2)
=>
используется для определения функции, и называется стрелочным оператором.
Перед стрелочным оператором находится список параметров, всё, что находится в круглых скобках ()
- это параметры, разделённые запятыми.
Параметры - это переменные, которые вы можете передать вашей функции, чтобы функция могла с ними работать.
Затем после оператора идёт тело функции, это всё, что находится в фигурных скобках {}
Это то место, где вы можете поместить свой код функции.
Теперь, когда функция готова, вы присваиваем её к переменной, чтобы дать имя. В нашем случае - addition
Как вы можете видеть, код берёт в качестве параметров переменные a
и b
, а затем складывает их.
Затем функция возвращает результат.
Когда функция определена, код в теле функции не выполняется. Чтобы запустить функцию вам нужно вызвать её.
Вы можете вызвать функцию, используя её имя, за которыми идут круглые скобки. В нашем случае - addition()
Однако для функции addition
требуется 2 параметра. Их можно передать, добавив их в круглые скобки через запятую. В нашем случае - addition(1, 2)
Когда функция готова, вы можете Wпредставить, что вызов функции заменяется тем, что функция вернула. Таким образом, в этом случае let test1 = addition(5, 10)
станет let test1 = result
(На самом вы этого не увидите, но это может помочь вам понять концепцию).
Иногда вы столкнётесь со следующим: function addition() {}
Это означает то же самое, но предпочтительнее использовать () => {}
. (Если вы действительно хотите знать почему, загуглите 'javascript function vs arrow function')
Приведённый код выше должен вывести следующее:
15
1
До этого мы работали только с числами, но Javascript имеет множество других типов данных:
- Строка - это текст, который содержит множество символов. Строки объявляются с помощью
''
const string = 'This is a string' // string type
- Массив - это тип, который может хранить несколько других переменных. Массивы объявляются с помощью
[]
const array = [1, 2, 3] // array type
- Объекты - это обычно продвинутые массивы, позже вы узнаете больше об этом типе в туториале. Они объявляются с помощью
{}
const object = {} // object type
- У функций есть свой собственный тип
const adder = (a, b) => { return a + b } // function type
- Логический тип может быть
true
илиfalse
const boolean = true // boolean type
- Когда что-либо ещё не объявлено, оно имеет тип
undefined
let nothing // undefined type
const notDefined = undefined // undefined type
Иногда вам придётся делать разные вещи, основываясь на определенном условии.
Это можно реализовать с помощью условных конструкций.
const name = 'Боб'
if (name === 'Боб') {
console.log('Меня зовут Боб')
} else if (name === 'Алиса') {
console.log('Меня зовут Алиса')
} else {
console.log('Меня не зовут Боб или Алиса')
}
Условные конструкции создаются с помощью if
. После этого идёт условие с круглых скобках ()
, код находится в фигурных скобках {}
В условии должно быть что-то, что возвращает логический тип данных.
В нашем случае используется ===
, которое возвращает true
, если значение значение слева равняется значению справа. Иначе будет false
Если значение равно true
, то код, соответствующий этому условию будет выполнен.
Вы можете продолжать цепочку условных конструкций используя else if
и else
.
Вы можете иметь столько условных конструкций с else if
, сколько вы захотите, но можно использовать только только 1 if
и else
.
Если у вас присутствует else
, то он будет вызываться только тогда, когда все остальные условия вернули false
Циклы используются для повторения определенного кода до тех пор, пока не будет выполнено определенное условие.
let countDown = 5
while (countDown > 0) {
console.log(countDown)
countDown = countDown - 1 // Понижаем значение countDown на 1
}
console.log('Конец!')
Код выше будет выводить следующее:
5
4
3
2
1
Конец!
Цикл while
имеет условие ()
и тело {}
Когда код доходит до цикла, он проверяет условие. Если условие равно true
, то код в теле циклы будет выполнен.
Когда код в теле выполнен, условие проверяется ещё раз, и если оно равно true
, код выполняется заново.
Это будет происходить до тех пор, пока условие равно true
Каждый цикл код выводит число countDown
, а затем отнимает от него 1.
После 5 срабатывания, когда условие равно 0 > 0
, будет false
, и тогда код будет продолжаться дальше.
Цикл for
также часто используется и немного отличается от while
.
for (let countDown = 5; countDown > 0; countDown = countDown - 1) {
console.log(countDown)
}
Вместо одного условия, цикл содержит 3 разных части.
Эти части разделены точкой с запятой.
Первая часть - let countDown = 5
, срабатывает только 1 раз, при запуске цикла.
Вторая часть - countDown > 0
, условие, которое одинаково при каждом срабатывании цикла.
Третья часть - countDown = countDown - 1
, срабатывает при каждом срабатывании цикла.
Если вы хотите что-то сделать с каждым элементом массива, вы можете использовать цикл for of
.
const array = [1, 2, 3]
for (const item of array) {
console.log(item)
}
Цикл for of
требует переменную перед of
, это требуется для доступа к каждому элементу этой переменной.
Переменная после of
нужна, чтобы хранить переменную. В основном это массивы, но также могут быть объектами.
Цикл будет выполняться для каждого элемента в array
, и каждый раз переменная item
будет являться элементом array
.
Теперь вы узнаете как пользоваться Node Package Manager(NPM).
NPM автоматически устанавливается, когда вы устанавливаете Node.
NPM используется для получения библиотек, которые другие люди создали для удобства.
Вы можете посмотреть библиотеки на сайте и затем установить их, используя команду npm install
в вашем терминале.
Например, чтобы скачать библиотеку Mineflayer, вам нужно прописать npm install mineflayer
Теперь Node может получить доступ к установленной библиотеке с помощью функции require()
.
const mineflayer = require('mineflayer')
После этого будет доступна переменная mineflayer
, представляющая все функции Mineflayer.
Теперь, когда вы знаете основы Javascript, Node и NPM, вы готовы к созданию вашего первого бота!
Если вы не знаете слов выше, то вернитесь к предыдущему
Снизу представлены начальные действия для создания бота.
const mineflayer = require('mineflayer')
const bot = mineflayer.createBot()
Если вы запустите этот код, вы заметите, что программа не останавливатся. Если вы хотите остановить работающую программу, нажмите Ctrl
+ c
Однако этот бот не совсем полезен, так как по умолчанию он подключается к серверу Minecraft, работающему на вашем компьютере, с портом 25565.
Если вы хотите выбрать сервер, на который будет заходить бот, вам нужно прописать некоторые настройки.
const mineflayer = require('mineflayer')
const options = {
host: 'localhost', // Измените это на айпи сервера, который вам нужен.
port: 25565 // Измените это на порт сервера, который вам нужен.
}
const bot = mineflayer.createBot(options)
Фигурные скобки {}
используются для созданий объектов.
Объекты содержат значения в виде пар ключ-значение
Эти пары разделены с помощью :
, где ключ перед двоеточием, а значение после двоеточия.
Ключи можно использовать для получения их значения.
Вы можете иметь несколько таких пар, разделённых запятыми.
const object = {
number: 10,
another: 5
}
console.log(object.number) // Выведет число 10
Эта концепция часто используется для создания так называемых 'именованных параметров'
Преимущество этого заключается в том, что вам не нужно использовать все доступные опции, и их расположение не имеет значения.
Значением может быть что угодно, даже другой объект. Если значение является функцией, то эта функция часто вызывается методом для этого объекта.
Вы также можете создать объект одной строкой.
const bot = mineflayer.createBot({ host: 'localhost', port: 25565 })
Без каких либо параметров у бота будет ник Player
и он сможет подключаться только к пиратским серверам(или LAN-сервера).
Если вы дополните createBot
опцией username
, то бот будет использовать указанный вами ник. (Всё ещё для пиратских серверов)
Чтобы зайти на конкретный лицензионный аккаунт, вы должны использовать username
вместе с password
const bot = mineflayer.createBot({
host: 'localhost',
port: 25565,
username: 'Player',
password: 'password'
})
Что если кому-то понравится ваш бот и он захочет использовать его на другом сервере или с другим аккаунтом?
Это означает, что все смогут изменить айпи сервера и настройки входа как они захотят. (А также плохая идея передавать свой пароль)
Поэтому многие используют аргументы командной строки.
const bot = mineflayer.createBot({
host: process.argv[2],
port: parseInt(process.argv[3]),
username: process.argv[4],
password: process.argv[5]
})
Как вы видите, теперь ваши данные не используются в коде! Но как его запустить?
Теперь вместо того, чтобы запускать код через node filename.js
, вы должны запускать его с помощью node filename.js host port username password
Node автоматически разделит агрументы через пробел в массив.
Этот массив - process.argv
Данные можно получить с помощью индексов. Индексы всегда начинаются с 0, поэтому первый аргумент с номером [0]
будет со значением node
и т.д.
Первый аргумент | Второй аргумент | Третий аргумент | Четвёртый аргумент | Пятый аргумент | Шестой аргумент | |
---|---|---|---|---|---|---|
Значение | node |
filename.js |
host |
port |
username |
password |
Индекс | [0] |
[1] |
[2] |
[3] |
[4] |
[5] |
Передаваться в качестве аргумента могут не только основные переменные, но и функции. Функции передаются точно так же.
const welcome = () => {
bot.chat('Привет!')
}
bot.once('spawn', welcome)
Как вы можете видеть, метод bot.once()
имеет 2 параметра.
Первый параметр - название события, второй - функция, которая вызывается, когда срабатывает событие.
Запомните, когда передаёте функцию в качестве аргумента, используйте только имя функции, без ()
bot.chat()
- это метод отправки сообщений в чат.
Вы можете упростить код, используя анонимные функции.
У анонимных функций нет названий, они создаются на месте имени функции.
Они так же могут иметь параметры в ()
и тело функции в {}
, даже если они не используются.
bot.once('spawn', () => {
bot.chat('Привет!')
})
Объект бота имеет множество полезных событий.
Вы можете прослушивать события используя методы bot.on()
или bot.once()
для объекта бота, они принимают имя события и функцию.
Чтобы удалить какой-либо прослушиватель событий, используйте метод bot.removeListener()
.
bot.on(eventName, listener)
Вызывает функциюlistener
каждый раз, когда срабатывает событиеeventName
.bot.once(eventName, listener)
Вызывает функциюlistener
только один раз, когда впервые срабатывает событиеeventName
.bot.removeListener(eventName, listener)
Удаляетlistener
для событияeventName
. Чтобы это использовать, вам нужно либо определить вашу функцию с помощьюfunction myNamedFunc() {}
, либо поместить вашу функцию в переменную с помощьюconst myNamedFunc = () => {}
. Затем вы можете использоватьmyNamedFunc
в аргументе слушателя.
События имеет не только объект бота, например у Сундуков
, Печек
, Раздатчиков
, Столов зачарования
, Жителей
также есть свои события.
Промисы - это функции, которые вы можете использовать с помощью переменной await
для ожидания, пока какая-либо функция не завершится (вы также можете прервать await, чтобы не ожидать результата).
async function consume (bot) {
try {
await bot.consume()
console.log('Съел')
} catch (err) {
console.log(error)
}
}
Код выше попытается употребить то, что сейчас бот держит в руке.
Когда употребление заканчивается, вызывается переданная функция.
После этого вы сможете делать любые другие вещи.
Функция также может быть вызвана при возникновении ошибки.
Снизу пример бота, который создаёт дубовые доски, а затем палки.
Неправильно ❌:
function craft (bot) {
const mcData = require('minecraft-data')(bot.version)
const plankRecipe = bot.recipesFor(mcData.itemsByName.oak_planks.id ?? mcData.itemsByName.planks.id)[0] // Получение рецепта для дубовых досок
bot.craft(plankRecipe, 1) // ❌ Начинает создавать дубовые доски
const stickRecipe = bot.recipesFor(mcData.itemsByName.sticks.id)[0] // Получение рецепта для палок
bot.craft(stickRecipe, 1) // ❌ Начинает создавать палки
}
Правильно с промисами ✔️:
async function craft (bot) {
const mcData = require('minecraft-data')(bot.version)
const plankRecipe = bot.recipesFor(mcData.itemsByName.oak_planks.id ?? mcData.itemsByName.planks.id)[0]
await bot.craft(plankRecipe, 1, null)
const stickRecipe = bot.recipesFor(mcData.itemsByName.sticks.id)[0]
await bot.craft(stickRecipe, 1, null)
bot.chat('Скрафтил палки')
}
Причина почему первый код неправильный в том, что когда вызывается bot.craft()
, код продолжает что-то делать, пока бот крафтит.
К тому времени как код уже выполняет второй bot.craft()
, первый ещё возможно даже не закончился, а значит ресурсов для палок ещё нет.
Использование промисов может исправить это, потому что будет известно, когда закончится выполнение bot.craft()
.
Больше о методе bot.craft()
здесь.
Следующие концепции необязательны для создания бота на Mineflayer, но могут быть полезны для понимая и создания усовершенствованных ботов.
Мы предполагаем, что вы поняли Основы.
Цикл for of
описанный в разделе о циклах также может использоваться и для объектов.
Если у нас есть следующий объект:
const obj = {
a: 1,
b: 2,
c: 3
}
Мы можем создать цикл, перебирающий все значения объекта.
for (const value of Object.values(obj)) {
console.log(value)
}
1
2
3
Это цикл, перебирающий все ключи объекта.
for (const key of Object.keys(obj)) {
console.log(key)
}
a
b
c
Вы также можете одновременно использовать ключи и значения одновременно. Сначала вам придется деструктурировать переменные, объяснение вы можете найти здесь.
for (const [key, value] of Object.entries(obj)) {
console.log(key + ', ' + value)
}
a, 1
b, 2
c, 3
Эти циклы возможны благодаря Object.values(obj)
и Object.keys(obj)
, который возвращают массивы с значениями и ключами объектов соотвественно.
Object.entries(obj)
возвращает массив, состоящий из двух элементов: ключа и его значения.
Важно знать, что в отличии от функций Object.values()
и Object.keys()
, функция Object.entries()
порядок элементов останется таким же, каким он был в объекте.
Также существует цикл for in
. Однако, вам чаще придётся использовать for of
вместо for in
, потому что есть различия в ключах.
Цикл for in
работает на основе ключей вместо значений. (Индекс в этом случае, если это массив)
Однако он зацикливается не только на своих собственных ключах, но и на ключах из другого объекта, от которого он "наследуется", что нежелательно и может сбивать с толку. Подробнее об этом здесь.
В общем, вам понадобится for of
вместо for in
, поэтому убедитесь, что вы не путаете эти два понятия.
Вы можете создать свои собственные события для чата, используя метод bot.chatAddPattern()
. Полезно для серверов с плагинами, который меняют формат чата на сервере.
Метод bot.chatAddPattern()
принимает три аргумента :
pattern
- Регулярное выражение для совпадения с сообщением.chatType
- Вид сообщения. Является названием события, который будет срабатывать при совпадении с шаблоном. Например: "chat" или "whisper".description
- Необязательно, описание шаблона.
Вы можете добавить группы в pattern
, чтобы затем слушатель последовательно распределил группы по аргументам вашего обратного вызова.
Ознакомиться с регулярными выражениями вы можете здесь.
Примеры :
Здесь мы создаём бота, который отвечает на 'привет' другого игрока.
bot.chatAddPattern(
/(прив|привет|Привет)/,
'hello',
'Кто-то приветствуется'
)
const hi = () => {
bot.chat('Здарова!')
}
bot.on('hello', hi)
Создание события основанного на изменённом формате сообщений.
Пример:
[Игрок] Player1 > Привет
[Админ] Alex > прив
[Игрок] Player2 > Помогите, я застрял
[Модератор] Jim > Сейчас
bot.chatAddPattern(
/^\[(.+)\] (\S+) > (.+)$/,
'my_chat_event',
'Собственное событие чата'
)
const logger = (rank, username, message) => {
console.log(`${username} сказал ${message}`)
}
bot.on('my_chat_event', logger)
Объяснение этого ^\[(.+)\] (\S+) > (.+)$
вы можете найти здесь.
Вы можете запускать ботов на Android при помощи Termux.
Установите Termux и запустите его.
Установите Node.js
:
pkg update -y
pkg install nodejs -y
❗️ Выдайте Termux права на доступ к файлам в настройках приложения. Создайте папку во внутреннем хранилище :
cd /sdcard
mkdir my_scripts
cd my_scripts
Установите mineflayer
:
npm install mineflayer
Теперь вы можете скопировать и хранить все свои скрипты в папке my_scripts
во внутреннем хранилище.
Чтобы запустить бота, запустите Node с именем вашего скрипта.
node script_name.js
❗️ Каждый раз, когда вы открываете Termux, вы должны изменять директорию на /sdcard/my_scripts
, перед тем как запускать бота:
cd /sdcard/my_scripts