JustMC Code Compiler - компилятор языка JustCode в структуру файлов кодинга, используемого на сервере JustMC
Для работы с JMCC нужно:
-
Открыть страницу релизов GitHub
-
Выбрать подходящий файл с компилятором для вашей операционной системы (-win для Windows, -linux для Linux) и установить его
-
Открыть командную строку в папке с установленным файлом:
- Win + R на Windows, затем вписать
cmd
в появивщееся окно - На Unix системах - открыть терминал
- Win + R на Windows, затем вписать
-
Использовать компилятор:
# Для Windows $ jmcc-win.exe compile example.jc # Для Linux $ ./jmcc-linux compile example.jc
Для просмотра помощи о командах, используйте команду help
Перед тем как использовать jmcc
, убедитесь что вы знаете синтаксис для создания программ.
Создайте файл с расширением .jc
и таким содержанием:
event<player_join> {
player::message("Привет!")
}
Скомпилируйте данный файл:
$ jmcc compile [имя файла].jc
Если компиляция была успешной, в папке с вашим файлом должен появиться новый файл, с таким же названием, но с расширением .json
. Чтобы использовать его на сервере, вам нужно загрузить его на файлообменник, либо использовать аргумент -u
:
$ jmcc compile -u [имя файла].jc
При его использовании, компилятор не будет создавать файлы компиляции на вашем компьютере, а сразу передавать их в облако. Если компиляция была успешной, у вас в терминале должна появиться ссылка, которую можно использовать на сервере напрямую.
Важно: Облачные ссылки, созданные при использовании аргумента -u
будут хранить код только 3 минуты. После этого времени они будут удаляться. Если вы хотите сохранить скомпилированный код на большее время, вам нужно будет сохранять его в сторонних файлообменниках.
"Текст!" // Текст
1 // Число
[1, 2] // Список
value::health // Игровое значение
// (об этом будет дальше)
item("stone") // Значения, созданные фабриками
// (об этом будет дальше)
Переменные можно использовать только после их определения. До определения такие переменные не будут доступны, и будут вызывать ошибку при их использовании. Так же, определять переменные можно только один раз.
Определение локальных переменных
var a = 1;
Определение игровых переменных
game var a = 1;
Определение сохранённых переменных
save var a = 1;
Встроенные (inline
) переменные — переменные, значение которых просчитывается при компиляции, и заменяется при каждом их использовании. Им нельзя присвоить динамические значения, типо результатов действий с переменных.
Определение встроенных переменных
inline var a = 1;
Переменные могут иметь имена, которые включают в себя селекторы либо строчные варианты значений. Так же, можно определить переменные с именем, состоящим из нестандартных символов, используя ``
. К примеру:
Использование селектора в имени
var %player%_переменная = 1;
Использование нестандартных символов в имени
var `странная переменная ⛏️` = 2;
Использование других значений в имени
var a = 1;
var `переменная $a` = 2;
// ^^^^^^^^^^^^^^^
// Данная переменная после компиляции будет
// иметь имя "переменная %var_local(a)"
// ...или со скобками:
var `переменная 2 ${a}` = 2;
// ^^^^^^^^^^^^^^^^^^^
// Данная переменная после компиляции будет
// иметь имя "переменная 2 %var_local(a)"
Использование встроенных переменных в имени
inline var a = 1 + 1; // <--- Эта переменная встроена!
var `переменная $a` = 2;
// ^^^^^^^^^^^^^^^
// Данная переменная после компиляции будет
// иметь имя "переменная 2"
В том случае, когда вы со 100% увереностью знаете, что переменная существует в выбранном контексте, но компилятор выдаёт вам ошибку неизвестной переменной, вы можете не определять переменной значения:
var a;
game var a;
В таком случае не будет создано действия "Установить переменную", но эта переменная может быть использована как обычно.
Inline переменные нельзя не определять. Они всегда должны иметь значение при создании.
Фабрики — функции, которые принимают аргументы и возвращают значение. Ими создаются предметы, зелья, локации и другие значения, которые можно определить в коде:
var a = location(1, 2, 3);
Математические функции - фабрики, которые аналогичны функциям из %math. Доступные функций:
abs(число)
- Абсолютное значение числаsqrt(число)
- Квадратные корень числаcbrt(число)
- Кубический корень числаceil(число)
- Округление числа до большего значенияfloor(число)
- Округление числа до меньшего значенияsin(число)
- Синус числаcos(число)
- Косинус числаround(число, N)
- Округление числа до N цифер после запятойpow(число, степень)
- Возведение числа в степеньmin(число, число)
- Минимальное из значенийmax(число, число)
- Максимальное из значений
Использование:
var a = floor(0.3) + abs(-3) + sqrt(2);
Вызов действий должен происходить от объекта или переменной.
Анатомия вызова:
player::message("Привет мир!")
^^^^^^
переменная или объект
player::message("Привет мир!")
^^
разделитель, определяющий тип вызова:
:: для объектов
. для переменных
player::message("Привет мир!")
^^^^^^^
имя функции
player::message("Привет мир!")
^^^^^^^^^^^^^
аргумент вызова
Аргументы вызова могут определяться:
-
позиционно
player::message("Привет мир!")
-
с именем
player::message(text = "Привет мир!")
-
комбинированно
player::message("Привет мир!", merging = "SPACES")
При вызове действий компилятор проверяет соответствие типов значений, переданных действию. При этом, переменные не проверяются на соответствие (так как могут изменить своё значение).
К примеру, если действие принимает в качестве аргумента только число, то и вызвать его можно только с числом либо переменной:
var a = 1;
a.increment('Не число!');
// ^^^^^^^^^^^
// Ошибка: Аргумент с типом текст не может быть
// установлен параметру с типом число
Действия, принимающие аргумент списка могут принимать одно его значение, и автоматически обворачивать его в список:
player::message("Привет мир!")
// ^^^^^^^^^^^^^
// Действие player::message принимает список,
// но ему можно передать одно значение
player::message(["Привет", " ", "мир!"])
// ^^^^^^^^^^^^^^^^^^^^^^^
// Так тоже работает
Действия, принимающие маркера являются перечислениями, которым можно указать текст в виде значения:
player::message(["Привет", "мир"], merging = "SEPARATE_LINES")
Объекты аналогичны категориям действий: действия игрока (player
), действия сущности (entity
), действия мира (world
), действия с переменными (variable
). Все остальные действия находятся в объекте code
Вызов действия от объекта:
player::message("Привет мир!")
code::wait(10, time_unit = "SECONDS")
player::message("Привет мир спустя 10 секунд!")
Получение значения из списка по индексу
var a = [1, 2];
var b = a[0];
Установка значения в списке по индексу
var a = [1, 2];
a[0] = 3;
От переменных можно вызвать некоторые действия, которые принимают переменные (либо значения, которые изменяют):
Действие принимает переменную
var a = 1;
a.increment();
Действие принимает значение, которое изменяют
var a = ['Привет', 'мир'];
a.set_at(1, 'сервер');
Существуют и действия, которые устанавливают переменным какое-либо значение:
var a = variable::create_list([1, 2])
// Эквивалентно:
// var a = [1, 2]
var b = variable::get_at(a, 0)
// Эквивалентно:
// var b = a[0]
var C = 3;
var D = C.clamp(1, 2);
// Переменная D будет равна результату применения
// действия clamp к переменной C
Обычное повторение:
repeat::forever() {
player::message("Я буду выполняться вечно");
code::wait(1);
}
Повторения с условием:
var a = 1;
repeat::while(a.less(10)) {
player::message("A меньше 10!");
a++;
code::wait(1);
}
Повторения с параметрами:
repeat::on_range(0, 10) { index ->
player::message("Текущий индекс: $index");
code::wait(1);
}
Все действия, созданные вне определения события, будут добавлены к событию запуска мира, поэтому код:
player::message("Привет!");
никогда не сработает, так как при запуске мира в нём нет игроков. Такой код нужно переделать на:
event<player_join> {
player::message("Привет!");
}
Теперь при входе игрока ему будет писаться сообщение "Привет!".
Другие события определяются аналогичным способом, только айди события player_join
будет изменяться на 📓 другое нужное.
Функции (и процессы) могут иметь параметры и определяются так:
function abc(a, b) {
player::message("Аргументы! $a $b")
}
process abc(a, b) {
player::message("Аргументы! $a $b")
}
Не стоит сваливать весь код в один файл. Разделяйте свой код на несколько модулей, которые вы потом можете импортировать в один файл:
// variables.jc
var a = 1;
var b = 2;
// utils.jc
function say_hello() {
player::message("Привет!")
}
// index.jc
import './variables.jc';
import './utils.jc';
event<player_join> {
player::message("Данный код состоит из 3 модулей!");
}
Для подробной информации воспользуйтесь документацией:
Подсветка синтаксиса поддерживается только в среде разработки Visual Studio Code. Расширение можно установить, перейдя по ссылке