TGU HUD + КЛИЕНТСКИЙ КУРСОР VOIDRP
Ресурс-пак для Minecraft Java Edition 26.3, resource format 97.1.
Тестовый датапак: data format 121.0. Под «2.63» принята версия 26.3 из имени вашего архива.

1. ЧТО СДЕЛАНО И ЧТО ЕЩЁ НЕЛЬЗЯ ОБЕЩАТЬ

Сохранены активные шрифты, текстуры и код GUI в title из HUD-proto-RP-26.3-v229.zip.
Добавлен курсор с формой стрелки из pack/Pointer.kt проекта voidrp-ui.
Движение этой стрелки считается клиентским шейдером из геометрии неподвижного
text_display, заново каждый кадр. Сервер не присылает координаты/скорости курсора.

Это адаптация, а не буквальная вставка всех шейдеров VoidRP. В предоставленном VoidRP
input/Pointer.kt и input/Motion.kt вычисляют движение на сервере, а Shaders.kt играет
расписание позиций и скоростей по GameTime. Перенос этого кода сохранил бы серверную
зависимость. Его здесь нет в активном ресурс-паке. Оригинальные файлы курсора приложены
как справочные исходники в integration/voidrp-reference, с лицензией MIT.

Критическое ограничение для вашего сценария: в 26.3 мир, затем post effects, затем
GUI рисуются последовательно. text_display принадлежит миру; title принадлежит GUI.
Поэтому НЕПРОЗРАЧНАЯ ПАНЕЛЬ TITLE МОЖЕТ ЗАКРЫВАТЬ КУРСОР. Полупрозрачная панель
окрашивает его своим цветом/альфой. Даже minecraft:end_of_frame и /posteffect в этой
версии выполняются до GUI — переименование post effect не решает порядок слоёв.

Таким образом, ресурс-пак решает объединение шейдеров, изоляцию ванилы и клиентское
движение, но не полностью решает «свободный курсор поверх непрозрачного title».
Нельзя выдать такой результат за полностью готовое title-меню без этого ограничения.
Для полного меню нужен выбор транспорта: панель и курсор в одном world-слое с
управляемым порядком отрисовки, штатный экран/dialog с нативной мышью, либо клиентский
мод, дающий GUI доступ к мыши/повороту камеры. Перенос панелей в world-слой — отдельная
переделка рендера меню, а не простая смена команды title на summon.

Это курсор от взгляда, а не свободный системный указатель. Камера продолжает вращать
мир. После полного разворота yaw через +/-180 градусов направление оборачивается.
Для нормальной работы меню держите поворот в рабочем секторе перед собой.

2. УСТАНОВКА И БЫСТРАЯ ПРОВЕРКА

TGU-HUD-ClientCursor-Java-26.3.zip положить целиком в .minecraft/resourcepacks.
Включить его в клиенте Java 26.3. Два исходных пака одновременно включать не нужно.
Клиентские моды не требуются для этого рендера курсора.

TGU-ClientCursor-Datapack-Java-26.3.zip положить целиком в <мир>/datapacks.
В игре выполнить /reload.

/trigger vrc_ctl set 1    — включить только курсор; не перезаписывает ваш title.
/trigger vrc_ctl set 2    — выключить курсор.
/trigger vrc_ctl set 3    — курсор + пример надписи title.

OP-команды для конкретного игрока:
/execute as <ник> at @s run function tgu_cursor:open
/execute as <ник> at @s run function tgu_cursor:close
/execute as <ник> at @s run function tgu_cursor:demo
/execute as <ник> at @s run function tgu_cursor:demo_close

При открытии pitch один раз сбрасывается в 0 — это та же схема открытия, что у VoidRP.
После этого yaw/pitch игрока и Rotation носителя не подменяются каждый тик.
Закрытие курсора само по себе не очищает title. demo_close дополнительно очищает title.
Старые /summon носителей курсора из предыдущих экспериментов нужно выключить/удалить.
Старый цвет #B00102 и текстура с B=19 больше не являются командами нового курсора.

Тестовый датапак прежде всего для одиночной игры или отдельных тестовых комнат.
Vanilla-датапак не умеет показать обычную сущность одному определённому клиенту:
другие игроки, отслеживающие этот носитель, тоже могут получить его курсор.
Датапак не использует /tp сущности и не обновляет текст курсора в tick.
Носитель остаётся на месте открытия: если уйти далеко, он перестанет отслеживаться.
Это не итоговый многопользовательский контроллер интерфейса.

3. ПРОТОКОЛ НОСИТЕЛЯ ДЛЯ ПЛАГИНА

