Server documentation
QuantumHy
ActiveHytale • Version 0.2.3
Install, config keys, adaptive chunk and entity radius, expand freeze, pressure governor, and LeanCore coexistence for QuantumHy on Hytale 0.6.
Install, configuration, and runtime behavior for QuantumHy.
Overview
QuantumHy is a server-side FPS mod for Hytale 0.6. The client is native and cannot be modded, but the server decides how much each client has to render, so QuantumHy trims that on a per-player basis. Every few seconds it samples entity density around each player, smooths it, and uses it to shrink two things: the client chunk view radius and the per-player entity stream radius. A global entity LOD setting drops small and distant entities sooner on top of that.
It never inflates a view past what the player asked for. Radius does not snap back the moment density looks open: expand is frozen until load is calm, the density disk is at least half loaded, the player is not flying, and the world is not MSPT-pressured. It helps only where it is installed, never on a remote server you merely join.
Installation
- Download QuantumHy-0.2.3.jar from the CurseForge Files tab
- Place the JAR in your server’s mods/ folder, or on Windows solo:
%AppData%\Hytale\data\release\Mods - Start the server. Config is generated as QuantumHy.json in the plugin data folder
- Watch the server log for the setup line (see Verifying it works)
Commands
/q status
/q help
Aliases: /quantumhy, /qhy. /q status is read-only diagnostics. There is no public /q perf.
How it works
Every pass (default 5s) QuantumHy does the per-player work on the owning world’s thread:
- Sample density (sometimes skipped). It counts entities in a disk of
densityScanChunkRadiuschunks (dx²+dz² ≤ r²). The 49-column walk is skipped on the first pass, while flying (2+ chunks/pass), while streaming, on a same-chunk cache hit, and while already at the minimum with expand frozen. - Smooth it. A valid sample goes through an exponential moving average (
densitySmoothing). - Turn it into a shrink factor. Density uses a smoothstep between
densityLowPerChunkanddensityHighPerChunk. That is combined with chunk-load shrink (loaded + loading sections) and a baseline floor. The combined factor only increases shrink until expand is allowed (ratchet). - Ramp two levers. Chunk view moves at most +1 / −2 per pass (−4 under pressure). Entity stream radius uses the same factor; at full shrink (
[min]) it snaps tominEntityViewBlocksin one write. Writes stop afterworldPassBudgetMsor while streaming.
Expand is allowed only after expandHysteresisPasses calm load passes, a density disk that is at least 50% loaded, no streaming, no fast travel, and no MSPT pressure.
entityLodAggressiveness is separate: a server-wide multiplier on the engine’s entity LOD cull, applied at startup and restored on shutdown.
Configuration
Runtime file: QuantumHy.json in the plugin data folder, created on first run. New installs get configVersion 5.
| Key | Default | What it does |
|---|---|---|
enabled | true | Master switch. When false, QuantumHy never touches any view radius. |
verboseLog | false | Log every pass with each player’s density and view decision. Off on new installs. |
checkForUpdates | true | On startup, check the QuantumHy page and notify operators or durkz.quantumhy.admin if a newer JAR is listed. |
tickIntervalSeconds | 5 | How often it re-checks each player. |
initialDelaySeconds | 20 | Wait this long after start before the first pass. |
targetClientViewRadius | 0 | Hard cap in chunks. 0 means no cap, just adapt to density. |
minClientViewRadius | 6 | Never pull anyone below this chunk radius. |
maxClientViewRadius | 32 | Ceiling for the hard cap (the player’s own view radius still wins). |
densityScanChunkRadius | 4 | How many chunks each way to count entities in. |
densityLowPerChunk | 1.0 | Weighted entities per chunk at or below this: no density shrink. |
densityHighPerChunk | 4.0 | Weighted entities per chunk at or above this: pulled to the minimum. |
densityRingWeighting | true | Count center chunks fully, outer scan rings less. |
densityRingEdgeWeight | 0.55 | Ring weight at the scan edge (1.0 = flat count). |
baselineShrinkFraction | 0.10 | Minimum shrink even in “open” density (0 = off). |
chunkLoadShrinkEnabled | true | Extra shrink from loaded + streaming section count. |
chunkLoadLowChunks | 700 | Loaded + loading sections at or below this: no chunk-load shrink. |
chunkLoadHighChunks | 1550 | At or above this section count: chunk-load shrink hits full strength. |
densitySmoothing | 0.4 | Weight of the newest sample in the EMA, in (0, 1]. 1.0 is off. |
adaptEntityRadius | true | Also shrink the per-player entity stream radius, not just chunks. |
minEntityViewBlocks | 48 | Lower bound for the entity radius, in blocks (16 blocks = 1 chunk). |
entityLodAggressiveness | 2.0 | Global entity LOD cull. 1.0 is the engine default. |
maxEntityVerticalDistance | 32 | Drop entities too far above/below the player. 0 = off. |
maxVisibleEntitiesPerPlayer | 80 | Cap streamed entities per player in crowds. 0 = off. |
holdSpawnOnLoadingChunks | true | Pause environmental spawning while any player has a section-stream backlog. |
minViewRadiusDelta | 2 | Minimum change (chunks) before an update is sent. Ramped +1 expands still apply. |
maxExpandChunksPerPass | 1 | Max chunks the client view radius may increase in one pass. |
maxShrinkChunksPerPass | 2 | Max chunks it may decrease in one pass (doubled under pressure). |
maxExpandEntityBlocksPerPass | 16 | Max entity-stream blocks the radius may increase in one pass. |
expandHysteresisPasses | 2 | Calm passes required before an expand is allowed. |
worldPassBudgetMs | 8 | Wall-clock budget for radius writes on the world thread. 0 disables. |
pressureExitRequiresLastTick | true | Pressure exits only when both the 10s MSPT average and the last tick are calm. |
respectStreamingGrace | true | Hold cuts while a player is still streaming sections. |
streamingBacklogThreshold | 80 | How many loading sections counts as “still streaming”. |
smoothChunkStreaming | true | Cap how fast sections stream to each managed client. |
maxChunksPerSecond | 128 | Cap on sections streamed per second. 0 keeps the engine default. |
maxChunksPerTick | 8 | Cap on sections streamed per tick (engine default is 40 on 0.6). |
leanCoreTakeover | true | If LeanCore is installed, take the view radius over from it. |
yieldToLeanCoreViewRadius | false | Leave the client view radius entirely to LeanCore. |
pressureGovernorEnabled | true | Tighten render levers when world MSPT stays high. |
pressureMsptEnter | 48 | 10s average MSPT at or above this enters pressure mode. |
pressureMsptExit | 43 | MSPT at or below this exits pressure mode. |
pressureSustainSeconds | 4 | How long MSPT must stay high before levers tighten. |
pressureCooldownSeconds | 15 | How long MSPT must stay low before levers restore. |
pressureDensityMultiplier | 1.45 | Under pressure, density thresholds tighten by this factor. |
pressureChunkRateMultiplier | 0.75 | Under pressure, multiply chunk streaming caps. |
pressureLodMultiplier | 1.15 | Under pressure, extra entity LOD cull. |
pressureVerticalTrimBlocks | 8 | Under pressure, subtract from maxEntityVerticalDistance. |
pressureWorldLevers | false | Under pressure, pause NPC spawn and block tick (restored on release). |
pressureTrimClientEffects | true | Under pressure, trim bloom/sunshaft (deferred if last tick is a hitch). |
pressureEffectScale | 0.5 | Multiplier for client effect intensities while trimmed. |
Permissions
| Permission | Who |
|---|---|
durkz.quantumhy.admin | In-game update notices. Server operators inherit this through *. |
Running it with LeanCore
QuantumHy and LeanCore can both write the client view radius, and only one should. By default QuantumHy takes it: on startup it detects LeanCore and turns off LeanCore’s view-radius governance (viewRadiusGovernanceEnabled, liteViewRadiusEnabled, motionViewRadiusBoostEnabled), then drives the view radius itself. LeanCore keeps simulation radius, chunk throughput, and memory. No config change is needed on either side. LeanCore is an optional dependency: when it is absent, QuantumHy just runs standalone.
leanCoreTakeover: falseleaves LeanCore alone. Both may then fight over the view radius.yieldToLeanCoreViewRadius: truemakes QuantumHy stay out of the client view radius entirely and lets LeanCore keep it.
Recommended
- Solo or your own server: leave the defaults. You only lose view distance when it is actually crowded or the world is hitching.
- Want FPS everywhere: set
targetClientViewRadiusto 12 to 16 to cap view distance even in the open. - Mob farms / heavy events: keep
adaptEntityRadius: true; this is what holds frames when hundreds of entities are on screen. - Turn
verboseLogon only while diagnosing; it is off by default. - Leave
checkForUpdateson unless you do not want operators to see a newer-JAR notice.
Verifying it works
- Start the server and look for the setup line:
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 - Then the runtime start line:
QuantumHy runtime started (interval=5s, hardCap=0, min=6, max=32, scan=4, entityRadius=true). - If LeanCore is present:
LeanCore detected: took over the client view radius (governance turned off).Otherwise:LeanCore not detected after 3 checks: QuantumHy owns the client view radius standalone. - With
verboseLog=true, each pass logs one line per player. Reading it:Durkz_z 32/49ch 0.7/ch~0.5 cl 6=6 ent 48=48 [hold]means 32 entities across 49 chunks, chunk view held at 6, entity radius at 48 blocks, expand frozen (hold). Other common reasons:[min],[pressure],[baseline],[chunk-load],[density]. - Radius does not bounce 6→13 in one pass. While pressured or flying you should see
[pressure]or[hold], not6->7 [baseline].
License
MIT License