Server documentation
QuantumHy
ActiveHytale • Version 0.2.3
Установка, ключи конфига, адаптивный радиус чанков и сущностей, заморозка expand, губернатор давления и совместимость с LeanCore на Hytale 0.6.
Установка, настройка и поведение QuantumHy во время работы.
Обзор
QuantumHy это серверный мод для FPS в Hytale 0.6. Клиент нативный и не моддится, но сервер решает, сколько каждому клиенту приходится отрисовывать, поэтому QuantumHy урезает это по каждому игроку. Каждые несколько секунд он замеряет плотность сущностей вокруг каждого игрока, сглаживает её и использует, чтобы уменьшить две вещи: радиус обзора в чанках у клиента и радиус стриминга сущностей по игроку. Глобальная настройка LOD сущностей вдобавок отбрасывает мелкие и дальние сущности раньше.
Он никогда не раздувает обзор дальше того, что запросил игрок. Радиус не возвращается в момент, когда плотность кажется открытой: expand заморожен, пока нагрузка не спокойна, диск плотности не загружен хотя бы наполовину, игрок не летит и мир не под давлением MSPT. Он помогает только там, где установлен, и никогда на удалённом сервере, к которому вы просто подключаетесь.
Установка
- Скачайте QuantumHy-0.2.3.jar на вкладке Files в CurseForge
- Поместите JAR в папку mods/ сервера или в одиночной игре на Windows:
%AppData%\Hytale\data\release\Mods - Запустите сервер. Конфиг генерируется как QuantumHy.json в папке данных плагина
- Следите за серверным логом по строке setup (см. Проверка работы)
Команды
/q status
/q help
Алиасы: /quantumhy, /qhy. /q status это диагностика только для чтения. Публичной /q perf нет.
Как это работает
Каждый проход (по умолчанию 5с) QuantumHy выполняет работу по игроку в потоке владеющего мира:
- Замер плотности (иногда пропускается). Считает сущности в диске
densityScanChunkRadiusчанков (dx²+dz² ≤ r²). Обход 49 колонок пропускается на первом проходе, в полёте (2+ чанка/проход), при стриминге, при попадании в кэш того же чанка и пока уже на минимуме с замороженным expand. - Сглаживание. Валидная выборка проходит через экспоненциальное скользящее среднее (
densitySmoothing). - Превращение в коэффициент урезания. Плотность использует smoothstep между
densityLowPerChunkиdensityHighPerChunk. Это сочетается со shrink по chunk-load (загруженные + загружающиеся sections) и полом baseline. Комбинированный коэффициент только увеличивает shrink, пока expand не разрешён (ratchet). - Рампа двух рычагов. Обзор в чанках движется максимум +1 / −2 за проход (−4 под давлением). Радиус сущностей использует тот же коэффициент; при полном shrink (
[min]) падает доminEntityViewBlocksза одну запись. Записи останавливаются послеworldPassBudgetMsили во время стриминга.
Expand разрешён только после expandHysteresisPasses спокойных проходов по нагрузке, диска плотности ≥ 50% загруженного, без стриминга, без быстрого перемещения и без давления MSPT.
entityLodAggressiveness отдельный: единый серверный множитель на LOD-куллинг движка, применяемый при запуске и восстанавливаемый при выключении.
Настройка
Файл времени работы: QuantumHy.json в папке данных плагина, создаётся при первом запуске. Новые установки получают configVersion 5.
| Ключ | По умолчанию | Что делает |
|---|---|---|
enabled | true | Главный выключатель. При false QuantumHy не трогает ни один радиус обзора. |
verboseLog | false | Логирует каждый проход с плотностью и решением по обзору каждого игрока. Выкл. на новой установке. |
checkForUpdates | true | При старте читает страницу QuantumHy и уведомляет операторов или durkz.quantumhy.admin, если указан более новый JAR. |
tickIntervalSeconds | 5 | Как часто он перепроверяет каждого игрока. |
initialDelaySeconds | 20 | Ждать столько после старта до первого прохода. |
targetClientViewRadius | 0 | Жёсткий потолок в чанках. 0 означает без потолка, только адаптация по плотности. |
minClientViewRadius | 6 | Никогда не опускать никого ниже этого радиуса в чанках. |
maxClientViewRadius | 32 | Потолок для жёсткого лимита (собственный радиус обзора игрока всё равно выигрывает). |
densityScanChunkRadius | 4 | Сколько чанков в каждую сторону считать сущности. |
densityLowPerChunk | 1.0 | Взвешенных сущностей на чанк на этом уровне или ниже: без shrink по плотности. |
densityHighPerChunk | 4.0 | Взвешенных сущностей на чанк на этом уровне или выше: опускается до минимума. |
densityRingWeighting | true | Центральные чанки считаются полностью, внешние кольца меньше. |
densityRingEdgeWeight | 0.55 | Вес на внешнем кольце (1.0 = плоский подсчёт). |
baselineShrinkFraction | 0.10 | Минимальный shrink даже при «открытой» плотности (0 = выкл.). |
chunkLoadShrinkEnabled | true | Дополнительный shrink по числу загруженных + стримящихся sections. |
chunkLoadLowChunks | 700 | Sections loaded+loading на этом уровне или ниже: без shrink по chunk-load. |
chunkLoadHighChunks | 1550 | На этом числе sections или выше: shrink по chunk-load на максимуме. |
densitySmoothing | 0.4 | Вес новейшей выборки в EMA, в (0, 1]. 1.0 отключает. |
adaptEntityRadius | true | Также уменьшать радиус стриминга сущностей по игроку, не только чанки. |
minEntityViewBlocks | 48 | Нижняя граница радиуса сущностей, в блоках (16 блоков = 1 чанк). |
entityLodAggressiveness | 2.0 | Глобальный LOD-куллинг сущностей. 1.0 это значение движка. |
maxEntityVerticalDistance | 32 | Отбрасывать сущности слишком далеко выше/ниже игрока. 0 = выкл. |
maxVisibleEntitiesPerPlayer | 80 | Потолок стримящихся сущностей на игрока в толпе. 0 = выкл. |
holdSpawnOnLoadingChunks | true | Пауза окружающего спавна, пока у любого игрока есть backlog sections. |
minViewRadiusDelta | 2 | Минимальное изменение (чанки) перед отправкой обновления. Рамповые +1 expand всё равно применяются. |
maxExpandChunksPerPass | 1 | Максимум чанков, на который радиус обзора растёт за проход. |
maxShrinkChunksPerPass | 2 | Максимум, на который падает за проход (удваивается под давлением). |
maxExpandEntityBlocksPerPass | 16 | Максимум блоков, на который радиус сущностей растёт за проход. |
expandHysteresisPasses | 2 | Спокойных проходов, требуемых до разрешения expand. |
worldPassBudgetMs | 8 | Бюджет настенных часов на запись радиусов в потоке мира. 0 отключает. |
pressureExitRequiresLastTick | true | Pressure выходит, только когда спокойны и среднее за 10 с, и последний тик. |
respectStreamingGrace | true | Удерживать урезание, пока игрок ещё стримит sections. |
streamingBacklogThreshold | 80 | Сколько загружающихся sections считается «ещё стримит». |
smoothChunkStreaming | true | Ограничивает скорость, с которой sections приходят каждому управляемому клиенту. |
maxChunksPerSecond | 128 | Потолок sections в секунду. 0 оставляет значение движка. |
maxChunksPerTick | 8 | Потолок sections за тик (у движка 40 на 0.6). |
leanCoreTakeover | true | Если LeanCore установлен, перехватить у него радиус обзора. |
yieldToLeanCoreViewRadius | false | Полностью оставить радиус обзора клиента за LeanCore. |
pressureGovernorEnabled | true | Сжимать рычаги рендера, когда MSPT мира остаётся высоким. |
pressureMsptEnter | 48 | Среднее MSPT за 10 с на этом уровне или выше входит в pressure. |
pressureMsptExit | 43 | MSPT на этом уровне или ниже выходит из pressure. |
pressureSustainSeconds | 4 | Сколько MSPT должен оставаться высоким до сжатия. |
pressureCooldownSeconds | 15 | Сколько MSPT должен оставаться низким до восстановления. |
pressureDensityMultiplier | 1.45 | Под давлением пороги плотности сжимаются на этот множитель. |
pressureChunkRateMultiplier | 0.75 | Под давлением умножает потолки стриминга чанков. |
pressureLodMultiplier | 1.15 | Под давлением дополнительный LOD-куллинг сущностей. |
pressureVerticalTrimBlocks | 8 | Под давлением вычитает из maxEntityVerticalDistance. |
pressureWorldLevers | false | Под давлением пауза спавна NPC и тика блоков (восстанавливается при выходе). |
pressureTrimClientEffects | true | Под давлением обрезает bloom/sunshaft (откладывается, если последний тик — hitch). |
pressureEffectScale | 0.5 | Множитель интенсивностей эффектов, пока они обрезаны. |
Права
| Право | Кто |
|---|---|
durkz.quantumhy.admin | Внутриигровые уведомления об обновлении. Операторы сервера наследуют это через *. |
Запуск вместе с LeanCore
QuantumHy и LeanCore оба могут задавать радиус обзора клиента, а должен только один. По умолчанию QuantumHy берёт его на себя: при запуске он обнаруживает LeanCore и отключает управление радиусом обзора у LeanCore (viewRadiusGovernanceEnabled, liteViewRadiusEnabled, motionViewRadiusBoostEnabled), а затем сам ведёт радиус. LeanCore сохраняет радиус симуляции, пропускную способность чанков и память. Никаких изменений конфига ни на одной из сторон не нужно. LeanCore это необязательная зависимость: когда его нет, QuantumHy просто работает самостоятельно.
leanCoreTakeover: falseоставляет LeanCore в покое. Тогда оба могут спорить за радиус обзора.yieldToLeanCoreViewRadius: trueзаставляет QuantumHy полностью держаться в стороне от радиуса обзора клиента и оставляет его за LeanCore.
Рекомендации
- Одиночный или ваш собственный сервер: оставьте значения по умолчанию. Дальность обзора теряется только когда реально людно или мир hitchит.
- Хотите FPS везде: установите
targetClientViewRadiusна 12-16, чтобы ограничить дальность обзора даже на открытом пространстве. - Фермы мобов / тяжёлые ивенты: держите
adaptEntityRadius: true; именно это удерживает кадры, когда на экране сотни сущностей. - Включайте
verboseLogтолько для диагностики; по умолчанию он выключен. - Оставляйте
checkForUpdatesвключённым. Выключите, если операторам не нужно уведомление о новом JAR.
Проверка работы
- Запустите сервер и найдите строку setup:
QuantumHy 0.2.3 setup. config: verboseLog=false tickInterval=5s ... densityLow=1.0/ch densityHigh=4.0/ch baseline=10% ... entityLod=2.00x ... expand=1 shrink=2 ... budget=8ms - Затем строку старта runtime:
QuantumHy runtime started (interval=5s, hardCap=0, min=6, max=32, scan=4, entityRadius=true). - Если LeanCore присутствует:
LeanCore detected: took over the client view radius (governance turned off).Иначе:LeanCore not detected after 3 checks: QuantumHy owns the client view radius standalone. - При
verboseLog=trueкаждый проход логирует одну строку на игрока. Чтение:Durkz_z 32/49ch 0.7/ch~0.5 cl 6=6 ent 48=48 [hold]означает 32 сущности в 49 чанках, обзор в чанках удерживается на 6, радиус сущностей 48 блоков, expand заморожен (hold). Другие частые причины:[min],[pressure],[baseline],[chunk-load],[density]. - Радиус не прыгает 6→13 за один проход. Под давлением или в полёте вы должны видеть
[pressure]или[hold], а не6->7 [baseline].
Лицензия
Лицензия MIT