
ImproperUI
Мод ImproperUI для Minecraft позволяет создавать интерактивные GUI с помощью скриптового языка на основе CSS. Идеальное решение для разработчиков, которые хотят упростить создание интерфейсов без изучения сложного рендеринга.
ImproperUI
Мод ImproperUI - это решение для тех, кто считает рендеринг GUI в Minecraft слишком сложным. Вместо того чтобы писать тонны Java-кода с MatrixStack и прочими прелестями, ты можешь описывать интерфейсы на специальном скриптовом языке, очень похожем на CSS.
В ванильном Minecraft создание кастомных экранов - задача не из легких. Даже простой HUD требует понимания рендеринга и координат. ImproperUI берет эту боль на себя и позволяет сосредоточиться на логике интерфейса.
Введение
Для работы с ImproperUI Script понадобятся базовые знания CSS и HTML, а также Java. Синтаксис вдохновлен CSS (Cascading Style Sheets), но не идентичен ему.
Ниже приведен скриншот интерактивного экрана с перетаскиваемыми и прокручиваемыми элементами - это домашняя страница мода. Этот экран полностью написан на ImproperUI Script.
Последние изменения
Version: 0.0.6-BETA
Added:
- added ConfigReader
- added ImproperUIAPI.getConfigReader()
Patches:
- fixed config integer args not parsing properly
Добавление ImproperUI в ваш проект
Чтобы добавить ImproperUI в свой мод, скачайте jar-файл и подключите его вручную через Gradle.
Вот пример использования:
Шаг 1
Скачайте jar и добавьте его в файлы проекта и в build.gradle как зависимость:
dependencies {
compileOnly files("libs/ImproperUI-theVersionYouWant.jar")
}
Шаг 2
Положите скачанный jar в папку mods! Да, его нужно использовать как библиотеку.
Шаг 3 (финальный)
Инициализируйте API. Вызовите функцию init() у ImproperUIAPI и передайте:
modIdвашего модаmain class mod initializerвашего мода- список путей к скриптам внутри папки
src/main/resources/вашего мода - по соглашению скрипты лучше хранить в
src/main/resources/assets/YOURMODID/improperui/
public class ImproperUI implements ModInitializer {
@Override
public void onInitialize() {
ImproperUIAPI.init("improperui", ImproperUI.class,
"assets/improperui/improperui/what.ui",
"assets/improperui/improperui/screen.ui"
);
}
}
public class YourModInitializer implements ModInitializer {
@Override
public void onInitialize() {
ImproperUIAPI.init("yourModId", YourModInitializer.class,
"assets/yourModId/improperui/yourscreen1.ui",
"assets/yourModId/improperui/yourscreen2.ui"
);
}
}
Важно: когда будете парсить или запускать скрипты, ссылайтесь на имя файла скрипта, а не на путь из init()!
События (Events)
Чтобы слушать события из скрипта, создайте класс, реализующий CallbackListener.
Создайте метод:
- С аннотацией
@CallbackHandler - С параметром нужного типа события
- Имя метода должно совпадать с именем события из скрипта
public class CustomCallbacks implements CallbackListener {
@CallbackHandler
public void sendHelloWorld(MouseEvent e) {
if (e.input.isDown())
ChatUtils.sendMessage("Hello World");
}
}
В скрипте событие выглядит так:
element {
on-click: sendHelloWorld
}
Когда объявляете экран ImproperUIPanel, зарегистрируйте callback:
public void openScreen() {
ImproperUIPanel panel = new ImproperUIPanel();
panel.registerCallback(new CustomCallback());
// парсим скрипт и добавляем дочерние элементы
// panel.addChild()
MinecraftClient.getInstance().setScreen(panel);
}
Если запускаете скрипт через API:
public void openScreen() {
ImproperUIAPI.parseAndRunFile("yourModId", "testing.ui", new CustomCallback() /* и другие */);
}
Вспомогательные методы (Helper Methods)
Helper Methods:
- ImproperUIPanel.collect() // список всех элементов и виджетов, включая дочерние
- ImproperUIPanel.collectOrdered() // отсортированный по z-index список всех элементов и виджетов с дочерними
- ImproperUIPanel.collectById() // список элементов с указанным ID
- ImproperUIPanel.collectByClassAttribute() // список элементов с указанным классом
- ImproperUIPanel.collectById() // первый элемент с указанным ID
- ImproperUIPanel.collectByClassAttribute() // первый элемент с указанным классом
API:
- ImproperUIAPI.parse() // парсит скрипт и возвращает все распарсенные элементы
- ImproperUIAPI.parseAndRunFile() // парсит зарегистрированный файл скрипта (по ИМЕНИ, не по пути) из init() и открывает экран с элементами
- ImproperUIAPI.parseAndRunScript() // парсит зарегистрированный скрипт из init() и открывает экран с элементами
- ImproperUIAPI.reload() // перезагружает API
- ImproperUIAPI.reInit() // переинициализирует API с другим Mod ID (возможно)
Ключи конфигурации (Config Keys)
Ключ конфигурации состоит из трех частей: modId, confileFile, propertyName. Они используются для сохранения значений конфигурации для слайдеров и чекбоксов.
Чтобы использовать ключ конфигурации в скрипте, просто напишите все три части БЕЗ ПРОБЕЛОВ И ЧЕРЕЗ ДВОЕТОЧИЕ (:). Затем используйте эту строку как атрибут класса элемента:
slider #someId -yourModId:config.properties:testing-slider-value -someAnotherAttributeClass {
}
Это создает слайдер, который сохраняет значения в конфиг.
Теги (Tags)
| Элемент | Динамические hover/select/focus | Поддержка детей | Поддержка конфига | Алиасы | Специфические свойства: тип |
|---|---|---|---|---|---|
| element | ✅ | ✅ | ✅ | e, div | |
| checkbox | ✅ | ❌ | ✅ | active:boolean | |
| radio | ✅ | ❌ | ✅ | active:boolean | |
| button | ✅ | ❌ | ❌ | ||
| link | ✅ | ❌ | ❌ | a | href:string |
| slider | ❌ | ❌ | ✅ | min:double max:double value:double range:double,double decimal-places:integer | |
| input | ❌ | ❌ | ✅ | textbox | pattern:quote placeholder:quote |
| textfield | ❌ | ❌ | ✅ | textarea | |
| label | ✅ | ❌ | ❌ | textlabel | |
| header1 | ✅ | ❌ | ❌ | h1 | |
| header2 | ✅ | ❌ | ❌ | h2 | |
| header3 | ✅ | ❌ | ❌ | h3 | |
| header4 | ✅ | ❌ | ❌ | h4 | |
| header5 | ✅ | ❌ | ❌ | h5 | |
| header6 | ✅ | ❌ | ❌ | h6 | |
| positionable | ✅ | ✅ | ✅ |
Пример скрипта домашнего экрана
Вот как выглядит тот самый интерактивный экран с перетаскиваемыми блоками:
div #background-gradient {
size: 100%
margin-top: 100%
shadow-distance: 50%
shadow-color: #9775a6
}
div #display {
size: 420 240
center: both
border-radius: 10
border-thickness: 1
border-color: #412752
background-color: #2d162c
shadow-distance: 5
shadow-color: #683a68
child-align: grid
grid-columns: 1
div #title {
inner-text: "ImproperUI Interactives"
size: 100% 10
text-align: center
text-scale: 1.69
text-color: #9775a6
background-color: none
margin-top: 15
}
div #motto {
inner-text: "We got CSS in Minecraft before GTA 6"
size: 100% 10
text-align: center
text-scale: 0.8
background-color: none
margin-top: 10
}
div #motto {
inner-text: "The Ultimate Solution To Minecraft Rendering Being Too Difficult"
size: 100% 10
text-align: center
text-scale: 0.8
background-color: none
margin-bottom: 10
}
div #navbar {
size: 100% 15
margin-top: 10
background-color: none
child-align: grid
grid-columns: 100
button #discord {
inner-text: "Discord"
background-color: #9775a6
border-radius: 0
margin: 0
width: 20%
padding-left: 0
padding-right: 0
on-click: openDiscord
hovered => { padding: 3; border-thickness: 0; border-radius: 2; shadow-distance: 2; }
}
button #github {
inner-text: "GitHub"
background-color: #9775a6
border-radius: 0
margin: 0
width: 20%
padding-left: 0
padding-right: 0
on-click: openGithub
hovered => { padding: 3; border-thickness: 0; border-radius: 2; shadow-distance: 2; }
}
button #modrinth {
inner-text: "Modrinth"
background-color: #9775a6
border-radius: 0
margin: 0
width: 20%
padding-left: 0
padding-right: 0
on-click: openModrinth
hovered => { padding: 3; border-thickness: 0; border-radius: 2; shadow-distance: 2; }
}
button #wiki {
inner-text: "Wiki"
background-color: #9775a6
border-radius: 0
margin: 0
width: 20%
padding-left: 0
padding-right: 0
on-click: openWiki
hovered => { padding: 3; border-thickness: 0; border-radius: 2; shadow-distance: 2; }
}
button #wiki {
inner-text: "Example"
background-color: #9775a6
border-radius: 0
margin: 0
width: 20%
padding-left: 0
padding-right: 0
on-click: openExampleScreen
hovered => { padding: 3; border-thickness: 0; border-radius: 2; shadow-distance: 2; }
}
}
div #mini-world {
size: 100% 140
background-color: none
child-align: grid
grid-columns: 21
scrollable: true
background-clip: padding
div #block { background-image: textures/block/ice.png; size: 20; draggable: true; hovered => { border-thickness: 1; border-color: white; } }
div #block { background-image: textures/block/ice.png; size: 20; draggable: true; hovered => { border-thickness: 1; border-color: white; } }
div #block { background-image: textures/block/ice.png; size: 20; draggable: true; hovered => { border-thickness: 1; border-color: white; } }
div #block { background-image... (скрипт продолжается)" } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } }... (сокращено для читаемости)" } и т.д."
Если вы разрабатываете моды и хотите быстро создавать красивые интерфейсы - этот мод для Майнкрафт стоит попробовать. Учтите, что требуется знание Java и основ CSS.
