[Скрипты] CustomNPC скрипты «События и методы для начинающих» №1/3
Приветствую, уважаемый читатель. Я скриптер в команде CremanMaps.
Сегодня я хотел бы рассказать немного о custom npc скриптах. Эта статья не для абсолютных новичков и я не буду рассказывать что такое nashorn и настройщик нпс. Однако, я буду пояснять некоторые моменты и приводить простые примеры. В этом цикле статей мы разберём как сделать действия после нажатия определённой кнопки, рассмотрим получение различных сущностей на определённом расстоянии от игрока, затронем хранение информации в storeddata, изучим команды tellraw и title, сделаем реакцию нпс на сообщения в чате. Не будем тянуть и приступим
Warning: Скрипты о которых я буду рассказывать могут иметь ошибки если их использовать для сетевой игрыЧто нам понадобится
Я рекомендую установить следующие модификации для minecraft
(Обязательно)
1.CustomNPCs_1.12.2-29Nov20snapshot
(для реализации нескольких примеров)
2.Mclib
(Так же мы будем использовать несколько сайтов)
2.Вспомогательный сайт для tellraw
4.Unicode
Вы можете писать скрипты непосредственно в Minecraft, но я рекомендую вам писать их в IDE(Интегрированная среда разработки), я пользуюсь microsoft visual studio code, которую можно скачать бесплатно, но вы можете писать скрипты хоть в блокноте.
Tipe: Храните свои скрипты за пределами майнкрафта в текстовых файлах. Редакторы кода могут так же облегчить написание скрипта, из-за подсказок во время ввода переменных или объявленных ранее функций.Часть 1
Событие нажатия кнопки
Начнём. Откройте документацию. Вы, конечно открываете РУССКУЮ документацию! Открыли? Молодцы, закрывайте, очищайте историю браузера и молчите об этом до конца жизни. Теперь серьёзно: Русская документация по сути не имеет никаких преимуществ. Название всех классов, методов можно перевести в гугл переводчике, если что. Официальная документация имеет ряд преимуществ: Лёгкий доступ к пакетам и классам, все названия при нажатии открывают полезные окна. Кроме этого, вы сможете сразу сможете понять какие классы или значения возвращает, принимает функция! У вас остались возражения? Нет, тогда идём дальше. Документация очень важна, но неподготовленному читателю может показаться солоноватой. Поэтому, в этой статье мы уделим ей особое внимание. Откройте документацию.
В верхнем левом углу вы увидите окно «packages». В нём представлены все доступные пакеты. Если мы нажмём на нужный, в окне classes появятся классы, которые находятся в этом пакете.
Сейчас нас интересует пакет с событиями. Это «noppes.npcs.api.event». Найти нужный вам пакет достаточно легко. Последние слова означают то что этот пакет содержит (Например: события — events, сущности — entity, предметы — items)
Нажали? Теперь нам необходимо выбрать нужный нам класс. Название классов в пакете событий обычно состоят из двух слов. 1 — то к чему событие относится, 2 — название самого события.
Действие нажатия кнопки совершает игрок, достаточно нажать на класс PlayerEvent и в основном окне появится список вложенных классов (полистайте и найдите его в рамке с классами). Путём гугл переводчика можно вычислить что существует класс PlayerEvent.KeyPressedEvent. Он нам и нужен.
В поле description копируем словосочетание keyPressed, оно используется для функции. Теперь можно открыть майнкрафт или текстовый редактор для кода.
Но сперва небольшое лирическое отступление. Давайте разберём что такое эти самые функции и как их объявлять.
1) Ключевое слово function говорит о том что это функция
2) Дальше идёт имя функции, то как эту функцию зовут (вызывают)
3) То что функция принимает, в основном необходимые функции переменные.
4) Фигурные скобки (тело фунции).
Если провести аналогию с человеком, то слово function — сам человек; Name — имя человека; () — то что этот человек принимает, например возраст, пол, расу;{} — тело с органами.
Что бы создать функцию которая проверяет нажатие кнопки мы должны вписать этот код.
function keyPressed(event){}
Это функция уже заготовлена noppes и является обработчиком событий. Поэтому важно написать название функции правильно. Слово event можно изменить, поскольку это просто название ссылки на событие.
Tipe: Использование документации — половина успеха.
Каждое событие имеет поля. К ним можно обращаться через «.» как в любом другом ООП(Объектное ориентированном программировании ). Для простоты это можно представить в виде пакета с пакетами. Представьте пакет в котором лежат все пакеты, в нём пакет для овощей, в нём пакет для огурцов, а в нём огурцы. В скрипте это выглядело бы так: пакетспакетами.пакетдляовощей.пакетдляогурцов.огурцы
Каждый event содержит интерфейс api, события связанные с игрокм — player, связанные с npc — npc и так далее. Кроме этого каждое событие может содержать индивидуальные поля. Поля — это вложенные в событие переменные. Можно сказать и событие хранит их в себе.
У разных классов есть свои методы. Методы — это функции, которыми мы можем взаимодействовать с классами. Давайте попробуем найти все методы для НПС. НПС это существо и находиться в пакете существ (noppes.npcs.api.entity). Если бы мы брали событие связанное с НПС, то ссылка на него содержалась бы в полях и мы получили бы его через e.npc;
Среди доступных классов понимаем что ICustomNpc имеет к НПС какое-то смутное отношение. Если Метод начинается со слова get и имеет пустые скобки, значит он берёт значение переменной. Например здоровье, координаты, или ссылки на подинтерфейсы. Если метод начинается со слова set, то он он устанавливает значение переменной на то, которое указано в скобках.
Кроме этого существуют Главные классы и Расширяющие. Если класс имеет их, они будут подписаны над его методами. Если сказать просто, то класс имеет все методы, которые имеют классы расширения и класс, по отношению к которому он является дочерним. Пример: Существует абстрактный класс люди, у него есть методы: Дышать, передвигаться. У этого класса не может быть переменной имени, поскольку это все люди. Создадим класс человек. У него уже может быть переменные имени, возраста, пола, расы. В нём уже могут быть методы: говорить, получить состояние здоровья и т.д. Но он человек, поэтому вне зависимости от того кто он, он всё равно должен иметь основные методы класса люди.
Давайте ещё раз. Класс игрока имеет те же методы что и класс сущности, так как игрок наследуется от сущности. Приведу пример. Допустим у нас есть Класс «человек» и класс «гопник». «Гопник» будет наследоваться от класса «Человек». Если у гопника будет метод getSemki(), то его нельзя будет вызвать у абстрактного человека, а в классе гопник можно будет вызвать метод eat(), который бы содержал класс человек. Например, класс НПС является дочерним по отношению к ентити, одновременно является главным для класса дисплей нпс. Для нпс будут работать методы энтити, а для энтити методы нпс — нет.
Это очень важно! Например (да, я ещё раз напишу это слово): Задача изменить нпс имя. Мы должные его изменить, значит нужна функция, которая начинается с set. Имя по английском — name. Этого достаточно, что бы воспользоваться поиском. (В скриптах вам нужно будет много всего искать, спрашивать советов, думать, находить баги и гениальность уровня noppes)
Вы узнаём что такой метод есть в классе INPCDisplay. Если мы просто пропишем e.npc.setName(»name») будет ошибка. Как я объяснял раннее INPCDisplay — дочерний класс. Что бы мы могли применить его методы, нам нужно получить на него ссылку. Заходим в класс нпс и листаем методы.
Слева от методов есть названия типов которые они возвращают. (Если функция ничего не возвращает — она называется void). Листаем и находи, что функция getDisplay() возвращает ссылку на этот класс. Пробуем. e.npc.getDisplay().setName(»Марк»)
Надеюсь с наследованием всё стало более-менее понятно.
Тренировка: Составьте с помощью документации путь от события PlayerEvent.InteractEvent до метода setBurning(int)
В скрипте может быть множество методов и каждый раз прописывать путь до них будет не рационально. Поэтому я советую использовать переменные хранящие ссылки на классы. Переменные объявляется так:
- ключевое слово var
- имя переменной
- оператор присвоения
- значение переменной
Например: var apple = 9
Давайте я приведу аналогию с жизнью и поясню что такое переменные. Представляйте переменную как коробку. В коробке могут лежать разные вещи, игрушки, конфеты, оружие. Что бы мы не потеряли коробку и знали что там, на коробках есть бирки с их именами. Так почему их назвали переменные? Могли бы так и назвать, box. Нет. Главная суть переменных это то что они — быть не может — умеют переменятся. Это их суть. Переменные могут содержать определённые вещи, а именно: целые числа, дробные (или как их называют: числа с плавающей точкой), истинность(true, false), null, слова (В кавычках!!!), ссылки на классы. Если мы зайдём в документацию, то увидим что событие содержит переменные:
isAltPressed - булевая переменная (нажат ли Альт)isCtrlPressed - булевая переменная (нажат ли Контрл)isMetaPressed - нажата ли кнопка на клавиатуре apple или windowsisShiftPressed - догадайся с трёх раз -_-key - кей код клавиши, можно узнать на сайтеfunction keyPressed(event){var player = event.player
var key = event.key
player.message("Hello world!")}
Функция message() находится в игроке, попробуй найти её. Если у тебя получилось то ты узнаешь что она принимает строку (string). Строки нужно вводить в кавычках! (Да, я ещё раз это напишу). Так же функция может принимать переменные, попробуйте создать переменную, которая хранит строку и в метод положить эту переменную.
function keyPressed(event){var player = event.player
var key = event.key
var message = "Я крутой"
player.message(message)
}
Вы можете добавлять к стоке значение переменной, ВАЖНО использовать +, а не запятую. Запятые используют если метод требует несколько переменных. Можно складывать друг с другом несколько строк, это называется «Конкатенация строк» (Выучил новое слово и сижу довольный)
function keyPressed(event){var player = event.player
var key = event.key
player.message("Код клавиши " + key)}
Красивый текст
Не кажется ли вам, что этого текста мало? Он слишком серый? Вы можете использовать специальные символы. Прямо в кавычках поставьте \ (обратная косая черта, не путать с / ) После этого символа идёт буква, вы можете посмотреть список здесь, в разделе текстовых операторов. Например если вы хотите использовать кавычки внутри кавычек, то вы должны поставить \»
Что бы добавить цвет, вы должны вставить знак параграфа и код цвета, которые можно посмотреть здесь. Красивый, радужный текст, всё просто, правда? Тогда добавим проверку, чтобы надпись появлялась при нажатии определённой кнопки. Для этого используется IF. Это условие. Краткость — сестра таланта. Условия бывают полные, неполные и больше (я их так называю). Сначала пишется ключевое слово if. После него в () пишется само логическое условие. После него в {} те действия, которые произойдут, если условие истинно. Это неполное условие. После фигурных скобок можно поставить ключевое слово else (иначе), после него в {} будут те действия, которые выполнятся, если условие не верно. Это полное условие. Если нам нужно несколько условий, можно использовать ключевое слово else if, это будет ещё одно условие.
if(условие){тело, если условие истинно}
else if(условие 2)
{тело, если условие истинно}else
{тело в любом случае, если предыдущее не верно}Что бы работать с условиями нужно знать операторы сравнения и логические, а именно <,>,>=,<=,==,!=,||,&&,!
>= — больше, или равно. == — проверка на равенство (если написать просто =, то это считается оператором присвоения и не походит для условий). != — это проверка на неравенство. || — это логическое сложение, истинно если хотя бы одно истинно. && — логическое умножение, истинно если оба истинны. ! отрицание, истинно когда условие не истинно.
var censorship = 18
var age = 15
if(censorship>age){player.message("Тебе такое смотреть нельзя")}
else if(censorship<=age){player.message("Тебе такое смотреть можно, извращенец")}
else{player.message("У тебя нет возраста, хд")}
Это простой пример. Приведём пример составного (сложного) условия
var isMan = true
var isFemale = false
if(isMan){ //Действие выполняется если условие верно, поскольку переменная истина, то действие выполнится, можно было бы записать как if(isMan==true){}player.message("Тобi повiстка")}
var apple = 5
var cookie = 10
if((apple>0)||(cookie>0)){ //Если хотя бы одно из выражений истинно, условие истинноplayer.message("Корзина не пуста")}
if((apple>0)&&(cookie>0)){ //только если оба условия истинныplayer.message("В корзине и яблоки и печенье")}
if(!apple>0){ // Яблок больше 0, если ложь, то будет истина из-за !//то есть !apple>0 будет тоже самое, что apple<0
player.message("Яблок нет")}
Важно, если if найдёт верное условие, он не будет проверять остальные!
var N = 5
if(N>0){player.message("Вы это увидели")}else if(N>1){player.message("Вы этого не увидите")}
Есть ключевое слово return. С помощью неё метод может что-то вернуть. Попробуем создать свой метод и вызвать его. Пользуясь знаниями о создании методов мы сможем его объявить. В скобках название переменной, которую будет получать метод. В теле метода можем прибавить к ней число и с помощью return вернуть эту переменную. Поскольку будет возвращаться число, мы можем отправить его игроку. Просто вызываем метод MyFunction(N) в методе message.
function keyPressed(event){var N = 5
event.player.message(N)
event.player.message(MyFunction(N))
}
function MyFunction(N){N+=100
return N
}
С помощью этой функции return вы можете прекратить выполнение кода, но не отменить события ( рассмотрим в следующей части). Вы могли догадаться, что такие функции, как getHealth() в классе энтити просто возвращает переменную. Вы могли бы обратиться к этой переменной напрямую (возможно не ко всем), но лучше этого не делать, правильнее использовать методы, надёжнее)
function getHealh(){return health
}
Вы можете дальше поиграться с условиями и проверить разные варианты, но мы идём дальше, давайте проверим, что нажатая кнопка это F. Из сайта узнаём что key code клавиши F — это 33. Проверяем.
function keyPressed(event){var player = event.player
var key = event.key
if(key!=33){return}player.damage(100)
}
Как говорится, press F.
Ну что ж, это первая часть моей статьи. Я надеюсь что вы узнали что-то новенькое, сейчас это может показаться скучным, но когда вы освоите основы перед вами откроются двери в дивный и прекрасный мир скриптов. В следующей части мы познакомимся с storeddata и научимся получать сущностей на расстоянии (спойлер: Мы сделаем нпс который будет грозить нам кулаком и говорить про нравы, если мы будем танцевать перед ним твёрк), не пропустите!
P.S: Об ошибках статьи пишите в комментарии, всегда рады игнорить людей, до встречи в будущем!
