Документация сервера
QuantumHy
АктивныйHytale • Version 0.4.0
Установка, ключи конфига, адаптивный радиус чанков и сущностей, заморозка expand, губернатор давления и совместимость с LeanCore на Hytale 0.7.
Установка, настройка и поведение QuantumHy во время работы.
Обзор
QuantumHy это серверный мод для FPS в Hytale 0.7. Клиент нативный и не моддится, но сервер решает, сколько каждому клиенту приходится отрисовывать, поэтому QuantumHy урезает это по каждому игроку. Каждые несколько секунд он замеряет плотность сущностей вокруг игрока, сглаживает её и уменьшает радиус обзора в чанках и радиус стриминга сущностей. Каждый игрок может включить или отключить оптимизацию для себя, не меняя её для остальных.
Он никогда не раздувает обзор дальше того, что запросил игрок. Радиус не возвращается в момент, когда плотность кажется открытой: expand заморожен, пока нагрузка не спокойна, диск плотности не загружен хотя бы наполовину, игрок не летит и мир не под давлением MSPT. Он помогает только там, где установлен, и никогда на удалённом сервере, к которому вы просто подключаетесь.
Установка
- Скачайте QuantumHy-0.4.0.jar на вкладке Files в CurseForge
- Поместите JAR в папку mods/ сервера или на Windows:
%AppData%\Hytale\UserData\Mods - Запустите сервер. Конфиг генерируется как QuantumHy.json в папке данных плагина
- Следите за серверным логом по строке setup (см. Проверка работы)
Команды
/q status
/q optimize on
/q optimize off
/q help
Алиасы: /quantumhy, /qhy. Обычный игрок видит в /q status только свой режим и последнее решение. Администраторы и консоль видят полную диагностику сервера. /q optimize on|off меняет режим только выполнившего команду игрока и сохраняет выбор по UUID.
Как это работает
Каждый проход (по умолчанию 5с) QuantumHy выполняет работу по игроку в потоке владеющего мира:
- Замер плотности (иногда пропускается). Считает сущности в диске
densityScanChunkRadiusчанков (dx²+dz² ≤ r²). Обход 49 колонок пропускается на первом проходе, в полёте (2+ чанка/проход), при стриминге, при свежем кэше того же чанка и пока уже на минимуме с замороженным expand. Кэш неподвижного игрока истекает через 15 секунд. - Сглаживание. Валидная выборка проходит через экспоненциальное скользящее среднее (
densitySmoothing). - Превращение в коэффициент урезания. Плотность использует smoothstep между
densityLowPerChunkиdensityHighPerChunk. Это сочетается со shrink по chunk-load (загруженные + загружающиеся sections) и полом baseline. Комбинированный коэффициент только увеличивает shrink, пока expand не разрешён (ratchet). - Рампа двух рычагов. Обзор в чанках движется максимум +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.
| Ключ | По умолчанию | Что делает |
|---|---|---|
enabled | true | Главный выключатель. При false QuantumHy не трогает ни один радиус обзора. |
verboseLog | false | Логирует каждый проход с плотностью и решением по обзору каждого игрока. Выкл. на новой установке. |
checkForUpdates | true | При старте читает страницу QuantumHy и уведомляет операторов или durkz.quantumhy.admin, если указан более новый JAR. |
tickIntervalSeconds | 5 | Как часто он перепроверяет каждого игрока. |
initialDelaySeconds | 20 | Ждать столько после старта до первого прохода. |
targetClientViewRadius | 0 | Жёсткий потолок в чанках. 0 означает без потолка, только адаптация по плотности. |
minClientViewRadius | 6 | Никогда не опускать никого ниже этого радиуса в чанках. |
maxClientViewRadius | 32 | Потолок для жёсткого лимита (собственный радиус обзора игрока всё равно выигрывает). |
adaptiveTerrainViewEnabled | true | Адаптирует радиус обзора ландшафта в обычной игре. |
emergencyTerrainTrimEnabled | true | Разрешает временно урезать ландшафт после устойчивой визуальной нагрузки. |
clientRenderCapEnabled | true | Ограничивает дальность отрисовки и туман клиента урезанным радиусом. Нужен перезапуск. |
clientStrainEnabled | true | Смягчает радиус и отправку чанков для отстающего клиента. Нужен перезапуск. |
clientStrainFrameLagLowMs | 25 | Задержка главного цикла клиента (мс), с которой начинает учитываться перегрузка (около 40 FPS). |
clientStrainFrameLagHighMs | 60 | Задержка, считающаяся полной перегрузкой (около 16 FPS). |
clientStrainQueueLow | 64 | Очередь пакетов клиента, с которой начинает учитываться перегрузка. |
clientStrainQueueHigh | 512 | Очередь пакетов, считающаяся полной перегрузкой. |
effectBudgetEnabled | true | Бюджет дальних частиц и 3D-звуков на игрока. Нужен перезапуск. |
effectBudgetPerSecond | 120 | Сколько дальних эффектов игрок может получить в секунду. |
effectProtectRadius | 16 | Эффекты в пределах этого числа блоков никогда не отбрасываются. |
effectSoftRadius | 48 | Когда потрачена половина бюджета, эффекты дальше этого отбрасываются первыми. |
effectMaxDistance | 0 | Жёсткая отсечка в блоках для позиционных эффектов. 0 = только бюджет. |
distantUpdateThrottleEnabled | false | Реже отправляет обновления позиции дальних сущностей. Последняя позиция всегда доходит. Нужен перезапуск. |
distantUpdateNearBlocks | 32 | Сущности ближе этого получают каждое обновление. |
distantUpdateFarBlocks | 64 | Сущности дальше этого получают каждое 4-е обновление. |
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 | 2800 | Sections loaded+loading на этом уровне или ниже: без shrink по chunk-load. Здесь же обзор останавливается в спокойной обстановке (около view 10 на 0.7). |
chunkLoadHighChunks | 5900 | На этом числе sections или выше: shrink по chunk-load на максимуме (около view 14). |
densitySmoothing | 0.4 | Вес новейшей выборки в EMA, в (0, 1]. 1.0 отключает. |
adaptEntityRadius | true | Также уменьшать радиус стриминга сущностей по игроку, не только чанки. |
minEntityViewBlocks | 48 | Нижняя граница радиуса сущностей, в блоках (16 блоков = 1 чанк). |
entityLodAggressiveness | 1.0 | Явный глобальный override LOD. 1.0 сохраняет значение движка. |
maxEntityVerticalDistance | 32 | Отбрасывать сущности слишком далеко выше/ниже игрока. 0 = выкл. |
maxVisibleEntitiesPerPlayer | 80 | Потолок стримящихся сущностей на игрока в толпе. 0 = выкл. |
holdSpawnOnLoadingChunks | false | Пауза окружающего спавна при тяжёлом 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). |
streamCatchUpEnabled | true | Временно повышает лимиты после быстрого перемещения при здоровом MSPT. |
streamCatchUpIntervalMs | 250 | Интервал лёгкого контроллера стриминга. |
streamCatchUpPerSecond | 256 | Здоровый лимит catch-up в sections за секунду. |
streamCatchUpPerTick | 12 | Здоровый лимит catch-up в sections за тик. |
streamCatchUpHoldMs | 1500 | Минимальное время catch-up после быстрого перемещения. |
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 выше 1.0. |
pressureVerticalTrimBlocks | 8 | Под давлением вычитает из maxEntityVerticalDistance. |
pressureWorldLevers | false | Под давлением пауза спавна NPC и тика блоков (восстанавливается при выходе). |
pressureTrimClientEffects | false | Под давлением обрезает bloom/sunshaft (откладывается, если последний тик был hitch). |
pressureEffectScale | 0.5 | Множитель интенсивностей эффектов, пока они обрезаны. |
pressureItemMerge | false | Под нагрузкой объединяет выброшенные предметы с большего расстояния, чтобы кучи стали меньше сущностей. Нужен перезапуск. |
pressureItemMergeRadius | 4.0 | Радиус слияния в блоках, пока это активно (по умолчанию в движке 2). |
leanCoreMemoryAware | true | С 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.
Проверка работы
- Запустите сервер и найдите строку 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 - Затем строку старта 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