← Back to documentation

Server documentation

QuantumHy

Active

Hytale • Version 0.4.0

Install, config keys, adaptive chunk and entity radius, expand freeze, pressure governor, and LeanCore coexistence for QuantumHy on Hytale 0.7.

Install, configuration, and runtime behavior for QuantumHy.


Overview

QuantumHy is a server-side FPS mod for Hytale 0.7. 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 the client chunk view radius and per-player entity stream radius. Each player can persistently opt in or out without changing anyone else.

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.4.0.jar from the CurseForge Files tab
  2. Place the JAR in your server’s mods/ folder, or on Windows: %AppData%\Hytale\UserData\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 optimize on
/q optimize off
/q help

Aliases: /quantumhy, /qhy. A player sees only their own mode and last decision in /q status. Admins and console see full server diagnostics. /q optimize on|off changes only the player who runs it and stores that preference by UUID.


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 fresh same-chunk cache hit, and while already at the minimum with expand frozen. A stationary player’s cache expires after 15 seconds.
  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 and global. The default 1.0 leaves engine LOD unchanged. Values above 1.0 are an explicit admin override, and only then can MSPT pressure apply pressureLodMultiplier.


Configuration

Runtime files: QuantumHy.json and PlayerPreferences.json in the plugin data folder, created on first run. New installs get configVersion 8.

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).
adaptiveTerrainViewEnabledtrueAdapt terrain view radius during normal play.
emergencyTerrainTrimEnabledtrueAllow temporary terrain trim after sustained visual pressure.
clientRenderCapEnabledtrueCap the client’s draw distance and fog to the trimmed radius. Restart required.
clientStrainEnabledtrueEase the radius and chunk rate for a client that falls behind. Restart required.
clientStrainFrameLagLowMs25Client main-loop lag (ms) where strain starts counting (about 40 FPS).
clientStrainFrameLagHighMs60Lag treated as fully strained (about 16 FPS).
clientStrainQueueLow64Client packet queue where strain starts counting.
clientStrainQueueHigh512Packet queue treated as fully strained.
effectBudgetEnabledtrueBudget far particles and 3D sounds per player. Restart required.
effectBudgetPerSecond120Far effects each player may receive per second.
effectProtectRadius16Effects within this many blocks are never dropped.
effectSoftRadius48Once half the budget is spent, effects beyond this are dropped first.
effectMaxDistance0Hard cut-off in blocks for positional effects. 0 = budget only.
distantUpdateThrottleEnabledfalseSend position updates for far entities less often. The latest position always arrives. Restart required.
distantUpdateNearBlocks32Entities closer than this get every update.
distantUpdateFarBlocks64Entities beyond this get every 4th update.
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.
chunkLoadLowChunks2800Loaded + loading sections at or below this: no chunk-load shrink. Also where the view settles when calm (about view 10 on 0.7).
chunkLoadHighChunks5900At or above this section count: chunk-load shrink hits full strength (about view 14).
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).
entityLodAggressiveness1.0Explicit global entity LOD override. 1.0 keeps the engine default.
maxEntityVerticalDistance32Drop entities too far above/below the player. 0 = off.
maxVisibleEntitiesPerPlayer80Cap streamed entities per player in crowds. 0 = off.
holdSpawnOnLoadingChunksfalsePause environmental spawning during a heavy section-stream backlog. Global admin control.
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).
streamCatchUpEnabledtrueTemporarily raise managed caps after fast travel while MSPT is healthy.
streamCatchUpIntervalMs250Interval for the lightweight stream controller.
streamCatchUpPerSecond256Healthy catch-up cap in sections per second.
streamCatchUpPerTick12Healthy catch-up cap in sections per tick.
streamCatchUpHoldMs1500Minimum catch-up hold after fast movement.
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.15Pressure multiplier used only with explicit global LOD above 1.0.
pressureVerticalTrimBlocks8Under pressure, subtract from maxEntityVerticalDistance.
pressureWorldLeversfalseUnder pressure, pause NPC spawn and block tick (restored on release).
pressureTrimClientEffectsfalseUnder pressure, trim bloom/sunshaft (deferred if last tick is a hitch).
pressureEffectScale0.5Multiplier for client effect intensities while trimmed.
pressureItemMergefalseUnder pressure, merge dropped items from farther away so piles collapse into fewer entities. Restart required.
pressureItemMergeRadius4.0Merge radius in blocks while that is active (engine default is 2).
leanCoreMemoryAwaretrueWith LeanCore, tighten the radius while its heap tier is TIGHT or CRITICAL. Read-only.

Permissions

PermissionWho
durkz.quantumhy.adminIn-game update notices and full /q status. 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.
  • Personal choice: use /q optimize off to restore and stop all player-targeted levers for yourself. Use /q optimize on to re-enable them.
  • 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.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. 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