← Back to documentation

Server documentation

QuantumHy

Active

Hytale • Version 0.2.3

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

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


Обзор

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

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


Установка

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

Команды

/q status
/q help

Алиасы: /quantumhy, /qhy. /q status это диагностика только для чтения. Публичной /q perf нет.


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

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

  1. Замер плотности (иногда пропускается). Считает сущности в диске densityScanChunkRadius чанков (dx²+dz² ≤ r²). Обход 49 колонок пропускается на первом проходе, в полёте (2+ чанка/проход), при стриминге, при попадании в кэш того же чанка и пока уже на минимуме с замороженным expand.
  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 отдельный: единый серверный множитель на LOD-куллинг движка, применяемый при запуске и восстанавливаемый при выключении.


Настройка

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

КлючПо умолчаниюЧто делает
enabledtrueГлавный выключатель. При false QuantumHy не трогает ни один радиус обзора.
verboseLogfalseЛогирует каждый проход с плотностью и решением по обзору каждого игрока. Выкл. на новой установке.
checkForUpdatestrueПри старте читает страницу QuantumHy и уведомляет операторов или durkz.quantumhy.admin, если указан более новый JAR.
tickIntervalSeconds5Как часто он перепроверяет каждого игрока.
initialDelaySeconds20Ждать столько после старта до первого прохода.
targetClientViewRadius0Жёсткий потолок в чанках. 0 означает без потолка, только адаптация по плотности.
minClientViewRadius6Никогда не опускать никого ниже этого радиуса в чанках.
maxClientViewRadius32Потолок для жёсткого лимита (собственный радиус обзора игрока всё равно выигрывает).
densityScanChunkRadius4Сколько чанков в каждую сторону считать сущности.
densityLowPerChunk1.0Взвешенных сущностей на чанк на этом уровне или ниже: без shrink по плотности.
densityHighPerChunk4.0Взвешенных сущностей на чанк на этом уровне или выше: опускается до минимума.
densityRingWeightingtrueЦентральные чанки считаются полностью, внешние кольца меньше.
densityRingEdgeWeight0.55Вес на внешнем кольце (1.0 = плоский подсчёт).
baselineShrinkFraction0.10Минимальный shrink даже при «открытой» плотности (0 = выкл.).
chunkLoadShrinkEnabledtrueДополнительный shrink по числу загруженных + стримящихся sections.
chunkLoadLowChunks700Sections loaded+loading на этом уровне или ниже: без shrink по chunk-load.
chunkLoadHighChunks1550На этом числе sections или выше: shrink по chunk-load на максимуме.
densitySmoothing0.4Вес новейшей выборки в EMA, в (0, 1]. 1.0 отключает.
adaptEntityRadiustrueТакже уменьшать радиус стриминга сущностей по игроку, не только чанки.
minEntityViewBlocks48Нижняя граница радиуса сущностей, в блоках (16 блоков = 1 чанк).
entityLodAggressiveness2.0Глобальный LOD-куллинг сущностей. 1.0 это значение движка.
maxEntityVerticalDistance32Отбрасывать сущности слишком далеко выше/ниже игрока. 0 = выкл.
maxVisibleEntitiesPerPlayer80Потолок стримящихся сущностей на игрока в толпе. 0 = выкл.
holdSpawnOnLoadingChunkstrueПауза окружающего спавна, пока у любого игрока есть 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).
leanCoreTakeovertrueЕсли LeanCore установлен, перехватить у него радиус обзора.
yieldToLeanCoreViewRadiusfalseПолностью оставить радиус обзора клиента за LeanCore.
pressureGovernorEnabledtrueСжимать рычаги рендера, когда MSPT мира остаётся высоким.
pressureMsptEnter48Среднее MSPT за 10 с на этом уровне или выше входит в pressure.
pressureMsptExit43MSPT на этом уровне или ниже выходит из pressure.
pressureSustainSeconds4Сколько MSPT должен оставаться высоким до сжатия.
pressureCooldownSeconds15Сколько MSPT должен оставаться низким до восстановления.
pressureDensityMultiplier1.45Под давлением пороги плотности сжимаются на этот множитель.
pressureChunkRateMultiplier0.75Под давлением умножает потолки стриминга чанков.
pressureLodMultiplier1.15Под давлением дополнительный LOD-куллинг сущностей.
pressureVerticalTrimBlocks8Под давлением вычитает из maxEntityVerticalDistance.
pressureWorldLeversfalseПод давлением пауза спавна NPC и тика блоков (восстанавливается при выходе).
pressureTrimClientEffectstrueПод давлением обрезает bloom/sunshaft (откладывается, если последний тик — hitch).
pressureEffectScale0.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.

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

  1. Запустите сервер и найдите строку 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
  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