← К документации

Документация сервера

QuantumHy

Активный

Hytale • Version 0.4.0

Установка, ключи конфига, адаптивный радиус чанков и сущностей, заморозка expand, губернатор давления и совместимость с LeanCore на Hytale 0.7.

Установка, настройка и поведение QuantumHy во время работы.


Обзор

QuantumHy это серверный мод для FPS в Hytale 0.7. Клиент нативный и не моддится, но сервер решает, сколько каждому клиенту приходится отрисовывать, поэтому QuantumHy урезает это по каждому игроку. Каждые несколько секунд он замеряет плотность сущностей вокруг игрока, сглаживает её и уменьшает радиус обзора в чанках и радиус стриминга сущностей. Каждый игрок может включить или отключить оптимизацию для себя, не меняя её для остальных.

Он никогда не раздувает обзор дальше того, что запросил игрок. Радиус не возвращается в момент, когда плотность кажется открытой: expand заморожен, пока нагрузка не спокойна, диск плотности не загружен хотя бы наполовину, игрок не летит и мир не под давлением MSPT. Он помогает только там, где установлен, и никогда на удалённом сервере, к которому вы просто подключаетесь.


Установка

  1. Скачайте QuantumHy-0.4.0.jar на вкладке Files в CurseForge
  2. Поместите JAR в папку mods/ сервера или на Windows: %AppData%\Hytale\UserData\Mods
  3. Запустите сервер. Конфиг генерируется как QuantumHy.json в папке данных плагина
  4. Следите за серверным логом по строке setup (см. Проверка работы)

Команды

/q status
/q optimize on
/q optimize off
/q help

Алиасы: /quantumhy, /qhy. Обычный игрок видит в /q status только свой режим и последнее решение. Администраторы и консоль видят полную диагностику сервера. /q optimize on|off меняет режим только выполнившего команду игрока и сохраняет выбор по UUID.


Как это работает

Каждый проход (по умолчанию 5с) QuantumHy выполняет работу по игроку в потоке владеющего мира:

  1. Замер плотности (иногда пропускается). Считает сущности в диске densityScanChunkRadius чанков (dx²+dz² ≤ r²). Обход 49 колонок пропускается на первом проходе, в полёте (2+ чанка/проход), при стриминге, при свежем кэше того же чанка и пока уже на минимуме с замороженным expand. Кэш неподвижного игрока истекает через 15 секунд.
  2. Сглаживание. Валидная выборка проходит через экспоненциальное скользящее среднее (densitySmoothing).
  3. Превращение в коэффициент урезания. Плотность использует smoothstep между densityLowPerChunk и densityHighPerChunk. Это сочетается со shrink по chunk-load (загруженные + загружающиеся sections) и полом baseline. Комбинированный коэффициент только увеличивает shrink, пока expand не разрешён (ratchet).
  4. Рампа двух рычагов. Обзор в чанках движется максимум +1 / −2 за проход (−4 под давлением). Радиус сущностей использует тот же коэффициент; при полном shrink ([min]) падает до minEntityViewBlocks за одну запись. Записи останавливаются после worldPassBudgetMs или во время стриминга.

Expand разрешён только после expandHysteresisPasses спокойных проходов по нагрузке, диска плотности ≥ 50% загруженного, без стриминга, без быстрого перемещения и без давления MSPT.

entityLodAggressiveness это отдельная глобальная настройка. Значение 1.0 сохраняет LOD движка. Значения выше 1.0 считаются явным override администратора, и только тогда давление MSPT применяет pressureLodMultiplier.


Настройка

Файлы времени работы: QuantumHy.json и PlayerPreferences.json в папке данных плагина, создаются при первом запуске. Новые установки получают configVersion 8.

КлючПо умолчаниюЧто делает
enabledtrueГлавный выключатель. При false QuantumHy не трогает ни один радиус обзора.
verboseLogfalseЛогирует каждый проход с плотностью и решением по обзору каждого игрока. Выкл. на новой установке.
checkForUpdatestrueПри старте читает страницу QuantumHy и уведомляет операторов или durkz.quantumhy.admin, если указан более новый JAR.
tickIntervalSeconds5Как часто он перепроверяет каждого игрока.
initialDelaySeconds20Ждать столько после старта до первого прохода.
targetClientViewRadius0Жёсткий потолок в чанках. 0 означает без потолка, только адаптация по плотности.
minClientViewRadius6Никогда не опускать никого ниже этого радиуса в чанках.
maxClientViewRadius32Потолок для жёсткого лимита (собственный радиус обзора игрока всё равно выигрывает).
adaptiveTerrainViewEnabledtrueАдаптирует радиус обзора ландшафта в обычной игре.
emergencyTerrainTrimEnabledtrueРазрешает временно урезать ландшафт после устойчивой визуальной нагрузки.
clientRenderCapEnabledtrueОграничивает дальность отрисовки и туман клиента урезанным радиусом. Нужен перезапуск.
clientStrainEnabledtrueСмягчает радиус и отправку чанков для отстающего клиента. Нужен перезапуск.
clientStrainFrameLagLowMs25Задержка главного цикла клиента (мс), с которой начинает учитываться перегрузка (около 40 FPS).
clientStrainFrameLagHighMs60Задержка, считающаяся полной перегрузкой (около 16 FPS).
clientStrainQueueLow64Очередь пакетов клиента, с которой начинает учитываться перегрузка.
clientStrainQueueHigh512Очередь пакетов, считающаяся полной перегрузкой.
effectBudgetEnabledtrueБюджет дальних частиц и 3D-звуков на игрока. Нужен перезапуск.
effectBudgetPerSecond120Сколько дальних эффектов игрок может получить в секунду.
effectProtectRadius16Эффекты в пределах этого числа блоков никогда не отбрасываются.
effectSoftRadius48Когда потрачена половина бюджета, эффекты дальше этого отбрасываются первыми.
effectMaxDistance0Жёсткая отсечка в блоках для позиционных эффектов. 0 = только бюджет.
distantUpdateThrottleEnabledfalseРеже отправляет обновления позиции дальних сущностей. Последняя позиция всегда доходит. Нужен перезапуск.
distantUpdateNearBlocks32Сущности ближе этого получают каждое обновление.
distantUpdateFarBlocks64Сущности дальше этого получают каждое 4-е обновление.
densityScanChunkRadius4Сколько чанков в каждую сторону считать сущности.
densityLowPerChunk1.0Взвешенных сущностей на чанк на этом уровне или ниже: без shrink по плотности.
densityHighPerChunk4.0Взвешенных сущностей на чанк на этом уровне или выше: опускается до минимума.
densityRingWeightingtrueЦентральные чанки считаются полностью, внешние кольца меньше.
densityRingEdgeWeight0.55Вес на внешнем кольце (1.0 = плоский подсчёт).
baselineShrinkFraction0.10Минимальный shrink даже при «открытой» плотности (0 = выкл.).
chunkLoadShrinkEnabledtrueДополнительный shrink по числу загруженных + стримящихся sections.
chunkLoadLowChunks2800Sections loaded+loading на этом уровне или ниже: без shrink по chunk-load. Здесь же обзор останавливается в спокойной обстановке (около view 10 на 0.7).
chunkLoadHighChunks5900На этом числе sections или выше: shrink по chunk-load на максимуме (около view 14).
densitySmoothing0.4Вес новейшей выборки в EMA, в (0, 1]. 1.0 отключает.
adaptEntityRadiustrueТакже уменьшать радиус стриминга сущностей по игроку, не только чанки.
minEntityViewBlocks48Нижняя граница радиуса сущностей, в блоках (16 блоков = 1 чанк).
entityLodAggressiveness1.0Явный глобальный override LOD. 1.0 сохраняет значение движка.
maxEntityVerticalDistance32Отбрасывать сущности слишком далеко выше/ниже игрока. 0 = выкл.
maxVisibleEntitiesPerPlayer80Потолок стримящихся сущностей на игрока в толпе. 0 = выкл.
holdSpawnOnLoadingChunksfalseПауза окружающего спавна при тяжёлом backlog sections. Глобальная настройка администратора.
minViewRadiusDelta2Минимальное изменение (чанки) перед отправкой обновления. Рамповые +1 expand всё равно применяются.
maxExpandChunksPerPass1Максимум чанков, на который радиус обзора растёт за проход.
maxShrinkChunksPerPass2Максимум, на который падает за проход (удваивается под давлением).
maxExpandEntityBlocksPerPass16Максимум блоков, на который радиус сущностей растёт за проход.
expandHysteresisPasses2Спокойных проходов, требуемых до разрешения expand.
worldPassBudgetMs8Бюджет настенных часов на запись радиусов в потоке мира. 0 отключает.
pressureExitRequiresLastTicktruePressure выходит, только когда спокойны и среднее за 10 с, и последний тик.
respectStreamingGracetrueУдерживать урезание, пока игрок ещё стримит sections.
streamingBacklogThreshold80Сколько загружающихся sections считается «ещё стримит».
smoothChunkStreamingtrueОграничивает скорость, с которой sections приходят каждому управляемому клиенту.
maxChunksPerSecond128Потолок sections в секунду. 0 оставляет значение движка.
maxChunksPerTick8Потолок sections за тик (у движка 40 на 0.6).
streamCatchUpEnabledtrueВременно повышает лимиты после быстрого перемещения при здоровом MSPT.
streamCatchUpIntervalMs250Интервал лёгкого контроллера стриминга.
streamCatchUpPerSecond256Здоровый лимит catch-up в sections за секунду.
streamCatchUpPerTick12Здоровый лимит catch-up в sections за тик.
streamCatchUpHoldMs1500Минимальное время catch-up после быстрого перемещения.
leanCoreTakeovertrueЕсли LeanCore установлен, перехватить у него радиус обзора.
yieldToLeanCoreViewRadiusfalseПолностью оставить радиус обзора клиента за LeanCore.
pressureGovernorEnabledtrueСжимать рычаги рендера, когда MSPT мира остаётся высоким.
pressureMsptEnter48Среднее MSPT за 10 с на этом уровне или выше входит в pressure.
pressureMsptExit43MSPT на этом уровне или ниже выходит из pressure.
pressureSustainSeconds4Сколько MSPT должен оставаться высоким до сжатия.
pressureCooldownSeconds15Сколько MSPT должен оставаться низким до восстановления.
pressureDensityMultiplier1.45Под давлением пороги плотности сжимаются на этот множитель.
pressureChunkRateMultiplier0.75Под давлением умножает потолки стриминга чанков.
pressureLodMultiplier1.15Множитель давления только для явного глобального LOD выше 1.0.
pressureVerticalTrimBlocks8Под давлением вычитает из maxEntityVerticalDistance.
pressureWorldLeversfalseПод давлением пауза спавна NPC и тика блоков (восстанавливается при выходе).
pressureTrimClientEffectsfalseПод давлением обрезает bloom/sunshaft (откладывается, если последний тик был hitch).
pressureEffectScale0.5Множитель интенсивностей эффектов, пока они обрезаны.
pressureItemMergefalseПод нагрузкой объединяет выброшенные предметы с большего расстояния, чтобы кучи стали меньше сущностей. Нужен перезапуск.
pressureItemMergeRadius4.0Радиус слияния в блоках, пока это активно (по умолчанию в движке 2).
leanCoreMemoryAwaretrueС LeanCore уменьшает радиус, пока его уровень heap TIGHT или CRITICAL. Только чтение.

Права

ПравоКто
durkz.quantumhy.adminУведомления об обновлении и полный /q status. Операторы сервера наследуют это через *.

Запуск вместе с 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; именно это удерживает кадры, когда на экране сотни сущностей.
  • Личный выбор: используйте /q optimize off, чтобы восстановить и остановить все персональные рычаги для себя. /q optimize on включает их снова.
  • Включайте verboseLog только для диагностики; по умолчанию он выключен.
  • Оставляйте checkForUpdates включённым. Выключите, если операторам не нужно уведомление о новом JAR.

Проверка работы

  1. Запустите сервер и найдите строку setup: QuantumHy 0.4.0 setup. config: verboseLog=false tickInterval=5s ... densityLow=1.0/ch densityHigh=4.0/ch baseline=10% ... entityLod=1.00x ... expand=1 shrink=2 ... budget=8ms
  2. Затем строку старта runtime: QuantumHy runtime started (interval=5s, hardCap=0, min=6, max=32, scan=4, entityRadius=true).
  3. Если 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.
  4. При 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].
  5. Радиус не прыгает 6→13 за один проход. Под давлением или в полёте вы должны видеть [pressure] или [hold], а не 6->7 [baseline].

Лицензия

Лицензия MIT