Тип: minecraft:text_display.
Текст: один символ U+E900 (в Java: "\uE900").
Font: tgu:cursor/client.
Цвет: #FFFFFF. Отключить shadow и shadow_color. Альфа текста 255.
background: 0; default_background: false; see_through: true.
billboard: fixed. НЕЛЬЗЯ center/vertical/horizontal: они стирают опорный поворот.
Rotation: [anchorYaw, 0]. anchorYaw сохранить на открытии; больше не менять.
Transformation: единичный масштаб [1,1,1], нулевой сдвиг и оба quaternion [0,0,0,1].
width: 0; height: 0 — не давать обычному фрустумному отсечению убрать носитель.
line_width: 4096; text_opacity: 255 (в NBT это -1b).
brightness: {block:15,sky:15}; shadow_radius и shadow_strength: 0.
Разместить примерно на 0.8 блока перед глазами игрока при открытии.

Глиф имеет текстурную ячейку 20x20: внутренняя стрелка 18x18, служебная рамка 1 px.
Шейдер проверяет две независимые текстурные сигнатуры, а не только цвет текста.
Размер атласа берётся через textureSize, жёсткого предположения «атлас 256» нет.
Не уменьшайте scale носителя до 0.001: это ухудшает точность восстановления осей.
Не добавляйте поворот/неравномерный масштаб/сдвиг в Transform ради положения курсора.
Стрелка рисуется в экранных координатах; физическая трансляция носителя не задаёт X/Y.

4. ЖИЗНЕННЫЙ ЦИКЛ ЛИЧНОГО МЕНЮ

Открытие:
  - дождаться успешного применения нужного ресурс-пака;
  - сохранить anchorYaw, один раз выставить pitch=0;
  - создать один носитель, доступный только владельцу;
  - отрисовать страницу вашим GUI-движком с учётом ограничения слоёв из пункта 1;
  - сохранить сессию: UUID игрока, ID/UUID носителя, anchorYaw, viewport, hitboxes.

Пока меню открыто:
  - НЕ отправлять name/text/цвет/Rotation носителя на каждом движении мыши;
  - НЕ делать tp/setRotation игрока каждый тик;
  - НЕ подключать MotionCodec/GameTime/velocity для визуального движения этого курсора;
  - читать входящие yaw/pitch только для hover и hit-test;
  - обновлять страницу только при изменении содержимого или наведённого элемента.

Если игроку разрешено ходить, носитель можно переносить ближе к его глазам, сохраняя
тот же anchorYaw и единичный Transform. Это лишь поддержание tracking range, не
управление экранными координатами. Либо запретить физическое перемещение на время меню.
Не вращать носитель вслед за камерой: курсор тогда будет оставаться по центру.

Закрытие:
  - remove/despawn носителя; убрать именно свою сессию;
  - очищать свой title только если плагин владеет этим каналом;
  - убирать носитель при quit, death, смене мира и остановке плагина;
  - при внешнем телепорте с поворотом закрыть или заново открыть сессию;
  - закрывать сессию при смене camera entity/spectator target.

Для Paper не обязательно делать вручную все пакеты. В callback world.spawn заранее
вызвать entity.setVisibleByDefault(false) и entity.setPersistent(false), затем
player.showEntity(plugin, entity) только для владельца. Параметры задать до публикации.
При закрытии entity.remove(). Это стандартный способ из документации Paper.
Альтернатива — виртуальный text_display: spawn + metadata только одному соединению,
remove-entity пакет на закрытии. IDs metadata брать из адаптера именно вашей версии,
а не копировать номера от 1.21.x. Protocol vanilla-клиента 26.3: 777.

5. КООРДИНАТЫ И НАЖАТИЯ

Клиентская схема:
  H = 480
  W = 480 * aspect
  sensitivity = 8 HU/градус
  dx = wrapDegrees(yaw - anchorYaw)
  x = W/2 + 8*dx
  y = H/2 + 8*pitch

Координаты здесь относятся к ОСТРИЮ стрелки. Размер её картинки:
  arrowScale = 480/1024
  extent = 18*arrowScale = 8.4375 HU
  hotspot = (1.5,1)*arrowScale

Границы острия:
  x от 1.5*arrowScale до W - 16.5*arrowScale
  y от 1.0*arrowScale до H - 17.0*arrowScale

На 16:9 W=853.3333; центр (426.6667,240).
При yaw-anchorYaw=20 и pitch=10 остриё (586.6667,320).
Пример серверного hit-test: integration/CursorMath.java. Это расчёт взаимодействия,
не код для пересылки позиции указателя. Графическое движение не ждёт этих вычислений.

У vanilla-сервера нет надёжного сообщения с размером окна/GUI scale игрока. Нельзя
считать 16:9 гарантированным. Для hitboxes нужен сохранённый выбор aspect или
калибровка интерфейса. При несовпадении aspect клики и картинка разойдутся.
Также ваш исходный title-движок использует собственные posed/GUI единицы: приводите
его hitboxes к экранному канвасу H=480, учитывая GUI scale, а не смешивайте единицы.
Камера в третьем лице, bobbing и эффекты повреждений могут менять видимую ориентацию;
для точного меню предпочтительны первый вид и неподвижный игрок.

Шейдер не отправляет на сервер результат своих вычислений и не вызывает click_event.
Кнопка становится интерактивной только после добавления обработчика в плагин.
Для PacketEvents можно слушать look/position-and-look, attack/use item/swap-hand;
из этих событий брать актуальный yaw/pitch и явно назначенное действие меню.
При обработке клика использовать последний доступный look, не старый сглаженный XY.
Из network callback передавать изменения мира/инвентаря на корректный серверный поток.
Пакет keepalive, task на 60/85 FPS и спам bossbar/title для этого курсора не нужны.

6. СОВМЕСТИМОСТЬ С ВАНИЛОЙ И СО СТАРЫМ HUD

В minecraft оставлены только shaders/core/text.vsh и text.fsh. Все новые include,
текстуры и шрифты расположены в tgu. Курсор не использует глобальный red nibble 6..E.
GUI-ветки распознаются по TGU-текстурам; в world обычные буквы не перепозиционируются.
Все varyings инициализируются до ранних return. Пары location совпадают в vsh/fsh.
OIT alpha-only/accumulation учитываются; белые/серые/цветные ванильные тексты идут
по исходному ванильному пути. Базовый fragment pipeline и fog сохранены.

Копии tgu:t1..t4 теперь ссылаются на собственные bitmap-листы с метаданными RGB.
Альфа букв, height, ascent и структура providers сохраняются. minecraft:default
и сами ванильные bitmap-файлы не переопределяются. Это убирает цветовые ложные срабатывания.
Текстовые листы f-шрифтов маркированы тем же способом, с неизменной альфой.
Rect/img имеют дополнительную проверку служебных пикселей; рамка не видна на экране.
Протокол TWO_PIX, RGB565+A4, палитра и отрицательные пробелы исходного HUD сохранены.
Для TWO_PIX нельзя вырубать shadow у элементов, где shadow_color несёт данные;
отключение shadow из пункта 3 относится только к НОСИТЕЛЮ КУРСОРА.

Удалены глобальные подмены box_blur, inworld_menu_background, ванильных кнопок/dialog
и minecraft:block/netherite_block; оставлять их значило бы менять ванилу без меню.
Поэтому старое скрытие подложки dialog по ширине 173 в новом паке отсутствует,
а netherite block снова обычный. GUI в title этих глобальных замен не требует.
Удалены дубли core/entity, core/item, legacy rendertype_entity_translucent и backups.
В моделях shade:false заменено на shade_direction_override:"up" для формата 26.3.

Это один объединённый core-text пакет. С третьим ресурс-паком, который тоже меняет
core/text.vsh/fsh, автоматического слияния не бывает: потребуется отдельное объединение.
Iris/OptiFine и их сторонние shader packs здесь не тестировались; сначала проверить vanilla.
Не заявлена совместимость с Bedrock, 1.21.x, 26.2, 26.4 или их snapshots.

7. ВЫПОЛНЕННЫЕ ПРОВЕРКИ

Взяты шейдеры из официального client.jar Java 26.3 и сверены форматы 97.1/121.0.
Проверен код DisplayRenderer/TextFeatureRenderer: позиции глифов уже могут быть
трансформированы на CPU. Поэтому клиентский курсор восстанавливает две оси через
derivatives, а не ошибочно считает ModelViewMat полной матрицей сущности.
Проверен GameRenderer.render: applyPostEffects расположен раньше guiRenderer.render.

160 компиляций vsh/fsh штатным ShaderC из LWJGL 3.4.3, указанного launcher manifest
Java 26.3: OpenGL/Vulkan, GUI/world/see-through/grayscale/background и OIT phases.
Все завершились успешно.

Offscreen OpenGL (Mesa llvmpipe): 24 рендера курсора, включая центр, края, pitch 89,
разворот +/-179, три размера атласа 256/512/1024. Курсор не растягивался на весь экран,
служебная рамка не появлялась; положение соответствовало формуле и clamp.
24 попиксельных сравнения обычного текста с исходным ванильным шейдером совпали.
11 непустых рендеров элементов исходного HUD (rect/image/text) тоже совпали пиксель
в пиксель, включая чётные/нечётные маркеры, субшаги, RGB565 и tint.
Проверены ссылки/размеры всех font providers, сохранность альфы текстовых листов,
JSON, содержимое ZIP и отсутствие backup-файлов.

Полный Minecraft-клиент/сервер с этим датапаком не запускался. Проверка ShaderC и
offscreen GPU не заменяет игровую проверку команды summon, слоя title, third person,
конкретного драйвера и производительности. Нельзя обещать отсутствие всех артефактов
на любом устройстве без такого запуска. Тестовый datapack — пример интеграции,
а не готовый плагин кнопок.

Отчёты находятся в integration/qa. Итоговые шейдеры и текстуры открыты для правки.

ПЕРВОИСТОЧНИКИ
Ваши HUD-proto-RP-26.3-v229.zip и voidrp-ui-source (1).tar.
Mojang Java 26.3: https://www.minecraft.net/en-us/article/minecraft-java-edition-26-3
Официальный client.jar 26.3, его version.json, текстовые shaders и классы рендера.
Paper display API: https://docs.papermc.io/paper/dev/display-entities/
