Отдельный локальный проект. Исходники клиента, GitHub main, теги и релизы не изменяются.
Требуется Node.js 22.12+ или 24 LTS и npm. Зависимости зафиксированы в package-lock.json.
cd D:\AMF-Website-Phase1
npm ci
npm run devСайт: http://127.0.0.1:5173/. Сервер слушает только loopback. Если он уже запущен, второй экземпляр на том же порту не требуется.
npm test
npm run build
npm run previewProduction-preview: http://127.0.0.1:4173/. Результат сборки — dist/.
Это полностью статический сайт, пригодный для GitHub Pages, включая размещение
в подкаталоге. Никаких действий публикации в этом проекте не выполнено.
Не открывайте dist/index.html через file://: для Worker и fetch нужен HTTP.
- Колесо / touchpad: вперёд и назад вдоль единого маршрута.
- Главная / Функции / Скачать: плавный переход к назначенной точке.
- Ручная прокрутка прерывает автоматический переход с текущего положения.
- Arrow keys / PageUp / PageDown: доступное с клавиатуры перемещение.
- Home / End: переход к первой / последней секции.
- N или кнопка Entities: переключение реальных game / auxiliary layers.
- «Карта и рендер»: сведения о фактически загруженной карте и draw calls.
Публичная камера движется по пути, построенному A* на реальном Game Layer. Solid, no-hook, death и границы запрещены. Отключённые от native spawn карманы исключены. Стоимость пути предпочитает открытые коридоры и удаление от стен, а не пересечение массивов Freeze. Freeze — опасное, но физически не сплошное пространство: необходимые пересечения допустимы, физика Tee не симулируется. Диагональное срезание углов запрещено. Упрощение сохраняет стоимость прохода; скругления проверяются точными пересечениями каждого сегмента с расширенными препятствиями. Непроверенного Catmull–Rom больше нет.
Движение параметризовано по длине. Скорость ограничена и снижается на поворотах; ускорение и торможение сглажены, расчёт разбит на малые временные шаги. Кнопки могут выбрать более короткий игровой путь. Колесо прерывает такой переход через проверенное соединение с основным маршрутом, без переноса камеры. Единый zoom маршрута — 1.1, исходное значение из резервной копии, явно выбранное пользователем. Формула WebGL не изменена: увеличение zoom расширяет видимую область. Геометрия проверяет центр/траекторию камеры, а не весь прямоугольник кадра. Вблизи края широкий кадр может показывать окружение за границей Game Layer — это не повод автоматически приближать камеру или сдвигать точку. Время анимаций не связано с камерой.
Актуальные инструменты ручной коррекции:
- Семь обязательных точек защищены: их координаты, ID, порядок и привязки не меняются.
- Клик по голубой линии добавляет оранжевый ромб — корректирующую точку.
- Перетащите ромб или задайте X/Y; после отпускания перестраивается его участок.
- «Удалить коррекцию» удаляет только выбранный ромб. ↑/↓ меняют порядок только коррекций внутри одного участка, а не порядок обязательных точек.
- Shift + клик / «Коррекция в центре» добавляют коррекцию рядом с ближайшим участком.
- Голубые мелкие точки показывают автоматически построенную геометрию; клик по ней превращает выбранное место в сохраняемую ручную коррекцию.
- «Предпросмотр» запускает движение по всему отредактированному пути; slider позволяет исследовать любой его участок, колесо работает в режиме preview.
- Ошибочная коррекция не переносится. Ошибка показывается явно, preview/save блокируются до исправления или удаления. Последний корректный путь красный.
- «Сохранить JSON в проект» записывает
segments: [{from,to,points:[{id,x,y}]}]вместе с неизменёнными обязательными точками. После reload коррекции загружаются из JSON, не заменяются автоматическим стартовым маршрутом. Есть экспорт/импорт. - Устаревшая вкладка получает HTTP 409 вместо перезаписи более нового JSON.
- Малого лимита числа коррекций в UI нет; файл ограничен 8 MiB для безопасности.
Исходный масштаб маршрута зафиксирован; «Zoom камеры» относится только к свободному обзору редактора. Редактор не меняет внешний вид сайта и отсутствует в production.
Описание старого редактора ниже сохранено как история Phase 1; для текущего ручного редактирования используйте инструкции выше.
Открыть http://127.0.0.1:5173/?editor=1 (именно dev server).
- Перетаскивание карты: свободная камера. Колесо: zoom вокруг курсора.
- Shift + клик: новая обязательная точка. «Точка в центре» — то же в центре камеры.
- Перетаскивание точки: изменение координат и автоматическое перестроение после отпускания. X/Y можно менять численно. Путь проходит через точные координаты, без скрытого переноса к ближайшей клетке. Редактируемая точка становится обязательной.
- Кнопки ↑/↓: порядок точек. «Удалить»: удалить выбранную точку.
- Двойной клик по точке в списке: переместить свободную камеру к ней.
- «Сделать обязательной в центре камеры»: записать только координаты свободной камеры. «Единый zoom маршрута» задаёт постоянный масштаб всего пути; «Zoom камеры» меняет только свободный обзор редактора и не влияет на публичную камеру.
- Списки Главная / Функции / Скачать: назначить разделы точкам по стабильным ID.
- «Предпросмотр»: движение тем же контроллером, который работает на сайте. Колесо и кнопки разделов остаются доступны; slider позволяет исследовать путь.
- «Сохранить JSON в проект»: атомарно обновить public/camera-route.json.
- «Экспорт JSON» / «Загрузить JSON»: скачать маршрут / открыть ранее сохранённый.
Соседние совпадающие точки запрещены. Непроходимая точка остаётся в черновике на заданном месте, с явной причиной ошибки. Сохранение и preview блокируются; оранжевым показан последний корректный путь. Исправьте/удалите точку, чтобы продолжить. Сервер сохранения независимо проверяет геометрию, а не только структуру JSON. При удалении назначенной точки раздел переназначается на соседнюю, а не остаётся с некорректной ссылкой. Невалидный JSON не заменяет текущий маршрут.
Редактор не является конструктором оформления. Он управляет только маршрутом.
Он доступен в DEV на localhost/127.0.0.1. Его JavaScript, CSS и endpoint сохранения
исключены из production; npm run build отдельно проверяет это.
Endpoint принимает только same-origin localhost POST JSON до 64 KiB и пишет
только один фиксированный файл маршрута. Клиентский путь записи не принимается.
По уточнению пользователя старые восемь точек НЕ являются обязательными. Они
сохранены только в artifacts/route-before-gameplay-20261024-201026/ вместе с
прежними route/main/editor исходниками. Новый путь инициализирован самостоятельно:
native spawn → стартовая линия → промежуточная секция → финишная линия.
Затем пользователь предоставил 7 новых обязательных точек: точный экспорт
сохранён в artifacts/route-user-export-20261024-202220.json (исходный SHA-256
B20CE9C0630AF6B20F0CE7D40C67267D2500F251122F50B76EE4A5AA158994A7).
Текущий public/camera-route.json использует именно эти семь точек, а не
автоматические четыре и не старые восемь. Их координаты, порядок, ID, исходные
поля zoom и привязки секций сохранены в точности. Меняется только общий zoom
сначала с 0.5 на 0.34 из-за излишне строгой проверки всего кадра. Эта проверка
затем отменена по уточнению пользователя, и согласованный 1.1 восстановлен.
Новые точки получают mandatory:true. Перестроение соединений не изменяет их.
JSON хранит ориентиры, единый zoom и секции; промежуточная геометрия детерминированно
восстанавливается из Game Layer. npx tsx scripts/plan-gameplay.ts только печатает
начальный план по native маркерам, никогда не перезаписывает текущий JSON.
После изменения маршрута production пересобирается: npm run build.
public/maps/for-site.map — неизменённая копия исходного For Site.map.
SHA-256: 63CBC6C5BA1DA35F7449A1D9D8A4BEC5274E025A9C84445CDB3DCE8F76B3F0EB.
Браузер загружает именно .map, разбирает DATA/container и zlib blocks в Web Worker,
передаёт RGBA и tile buffers через transferable objects и создаёт реальные WebGL 2
текстуры / геометрию. Предварительного screenshot, видео или baked background нет.
Фактическое содержимое карты:
- DATA v4, 1 718 790 bytes.
- 8 groups, 28 layers: 18 tile layers, 10 quad layers, 28 quads всего.
- 237 × 70 tiles в game layer; 12 305 non-air game tiles.
- 17 embedded RGBA images; внешние mapres этой карте не нужны.
- Game, Front, Tele, Tune и Speedup auxiliary layers; Tune и Speedup содержат данные.
- 2 position envelopes (5 points), 2 animated cloud quads.
- 0 color-envelope bindings; curves в этой карте — LINEAR.
- UUID extension — automapper configuration (editor metadata, не анимация).
Поддерживаются native quad position envelopes (X/Y/rotation, pivot, offset), quad и tile color envelopes (RGBA), STEP, LINEAR, SLOW, FAST, SMOOTH и BEZIER. Bezier решается отдельно по time-компоненте каждого канала с native tangent deltas; поддерживаются отдельные DDNet UUID tangent items и upstream envelope v3. Отсутствующие Bezier tangents дают native linear fallback с предупреждением. Неизвестные curves дают такой же fallback, явно отображённый в диагностике.
Move Tiles: в native формате tilemap имеет color envelope, но не поле position
envelope. Движущаяся геометрия задаётся quads с position envelope. Она полностью
проходит через тот же рендер, включая вращение и параллакс. Семантические имена
TClient QFr/QUnFr/QDeath/QStopa/QCfrm/QHook/QUnHook распознаются в Entities,
но отображаются там диагностической заливкой реальной анимированной геометрии,
а не точной копией оформления TClient Entities. Игровая collision не симулируется.
В этой конкретной карте таких Q-слоёв нет: анимированы только два облака.
Не добавлены выдуманные движения статических terrain tiles. Position / color /
rotation / curves проверены тестами, а реальные облака — на исходных данных карты.
Для отдельной визуальной проверки игровых Move Tiles нужен .map с такими quads.
Обычный режим сохраняет авторский порядок слоёв, corner colors и UV, tile flips / rotation, group parallax и offsets. Формула map-to-world взята из спецификации поведения DDNet (base area 1150×1000, max view 1500×1050, parallax zoom). Entities рисует настоящие индексы game / special tiles с DDNet atlas; номера tune, tele, switch и параметры speedup читаются из их собственных raw blocks.
- Tiles разбиты на 32×32 chunks; отправляются только пересекающие viewport chunks.
- Quads отсекаются по фактическим bounds после envelope transform.
- GPU buffers/текстуры создаются при загрузке; не пересоздаются каждый кадр.
- У текстур нет atlas mipmap bleeding; используется linear sampling с texel inset.
- Pixel ratio ограничен 2; исходное изображение карты не уменьшается.
- Отдельный clock анимаций продолжает логически идти при остановленной камере.
- В скрытой вкладке RAF остановлен. При возвращении камера не догоняет пропущенное время рывком, а анимации синхронизируются с elapsed monotonic time.
- WebGL context loss/restoration обработаны; workers завершаются после decode, HMR освобождает события, buffers и текстуры.
- Нет прямого pixel-by-pixel сравнения с запущенным DDNet. Есть реальный browser QA.
- Нет multiplayer physics, server clock, shader effects сторонних модификаций, freeze character overlay или игровой симуляции. Для фона это не требуется.
- Sound layers не воспроизводятся (в данной карте отсутствуют); неизвестный тип слоя вызывает явную ошибку, неизвестный UUID — видимое предупреждение.
- DATA big-endian (
ATAD) и Teeworlds 0.7 compressed tilemap v4 не поддержаны. Это не используется вFor Site.mapи не скрывается в случае другой карты. - Бесконечное повторение граничных tiles за пределами авторского tilemap не реализовано. Внутри карты используются точные данные; редактор может показать эту границу при сильном zoom-out. При подборе публичного пути учитывайте это.
- Полностью идентичное оформление gameplay Move Tiles Entities не заявляется.
- Нет автоматического детектирования производительности всех GPU/браузеров.
- Права на пользовательскую карту и её embedded art надо подтвердить перед
публикацией: поля author/license в
.mapпустые. Сейчас проект только локальный.
Изучены DDNet/libtw2 Datafile,
Map, чистые исходники DDNet 20.1.1
(mapitems.h, render_map.cpp, graphics.cpp) и подходы
ddnet/tw-webgl /
TwMap. Чужой renderer не скопирован:
в проекте собственный TypeScript parser и WebGL 2 renderer.
BestClient исследован как референс поведения навигации и переходов, его код, карта, UI-assets и графика не копируются.
fflate — MIT (license в node_modules/fflate/LICENSE).
Comfort entity atlas — CC BY-SA 3.0, автор louis; этот официальный ресурс DDNet
побайтно совпадает с atlas режима Entities на BestClient. См. THIRD_PARTY.md и
public/licenses/. Официальная ссылка скачивания ведёт только на существующий
release v2.0.1.
public/camera-route.json — единственный источник геометрии; утверждённый JSON
не перестраивается. Основные точки отмечены mandatory: true, дополнительные
точки формы — mandatory: false либо controls в segments. При наличии отмеченных
основных точек остальные точки отдельными разделами не становятся.
Сейчас основных точек 7. public/site-sections.json содержит только тексты,
карточки, кнопки и ссылки на ID этих точек, без дублирования координат/zoom.
Нажатие вкладки анимирует координаты камеры напрямую к выбранной точке за 1000 мс с quintic easing. Для этого перехода промежуточные точки маршрута не посещаются; камера может пересекать стены. Время берётся из RAF/performance.now, не из числа кадров. Первый кадр на/после 1000 мс фиксирует точные координаты назначения и синхронизирует arc-distance с её местом на JSON-маршруте. Повтор выбранной цели не перезапускает движение; новая цель начинает переход из текущих визуальных координат. Колёсико после приземления продолжает движение по сохранённой линии с естественным сглаживанием, не меняя zoom. Если колёсико используют во время вкладочного перехода, его дельта применяется после посадки. A* для вкладочной навигации не вызывается.
Entities: физическая KeyN, без автоповтора, без перехвата ввода текста/IME
или сочетаний Ctrl/Alt/Meta. Значение event.key и раскладка не используются.
В существующем редакторе откройте «Разделы: тексты, карточки и кнопки»:
список всех разделов, заголовки, описание, карточки и действия кнопок доступны
для изменения. Карточки/кнопки редактируются как JSON-массивы, а не через новый
визуальный конструктор. Сохранение меняет только site-sections.json, создаёт
его копию в artifacts/content-backups и проверяет конфликт другой вкладки.
Привязки точек защищены от смены порядка и не меняют окончательный маршрут.
На узких экранах верхнее меню прокручивается горизонтально.
Откройте http://127.0.0.1:5173/?editor=1 после npm run dev.
Редактор сразу использует ручной маршрут без ограничений стен. При открытии
старого автоматического JSON сначала создаётся резервная копия, затем маршрут
переводится в ручной черновик; файл на диске не перезаписывается.
Существующие точки и коррекции сохраняют координаты, ID, порядок и привязки
разделов; убираются только автоматически рассчитанные обходы стен.
Для нового маршрута с нуля отдельно используйте «Очистить маршрут».
До сохранения это черновик.
После очистки ручной режим сохраняется. Первые две точки ставятся обычным кликом
в режиме редактирования, последующие — Shift + клик или «Точка в центре».
Точка внутри стены допустима; проверяются только границы карты и структура JSON.
Левая кнопка рисует линию; следующий штрих начинайте рядом с её концом.
«Перемещать карту» отделяет панорамирование от рисования; колесо меняет только
свободную камеру редактора. Масштаб воспроизведения остаётся 1.1.
В режиме «Редактировать маршрут» перетаскивайте точки или участок линии. Клик по линии вставляет редактируемую точку. Delete удаляет выбранную точку или коррекцию в любом режиме редактора (кроме ввода текста/чисел); для диапазона отметьте начало, выберите конец и удалите участок. Оставшиеся соседи соединяются напрямую. Можно отдельно удалить хвост маршрута. «Отменить» / «Повторить» и Ctrl+Z / Ctrl+Y работают для штрихов, правок и очистки. Назначайте Главную, Функции и Скачать через существующие списки точек.
Свободный JSON имеет mode: "freehand"; points — окончательные координаты
линии после одного локального сглаживания штриха. При загрузке повторного
сглаживания, A* и проверок стен нет. Колёсико и предпросмотр идут по длине этой
линии; вкладки используют отдельные прямые координатные переходы и в конце
синхронизируются с соответствующей точкой линии. Zoom постоянный. Выход центра за границы карты
отклоняется без переноса точек; близость к краю вызывает предупреждение.
Семь существующих точек не заменяются при обновлении редактора.
«Очистить маршрут» требует подтверждения и сначала сохраняет черновик в
artifacts/route-backups/. Пустой маршрут записывается отдельным сохранением
с повторным подтверждением и остаётся пустым после загрузки. Каждая успешная
запись JSON также резервирует предыдущий файл. «Восстановить резервную копию»
загружает последнюю копию в черновик; остальные копии доступны через «Загрузить JSON».
При конфликте изменений в другой вкладке запись отклоняется, а не перезаписывает её.
npm test — parser исходной карты, целостность, реальные entity arrays и облака,
все кривые, pivot rotation, parallax, tile orientations, повреждённые входы,
длина дуги, движение в обе стороны, wheel interruption, 30/60/144 FPS и JSON.
npm run build — TypeScript + Vite production + проверка исключения редактора.
npm run inspect:map — полный отчёт о реальных слоях/envelopes без изменения карты.
Подробности выполненных browser-проверок и оставшихся ограничений — в TESTING.md.