Это джей эм си си, он компилирует код в json, который используется на сервере JustMC
Для работы с JMCC нужно:
-
Открыть страницу релизов GitHub
-
Выбрать понравившийся файл с компилятором
-
Открыть командную строку в папке с установленным файлом:
Win + R на Windows, затем вписатьcmdв появивщееся окно -
Использовать компилятор:
# Для Windows $ python jmcc.py compile example.jc
Для просмотра помощи о командах, используйте команду help
Перед тем как использовать jmcc, убедитесь что вы знаете синтаксис для создания программ.
Так же для использования jmcc, необходим установленный python.
Создайте файл с расширением .jc и таким содержанием:
event<player_join> {
player::message("Привет!")
}Скомпилируйте данный файл:
$ python jmcc.py compile [имя файла].jcЕсли компиляция была успешной, в папке с вашим файлом должен появиться новый файл, с таким же названием, но с расширением .json. Чтобы использовать его на сервере, вам нужно загрузить его на файлообменник, либо использовать аргумент -u:
$ python jmcc.py compile [имя файла].jc -uПри его использовании, компилятор не будет создавать файлы компиляции на вашем компьютере, а сразу передавать их в облако. Если компиляция была успешной, у вас в терминале должна появиться ссылка, которую можно использовать на сервере напрямую.
Важно: Облачные ссылки, созданные при использовании аргумента -u будут хранить код только 3 минуты. После этого времени они будут удаляться. Если вы хотите сохранить скомпилированный код на большее время, вам нужно будет сохранять его в сторонних файлообменниках.
"Текст!" # Текст
1 # Число
[1, 2] # Список
{"a":1,"b":2} # Словарь
value::health # Игровое значение
value::health<current> #Игровое значение с селектором
item("stone") # Значения, созданные фабрикамиl"текст" #текст типа legacy(цветной)
m"текст" #текст типа minimessage(стилизуемый)
p"текст" #текст типа plain(без всего)
j"текст" #текст типа jsonПеременные можно определять.
Определение локальных переменных
var a = 1;
#или
l`a`= 1;Определение игровых переменных
game var a = 1;
#или
g`a`= 1;Определение сохранённых переменных
save var a = 1;
#или
s`a`= 1;Встроенные (inline) переменные — переменные, значение которых просчитывается при компиляции, и заменяется при каждом их использовании.
Определение встроенных переменных
inline var a = 1;
#или
i`a`= 1;Переменные могут иметь имена, которые включают в себя селекторы либо строчные варианты значений. Так же, можно определить переменные с именем, состоящим из нестандартных символов, используя `` . К примеру:
Использование селектора в имени
var `%player%_переменная` = 1;Использование нестандартных символов в имени
var `странная переменная ⛏️` = 2;Вы можете определять переменную таким способом:
var a;
game var a;
s`a`;В таком случае не будет создано действия "Установить переменную", но эта переменная может быть использована как обычно.
var a: text;Однако определение с помощью var и типизация возможна только в начале строки.
Переменная созданная с помощью префикса s`a` определяет переменную только в случае, если она ранее не имела определение. В противном случае ничего не меняет.
Фабрики — функции, которые принимают аргументы и возвращают значение. Ими создаются предметы, зелья, локации и другие значения, которые можно определить в коде:
a = location(1, 2, 3);
b = item("stone_sword",nbt={Damage:1})Математические функции - фабрики, которые аналогичны функциям из %math.
Доступная математика:
+- сложение-- вычитание*- умножение/- деление//- целочисленное деление(нету в %math)%- остаток от деления^- возвести в степень(аналогpow())
Доступные функции:
abs(число)- Абсолютное значение числаsqrt(число)- Квадратные корень числаcbrt(число)- Кубический корень числаceil(число)- Округление числа до большего значенияfloor(число)- Округление числа до меньшего значенияsin(число)- Синус числаcos(число)- Косинус числаround(число, N)- Округление числа до N цифер после запятойpow(число, степень)- Возведение числа в степеньmin(число, число)- Минимальное из значенийmax(число, число)- Максимальное из значений
Использование:
a = floor(0.3) + abs(-3) + sqrt(2);Небольшая особенность: возможная математика будет выполняться. К примеру результатом выше приведенного будет a = 4,71421
Вызов действий должен происходить от объекта или переменной.
Анатомия вызова:
player::message("Привет мир!")
#^^^^^^
#переменная или объект
player::message("Привет мир!")
# ^^
# разделитель, определяющий тип вызова:
# :: для объектов
# . для переменных
player::message("Привет мир!")
# ^^^^^^^
# имя функции
player::message("Привет мир!")
# ^^^^^^^^^^^^^
# аргумент вызоваАргументы вызова могут определяться:
-
позиционно
player::message("Привет мир!")
-
с именем
player::message(text = "Привет мир!")
-
комбинированно
player::message("Привет мир!", merging = "SPACES") #Позиционные аргументы устанавливаются на следующее неустановленное значение: player::message("SPACES", text = "Привет мир!")
Так же у действий есть селектор:
player::message<all_players>("Привет мир!")
#Выведет "Привет мир!" всем игрокам.При вызове действий компилятор проверяет соответствие типов значений, переданных действию.
К примеру, если действие принимает в качестве аргумента только число, то и вызвать его можно только с числом либо переменной:
a = 1;
variable::increment("a",1);
# ^^^
# Ошибка: Аргумент с типом текст не может быть
# установлен параметру с типом переменнаяДействия, принимающие аргумент списка могут принимать одно его значение, и автоматически обворачивать его в список:
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 секунд!")Получение значения из по индексу
#для списков
a = [1, 2];
b = a[0];
#для текстов
a:text = "12345"
b=a[0]
#для словарей
a:map = {"a":1,"b":2}
b=a["a"]Установка значения по индексу
#для списков
a = [1, 2];
a[0] = 3;
#для текстов
a:text="12345"
a[0]="6"
#для словарей
a:map = {"a":1,"b":2}
a["a"]=3Получение значений из среза
#для списков
a = [1, 2, 3];
b = a[0:2];
#для текстов
a:text = "12345"
b=a[0:2]Установка значения по срезу
#для списков
a = [1, 2, 3];
a[0:2] = [5, 4];
#для текстов
a:text="12345"
a[0:2]="65"
#Указывать размер равный размеру среза не обязательно.Способы приравнивания
a+=1 #сложение
a-=1 #вычитание
a*=1 #умножение
a/=1 #деление
a//=1 #целочисленное деление
a^=1 #возвести в степень
a%=1 #получить остаток От переменных можно вызвать некоторые действия, которые принимают переменные (либо значения, которые изменяют):
Действие принимает переменную
a = 1;
a.increment();Действие принимает значение, которое изменяют
a = ['Привет', 'мир'];
a.set_at(1, 'сервер');Существуют и действия, которые устанавливают переменным какое-либо значение:
a = variable::create_list([1, 2])
# Эквивалентно:
# var a = [1, 2]
b = variable::get_list_value(a, 0)
# Эквивалентно:
# b = a[0]
C = 3;
D = C.clamp(1, 2);
# Переменная D будет равна результату применения
# действия clamp к переменной Cif(a.exists()){
player::message("Переменная a существует!")
}
#или инвертируйте условие
if not (a.exists()){
player::message("Переменная a не существует!")
}
#Другой способ
if(not a.exists()){
player::message("Переменная a не существует!")
} else {
player::message("Переменная a существует")
}Обычное повторение:
repeat::forever() {
player::message("Вечное выполнение");
code::wait(1);
}Повторения с условием:
a=1;
repeat::while(a.less(10)) {
player::message("A меньше 10!");
a+=1;
code::wait(1);
}
#Или инвентируйте условие
repeat::while(not a.less(10)) {
player::message("A меньше 10!");
a+=1;
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() {
player::message("Функция!")
}process abc() {
player::message("Процесс!")
}Не стоит сваливать весь код в один файл. Разделяйте свой код на несколько модулей, которые вы потом можете импортировать в один файл:
// 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 модулей!");
}Для подробной информации воспользуйтесь документацией: