Это джей эм си си, он компилирует код в 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 к переменной C
if(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 модулей!");
}
Для подробной информации воспользуйтесь документацией: