Что нового — октябрь'26
У меня регулярно копится техдолг – задачи, которые хотелось бы сделать, но они не принесут ничего нового и съедят кучу времени. К примеру, у движка все еще нет документации. Пользователей ноль, так что она вроде бы и не нужна, но за годы разработки я и сам уже забываю, как что работает. Да и просто несолидно как-то.
Еще было бы здорово сделать редизайн редактора. Сейчас он собран на дефолтном Ant Design и выглядит слишком дженерик: темная тема слишком темная, а инспектору не хватает выразительности, из-за чего тяжело понять, что к чему относится.
С появлением агентов решать такие задачи стало значительно проще. Захотел с CSS in JS соскочить на CSS Modules – пожалуйста; собрать CI с линтерами и тестами – легко. В эйфории от быстрого результата я два месяца закрывал свои давние хотелки и к октябрю, наконец, успокоился.
Инфраструктура
Для начала я объединил движок и редактор в один монорепозиторий и накрутил CI: прогон юнит-тестов, линтеры, проверку, что пакеты корректно собираются, и так далее. Также наконец-то добавил интеграционные тесты на Playwright для редактора. Очень давно хотелось: редактор уже сильно разросся, и перед каждым регрессом возникала тревога, что опять придется протыкать все кнопки и проверять каждую форму. Не говоря о том, что редактор должен работать и на macOS, и на Windows, а под виндой я запускаю его в лучшем случае раз в год, и там меня обычно ждет неприятный сюрприз. Благо GitHub позволяет выбрать в CI образы macOS и Windows, чтобы гонять на них свои скрипты, так что теперь у меня есть автоматизированный регресс редактора на двух платформах со скриншотными проверками.
Редизайн
Далее я начал обновлять устаревшие пакеты: ESLint, TypeScript, Webpack и тому подобное. Переход на новый мажор Ant Design развалил все мои костыли, поэтому я решил, что настало время сделать полный редизайн редактора и добавить ему хоть немного идентичности. Подобрал цветовую схему, переверстал некоторые панели, заменил иконки, нарисовал простое лого для движка и добавил инспектору пару новых вариантов отображения полей: группировку в сворачиваемую секцию и поле ввода типа Vector для компактной записи координат.
Документация
Следующий пункт – это документация. Очень долго я откладывал ее создание, и писать все самостоятельно казалось уже неподъемной задачей. Но теперь, благодаря другу-нейрослопу, все изменилось. Собрал сайт на Astro Starlight, а на отдельной странице – API-справочник на TypeDoc с детальным описанием публичного API по JSDoc-комментариям. Подглядел это у pixi.js – понравилось. Даже с ИИ работа заняла около двух недель. Материала за эти годы накопилось много, и каждую страницу пришлось вычитать: убрать графоманию и излишние подробности про внутреннее устройство, которые только запутают. Разместил на домене dachajs.org. Надеюсь, не отберут.
Декораторы
Ну и последнее, чем я занимался в конце сентября, – это рефакторинг декораторов. Перенес их из редактора в движок, перевел с легаси-варианта TypeScript на современный стандарт и сделал чуть более полезными для рантайма. До этого декораторы по большей части нужны были только для того, чтобы описать, как рисовать компоненты и системы в редакторе, а коду движка они ничего не давали. Доработал декоратор поля так, чтобы он не только описывал, как отображать поле в инспекторе, но и сам проставлял ему значение из редактора при создании экземпляра класса. То есть в общем случае больше не нужно маппить значения из JSON редактора на поля компонента в конструкторе – движок сделает это сам.
Было:
@DefineComponent({ name: 'Camera', icon: 'Video' })
export class Camera extends Component {
@DefineField({ initialValue: 1 })
zoom: number;
@DefineField({ initialValue: false })
current: boolean;
windowSizeX: number;
windowSizeY: number;
constructor(config: CameraConfig) {
super();
this.zoom = config.zoom;
this.current = config.current;
this.windowSizeX = 0;
this.windowSizeY = 0;
}
}
Стало:
@DefineComponent({ name: 'Camera', icon: 'Video' })
export class Camera extends Component<CameraConfig> {
@DefineField({ initialValue: 1 })
zoom!: number;
@DefineField({ initialValue: false })
current!: boolean;
windowSizeX = 0;
windowSizeY = 0;
}
Это один из самых простых компонентов в движке, но в играх на джемах сложнее этого обычно писать и не приходилось.
Что дальше
Теперь я могу вернуться к своим изначальным планам. Нужно переработать структуру шаблонов и их отображение в редакторе. Добавить ассеты как сущность, а то каждая система сейчас загружает медиаданные по-своему. Ну и затем пойду разбираться, как работают тайлмапы.