← Back to documentation

Server documentation

QuantumHy

Active

Hytale • 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

  1. Download QuantumHy-0.2.3.jar from the CurseForge Files tab
  2. Place the JAR in your server’s mods/ folder, or on Windows solo: %AppData%\Hytale\data\release\Mods
  3. Start the server. Config is generated as QuantumHy.json in the plugin data folder
  4. 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:

  1. Sample density (sometimes skipped). It counts entities in a disk of densityScanChunkRadius chunks (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.
  2. Smooth it. A valid sample goes through an exponential moving average (densitySmoothing).
  3. Turn it into a shrink factor. Density uses a smoothstep between densityLowPerChunk and densityHighPerChunk. 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).
  4. 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 to minEntityViewBlocks in one write. Writes stop after worldPassBudgetMs or 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.

KeyDefaultWhat it does
enabledtrueMaster switch. When false, QuantumHy never touches any view radius.
verboseLogfalseLog every pass with each player’s density and view decision. Off on new installs.
checkForUpdatestrueOn startup, check the QuantumHy page and notify operators or durkz.quantumhy.admin if a newer JAR is listed.
tickIntervalSeconds5How often it re-checks each player.
initialDelaySeconds20Wait this long after start before the first pass.
targetClientViewRadius0Hard cap in chunks. 0 means no cap, just adapt to density.
minClientViewRadius6Never pull anyone below this chunk radius.
maxClientViewRadius32Ceiling for the hard cap (the player’s own view radius still wins).
densityScanChunkRadius4How many chunks each way to count entities in.
densityLowPerChunk1.0Weighted entities per chunk at or below this: no density shrink.
densityHighPerChunk4.0Weighted entities per chunk at or above this: pulled to the minimum.
densityRingWeightingtrueCount center chunks fully, outer scan rings less.
densityRingEdgeWeight0.55Ring weight at the scan edge (1.0 = flat count).
baselineShrinkFraction0.10Minimum shrink even in “open” density (0 = off).
chunkLoadShrinkEnabledtrueExtra shrink from loaded + streaming section count.
chunkLoadLowChunks700Loaded + loading sections at or below this: no chunk-load shrink.
chunkLoadHighChunks1550At or above this section count: chunk-load shrink hits full strength.
densitySmoothing0.4Weight of the newest sample in the EMA, in (0, 1]. 1.0 is off.
adaptEntityRadiustrueAlso shrink the per-player entity stream radius, not just chunks.
minEntityViewBlocks48Lower bound for the entity radius, in blocks (16 blocks = 1 chunk).
entityLodAggressiveness2.0Global entity LOD cull. 1.0 is the engine default.
maxEntityVerticalDistance32Drop entities too far above/below the player. 0 = off.
maxVisibleEntitiesPerPlayer80Cap streamed entities per player in crowds. 0 = off.
holdSpawnOnLoadingChunkstruePause environmental spawning while any player has a section-stream backlog.
minViewRadiusDelta2Minimum change (chunks) before an update is sent. Ramped +1 expands still apply.
maxExpandChunksPerPass1Max chunks the client view radius may increase in one pass.
maxShrinkChunksPerPass2Max chunks it may decrease in one pass (doubled under pressure).
maxExpandEntityBlocksPerPass16Max entity-stream blocks the radius may increase in one pass.
expandHysteresisPasses2Calm passes required before an expand is allowed.
worldPassBudgetMs8Wall-clock budget for radius writes on the world thread. 0 disables.
pressureExitRequiresLastTicktruePressure exits only when both the 10s MSPT average and the last tick are calm.
respectStreamingGracetrueHold cuts while a player is still streaming sections.
streamingBacklogThreshold80How many loading sections counts as “still streaming”.
smoothChunkStreamingtrueCap how fast sections stream to each managed client.
maxChunksPerSecond128Cap on sections streamed per second. 0 keeps the engine default.
maxChunksPerTick8Cap on sections streamed per tick (engine default is 40 on 0.6).
leanCoreTakeovertrueIf LeanCore is installed, take the view radius over from it.
yieldToLeanCoreViewRadiusfalseLeave the client view radius entirely to LeanCore.
pressureGovernorEnabledtrueTighten render levers when world MSPT stays high.
pressureMsptEnter4810s average MSPT at or above this enters pressure mode.
pressureMsptExit43MSPT at or below this exits pressure mode.
pressureSustainSeconds4How long MSPT must stay high before levers tighten.
pressureCooldownSeconds15How long MSPT must stay low before levers restore.
pressureDensityMultiplier1.45Under pressure, density thresholds tighten by this factor.
pressureChunkRateMultiplier0.75Under pressure, multiply chunk streaming caps.
pressureLodMultiplier1.15Under pressure, extra entity LOD cull.
pressureVerticalTrimBlocks8Under pressure, subtract from maxEntityVerticalDistance.
pressureWorldLeversfalseUnder pressure, pause NPC spawn and block tick (restored on release).
pressureTrimClientEffectstrueUnder pressure, trim bloom/sunshaft (deferred if last tick is a hitch).
pressureEffectScale0.5Multiplier for client effect intensities while trimmed.

Permissions

PermissionWho
durkz.quantumhy.adminIn-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: false leaves LeanCore alone. Both may then fight over the view radius.
  • yieldToLeanCoreViewRadius: true makes QuantumHy stay out of the client view radius entirely and lets LeanCore keep it.

  • 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 targetClientViewRadius to 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 verboseLog on only while diagnosing; it is off by default.
  • Leave checkForUpdates on unless you do not want operators to see a newer-JAR notice.

Verifying it works

  1. 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
  2. Then the runtime start line: QuantumHy runtime started (interval=5s, hardCap=0, min=6, max=32, scan=4, entityRadius=true).
  3. 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.
  4. 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].
  5. Radius does not bounce 6→13 in one pass. While pressured or flying you should see [pressure] or [hold], not 6->7 [baseline].

License

MIT License