Skip to content

Releases: Zaldaryon/Optimum

v0.3.5

Choose a tag to compare

@Zaldaryon Zaldaryon released this 06 Aug 10:35
v0.3.5
9b967f1

🔖 v0.3.5

Optimum 0.3.5 continues to target Vintage Story 1.22.5 by default and adds experimental, opt-in support for building and installing against Vintage Story 1.22.6, ahead of Anego publishing matching open-source updates for vsapi/vsessentialsmod/vssurvivalmod.

New

  • make bootstrap VERSION=1.22.6 (and install-linux.sh --version 1.22.6, install-windows.ps1 -Version 1.22.6, install-macos.sh with a version-mismatch confirmation) builds and installs Optimum against the real 1.22.6 client. patches-1.22.6-bridge/ reconstructs the confirmed 1.22.6 source-level changes for the three affected fork repos (vsapi, vsessentialsmod, vssurvivalmod) on top of the pinned 1.22.5 refs, plus a one-line version-constant bump (vscreativemod and Cairo need no bridge, confirmed byte-identical to 1.22.6 at the decompiled level). The closed-source engine (VintagestoryLib/Vintagestory) needs no bridging at all: bootstrap.sh/bootstrap.ps1 decompile it fresh from whichever client archive --version/-Version downloads, so it's already 1.22.6-shaped the moment decompilation finishes.
  • install-linux.sh prompts for the Vintage Story version interactively when a patches--bridge/ directory offers an alternate to the pinned default, and shows the chosen version in the install summary.
  • install-macos.sh (which overlays Optimum's compiled DLLs onto an existing local Vintage Story install rather than downloading one) now detects a version mismatch between that local install and what Optimum was built for, and asks for confirmation before installing a mismatched build instead of doing so silently.
  • install-windows.ps1 gained a -Version parameter, threaded through to bootstrap.ps1 and the version-requirement check that previously only accepted the exact version pinned in forks.json with no override. Both the GUI and the headless path now also auto-detect: without an explicit -Version, they build against whichever supported version (pinned or bridge-patched) the locally installed Vintage Story actually is, matching install-linux.sh's existing auto-detection instead of requiring an exact match to the pinned default.
  • docs/vintage-story-version-updates.md documents both ways to handle a new Vintage Story release going forward, in order of preference: pin real upstream source once Anego publishes it (always try this first), or bridge-patch from the compiled client as a temporary stopgap (this release's 1.22.6 support).

Fixes

  • bootstrap.sh/bootstrap.ps1 no longer silently reuse a stale .vanilla/win-x64 client cached from a previous --version/-Version; the extracted client's own version marker is now checked before reuse, and a mismatch triggers a clean re-extraction.
  • package-linux.sh/package-macos.sh had the same stale-cache bug in their own separate per-platform .vanilla caches, with a more serious effect: packaging for a new version after a prior version's package run silently grafted Optimum's patches onto the old version's vanilla VintagestoryLib.dll as the Cecil transplant donor, shipping a client whose engine IL didn't match the version its compiled mod-API assemblies expected. Both scripts now re-extract on a version-marker mismatch, matching the fix already applied to bootstrap.sh.
  • check-vanilla-compat.sh no longer asserts a hardcoded game-version string; it now reads the actually-extracted client's own version marker.
  • bootstrap.sh's upstream-bridge directory lookup is generic (patches--bridge/) instead of hardcoding 1.22.6, matching a new equivalent implementation added to bootstrap.ps1 (which previously had no bridge-patch support at all - a Windows -Version build of a bridged version would have silently built unpatched, mismatched source).
  • install-windows.ps1 silently dropped the real error when the runtime donor build (VSEssentials/VSSurvivalMod) failed, showing only a generic "Runtime donor build failed" message with no compiler output to diagnose it. The install script now streams that output into the log as it happens instead of buffering it until after the (failed) call returns, so the actual dotnet build error is visible.
  • Installing to a drive root (C:\Optimum, D:\Optimum) failed at the final cleanup step with "The path is not of a legal form". PowerShell 5.1's Split-Path -Parent strips the trailing backslash from drive roots, turning the parent path into a relative path that Join-Path/New-Item/Move-Item reject. Install-StagedPackage now normalizes that path back to an absolute one, with a regression test covering it.
  • prepare-runtime-donors.ps1/.sh wrote the user's Vintage Story install path straight into generated XML for the VSEssentials/VSSurvivalMod runtime donors. An install path containing & (e.g. "C:\Modding & Games...") produced invalid XML, which MSBuild reported as MSB4025 "error occurred while parsing EntityName" and failed the runtime donor build. Both scripts now XML-escape &, <, > in every path written into generated project files.
  • A macOS bootstrap downloaded the client archive, then failed on the next line (VintagestoryLib.dll: No such file) because the macOS tarball roots at "Vintage Story.app" instead of "vintagestory" like the Windows/Linux archives. extract_archive now normalises a single extracted root to vintagestory when that directory isn't already present. (#13)
  • curl wrote the client and innounp downloads straight to their cache paths, so an interrupted download left a short file that the reuse check only asks whether exists - the next run reported "Using cached" and failed in tar/innounp instead, with nothing pointing at the download. Both downloads now write to a .partial path and move into place only on success; bootstrap.sh also verifies a cached archive reads end to end before trusting it. (#14)

Community contributions

Thanks to @dizzyd for both fixes above:

  • #13 - macOS bootstrap archive-root fix
  • #14 - atomic client/innounp download, fixing a poisoned-cache bug

Validation

Verified end-to-end on Linux: make bootstrap VERSION=1.22.6 && dotnet build succeeds against the real downloaded 1.22.6 client (95/95 patches applied, 0 build errors, 0 warnings). The packaged install-linux.sh output launches, reaches the login screen with no crash, and completed a real online session (server validation, joined a public multiplayer server, exchanged chat, disconnected cleanly) with no exceptions in client-debug.log or server-debug.log.

Windows and macOS builds are implemented and syntax-validated (pwsh-parsed, bash -n-checked) but not yet retested on those platforms - no Windows or macOS host was available to run them end to end this session.

1.22.5 continues to build and install exactly as before this release (VERSION defaults to forks.json's pinned value).

v0.3.4

Choose a tag to compare

@Zaldaryon Zaldaryon released this 04 Aug 12:39
v0.3.4
3ea6272

Fixes

  • Restored the missing unified-diff header in SystemRenderOITLayers.cs.patch.
  • Added patch-syntax validation before bootstrap applies patches.
  • The launcher exits before game startup when a required patch, assembly validation, or JIT preflight fails.

Notes

  • Targets Vintage Story 1.22.5.
  • Source-only release. See the wiki for install instructions.

v0.3.3

Choose a tag to compare

@Zaldaryon Zaldaryon released this 03 Aug 10:39
v0.3.3
34249da

Fixes

  • Added guards to SystemRenderOITLayers and GearRenderer for missing render resources, meshes, shaders, callbacks, and state.
  • Added null-safe player head animation setup and pose lookup.
  • Added dependency closure for injected helpers, complete method signatures, IL stack validation, and strict manifest checks.
  • Added cache hashes, temporary writes, path checks, locks, timeouts, and rollback handling. Failed patching stops before Vintagestory.exe starts.
  • Added Optimum.exe --validate-only with assembly loading, reflection, and JIT preflight.
  • Hardened the Windows installer with package completion checks, runtime preflight, temporary installation swaps, and rollback.
  • Accepted stable four-part ilspycmd versions from 10.1.0.8386 through 10.1.1.8388, inclusive. The build prefers 10.1.1.8388.
  • Unified LF normalization across Bash and PowerShell bootstrap paths.
  • Added the standalone Windows uninstaller and kept the original Vintage Story installation untouched.

Notes

  • Targets Vintage Story 1.22.5.
  • Source-only release. See the wiki for install instructions.

v0.3.2

Choose a tag to compare

@Zaldaryon Zaldaryon released this 31 Jul 21:35
v0.3.2
2292954

Fixes

  • Prospecting pick node search silently did nothing. Node Search Mode never printed "no ore nearby" or any quantity result (Density Search Mode still worked). Two fields added for the node-search optimization had no initializer run under the runtime patcher, so the first lookup threw before any chat message could be sent. Fixed by lazily initializing on first use.
  • Animation lookups allocated a string every frame. AnimatorBase.animsByCode used the default ordinal comparer in the shipped API assembly, so every animated entity's animation-state lookup lowercased its animation code on every call. The source-tree fix existed but had no Cecil target and never reached players; it now ships via a dedicated API patch.
  • A missing Cecil type target could fall an install back to vanilla. Optimum.OptimumOptiTimeGuard was absent from the engine's type-injection list, so any install exercising GetMigrationMessage() failed self-consistency verification.
  • The version string stuck at 0.3.0/0.3.1 across releases.

Performance (opt-in, default off)

Dressed NPCs (traders, villagers) re-tesselating their shape and gear could cost 50-230ms in a single frame, most visible when several load in at once (a caravan arriving, entering a village). Four settings target this, configurable only via ModConfig/optimum.json for now:

  • EntityTesselationFrameBudget: caps how many dressed-entity re-tesselations run per frame, spreading the rest across following frames.
  • EntityOutfitShapeCache: reuses the fully assembled gear shape and resolved textures for outfit combinations already built once.
  • EntityOutfitAnimatorCache: reuses the built animator (pose graph) across entities sharing an outfit combination instead of rebuilding it every re-tesselation - the largest remaining cost in this path.
  • EntityOutfitTexturePrewarm: inserts every outfit variant's textures into the atlas during the loading screen instead of on first encounter mid-gameplay.

Measured via .optimum stutterwatch, together these reduced per-call cost from 58-230ms down to 7-9ms in real gameplay testing.

Diagnostics

  • New .optimum stutterwatch <ms> command attributes per-frame cost to Optimum's own subsystems, complementing vanilla's .debug logticks.

Notes

  • Targets Vintage Story 1.22.5.
  • Source-only release. See the wiki for install instructions.

v0.3.1

Choose a tag to compare

@Zaldaryon Zaldaryon released this 31 Jul 01:08
v0.3.1
53834c4

Fixes

  • Runtime donor build fails during install when ILSpy generates self-closing <Reference> elements without <HintPath>. MSBuild cannot resolve assemblies like Newtonsoft.Json from a bare <Reference Include="Newtonsoft.Json" />. Added Resolve-ProjectReferences/resolve_references to both the PowerShell and bash donor scripts. A two-pass strategy expands self-closing references (finds DLLs in the vanilla Lib/, root, and Mods/ directories) and replaces invalid relative HintPaths with correct absolute paths from the user's local installation.
  • <LangVersion> hardcoded to 15.0. ILSpy changes the emitted version number across releases. The regex now matches any X.Y version.
  • macOS bash 3.2 compatibility. set -o pipefail, sort -z, and find -quit are GNU extensions unavailable on macOS's bundled bash and BSD find. All three now have conditional fallbacks.
  • PowerShell 5.1 compatibility. $IsWindows is PS 6+ only; the fallback path now probes for both ilspycmd and ilspycmd.exe. Native build commands use Invoke-NativeStep (from _exec.ps1) to prevent stderr lines from becoming terminating errors under $ErrorActionPreference = 'Stop' (PowerShell/PowerShell#4002).
  • Missing reference-path directories are now reported. Vanilla Lib/, root, and Mods/ directories are checked for existence before being passed to ilspycmd --referencepath. Missing directories emit a warning instead of silently being skipped.
  • Build step tries all donors before failing. If one donor (VSEssentials or VSSurvivalMod) fails to build, the script now attempts the other and reports all failures at the end.

v0.3.0

Choose a tag to compare

@Zaldaryon Zaldaryon released this 30 Jul 22:40
v0.3.0
447a765

New

  • Optimum is now a launcher, not a pre-patched game. 0.2.x shipped complete optimized assemblies. 0.3.0 ships Optimum.exe (the launcher), Optimum.Patcher.dll (Cecil), and runtime "donor" DLLs, and patches copies of the game's own assemblies at launch. Four shipping paths carry the changes: an engine Cecil transplant into VintagestoryLib.dll (4 injected types, 52 method transplants, 1 IL hook), an ABI-safe API patch into VintagestoryAPI.dll, runtime donor manifests for VSEssentials.dll and VSSurvivalMod.dll, and an asset overlay for the optimized shaders and the Optimum language strings. Vanilla files on disk are never modified.
  • Patch results are cached and validated per launch. First launch (or the first launch after a Vintage Story or Optimum update) applies the patches and writes them to .optimum/cache/; every launch after that validates the cache and loads it. If any patch step fails, the launcher falls back to a vanilla launch instead of leaving a half-patched install.
  • Branded patch splash screen. The cache-miss path now shows a small window styled after the vanilla GuiScreenLoadingGame (same font family, colour, and size), updated per patch target, so the first launch reads as one continuous loading sequence instead of a console flash. It is a core-profile GL 3.3 renderer with a logging GLFW error callback, so a headless host, a Wayland compositor rejecting window positioning, or an unsupported driver degrades to log-only and never blocks patching.
  • No more console window. The launcher builds as WinExe and writes every diagnostic line to {dataPath}/Logs/optimum-launcher.log (truncated per run) instead of holding a console open for the whole session.
  • Optimum window identity. The client window title is Optimum, the window icon is set from the Optimum-branded gameicon.png at window creation (rather than relying on WM_CLASS resolution, which OpenTK's bundled build cannot set), and GameVersion.LongGameVersion carries a + Optimum v0.3.0 suffix on Windows, Linux and macOS.
  • Vintage Story 1.22.5. All patches were regenerated against the 1.22.5 baseline and the fork refs in forks.json were moved to the 1.22.5 source release.

Performance

  • Map page cache. ChunkMapLayer's per-chunk upload pipeline is replaced by an 8x8-chunk page cache (256x256 px per page). Pages persist to ModData/optimum-map/{world-id}/ as GZip-compressed RGBA written by a background coalescing thread, upload into a GL_TEXTURE_2D_ARRAY (128 layers, free-list allocator, LRU eviction) with BC7 Mode 6 compression when GL_ARB_texture_compression_bptc is present (64KB vs 256KB per page), and draw through a single GL.DrawArraysInstanced call against the optimum-map shader instead of one draw per map component. 2x and 4x box-filtered LOD tiers serve zoomed-out views, and a min-heap priority queue keyed on squared distance from the viewport centre loads near pages first. Falls back to the vanilla per-component path when no pages are resident.
  • Optional map terrain pre-generation. With MapPageCachePregen enabled in .optimum/optimum.json (default off), unexplored chunks entering the viewport are filled on the background map thread with biome-approximated colour derived from the world seed plus the client-side climate, ocean and forest maps, shaded by replaying GenTerra's noise (9 octaves, freq 1/3267, persistence 0.9) over a 34x34 padded height grid for NW-illuminated slope brightness. Pregen pixels are desaturated 35% so they stay visually distinct from explored terrain, and explored data always wins.
  • Wind and rain volume deadzone now actually ships. WeatherSimulationSound.updateSounds skipped OpenAL SetVolume calls below a 1% delta in the source tree since 0.2.x, but updateSounds was never a transplant target, so the shipped game never ran it. It is now in the Essentials runtime manifest along with its four tracking fields.

Fixes

  • Native 0xc0000005 crash when switching settings tabs. _AddOptimumTab widened the settings background bounds without widening the composer's own surface bounds. GuiElementDialogBackground blurs up to Bounds.OuterWidth through raw unclamped pointers, so a background wider than the Cairo surface overran the native pixel buffer — a stack-trace-less access violation on every in-game tab switch, previously misattributed to widening c.Bounds and reverted twice without being fixed. Every fixed-width ancestor bounds, up to and including the composer's own, now grows by the same delta so background and surface stay in lockstep on both the main-menu and in-game paths.
  • A patch-resolution failure could silently drop the whole install back to vanilla. The Cecil assembly resolver for the --mod runs searched only the vanilla input directory, its Lib folder, the donor directory and the output directory — none of which hold VintagestoryAPI.dll for the mod pass (input comes from .optimum/vanilla/Mods, donors from .optimum/donors). It stayed invisible until Cecil had to resolve a type while writing output, at which point AssemblyDefinition.Write threw AssemblyResolutionException, the patcher process died, and the launcher fell back to a fully vanilla launch — discarding even assemblies that had patched cleanly. The resolver now walks up from both the vanilla and compiled paths to the first ancestor directory containing VintagestoryAPI.dll and adds it plus its Lib folder.
  • Chiseled blocks cast full-cube shadows at any distance. Two separate bugs. The shadow-cull path (CullInstantShadowPassNear/Far) had no chisel-distance awareness in either the source tree or the shipped runtime, so vanilla's plain LodLevel >= 1 check let the cheap full-cube LOD 3 proxy into the depth map even right next to the camera. Separately, OptimumApiBridge.InFrustumAndRange ignored its lodLevel parameter for chisel-flagged locations and returned one shared boolean for both LOD 2 and LOD 3 — up close both meshes drew together (z-fighting), and past the chisel distance the block vanished entirely instead of falling back to the proxy. Fixed with a new InFrustumShadowPass bridge method plus a PatchChiselLodShadowHook IL hook, a shared OptimumChiselLodVisible helper for the source tree, and per-lodLevel branching in InFrustumAndRange.
  • A self-reference in a transplanted method broke every patch on install. updateSounds contains .All(s => s.IsReady) LINQ predicates that the C# compiler caches as static delegates on a generated <>c class. Cecil member injection clones only the named method, not that nested type, so the transplanted IL referenced a method that did not exist in the output. SelfConsistencyVerifier correctly refused to write, but the resulting ModPatcher.Patch exception was unhandled in Optimum.exe and killed the launcher mid-sequence, leaving VSEssentials.dll, VintagestoryLib.dll and VintagestoryAPI.dll all fully vanilla — no Optimum tab, no version suffix. Both .All(...) calls are now explicit loops, with a regression test.
  • Four crashes from Cecil-injected fields whose initializers never ran. Member injection adds a field slot but does not run constructor IL, so any C# field initializer on an injected field silently vanishes. WeatherSystemClient.optimumWindSpeed/optimumSurfaceWindSpeed (null Vec3d, NRE on the first render frame after joining, now plain locals), AStar.optimumNodePool (NRE per pathfinding attempt, swallowed by vanilla's try/catch, leaving every pathing entity unable to move; now lazily allocated), MechanicalPowerMod.optimumTickNetworks (NRE on every server tick, ~16,000/s, producing a 73MB log and an auto-shutdown at 100,000 errors; now lazily allocated) and TreeGen.vineScratchPos/positionStack.
  • NRE on joining a world. WeatherSystemClient.OnRenderFrame dereferenced capi.World.Player.Entity before the local player existed, and then WeatherDataAtPlayer before the server's LevelFinalize packet had populated it. Most reproducible in singleplayer, where render frames tick faster than the integrated server's join sequence. Both are now guarded with an early return.
  • The Optimum settings tab disappeared, and the Back button overflowed the panel. _AddOptimumTab widened c.Bounds, the dialog composer's own on-screen extent, which is a different object from what the tab buttons are parented to — so the dialog re-centred without moving the buttons, pushing the Optimum tab and Back button outside the panel background. Fixed by widening oButtonBounds.ParentBounds (the real layout parent) on both paths, and additionally c.Bounds in-game only. Inter-tab gaps are 10px and the Back gap 15px so the row fits narrow windows, and the Extra tab's switches are now centred on their label rows.
  • Crucible rendered pitch black above 900°C (#9718 regression). CrucibleInFirepitRenderer added incandescence colour straight into RgbaLightIn, saturating the light vector above 1.0, which some Nvidia drivers render as black. Glow now goes through the dedicated RgbaGlowIn uniform with alpha = extraGlow/255f, matching the ForgeContentsRenderer path that always worked.
  • FSR at native resolution no longer differs from vanilla. The LOD-bias SamplerParameter/TexParameter calls are skipped when Render Scale is Native (1.0x); vanilla never sets them, so native-resolution output is now bit-identical to vanilla instead of subtly different.
  • The version label was appended twice. Both ApiPatcher.PatchGameVersionLabel (rewriting GameVersion..cctor) and a source patch in ClientProgram.Main suffixed LongGameVersion, producing v1.22.5 (Stable) + Optimum v0.3.0 + Optimum v0.3.0. The Cecil patch is now the single source of truth.
  • Three patches were out of sync with build/. The settings-tab spacing fix and the FSR native LOD-bias skip were edited directly in build/VintagestoryLib without regenerating...
Read more

v0.2.11

Choose a tag to compare

@Zaldaryon Zaldaryon released this 15 Jul 11:44
v0.2.11
fc96a64

Fixes

  • 0.2.10 installs failed at the packaging phase. The 0.2.10 release shipped the FSR patches without the matching injection entries in Optimum.Patcher, so the Cecil self-consistency gate found six dangling references to ClientSettings.OptimumRenderScale and aborted every fresh install with "output not written". The patcher now injects the FSR members (OptimumRenderScale, onOptimumRenderScaleChanged, FsrEasu, FsrRcas, RegisterOptimumShaderProgram, texture LOD bias helpers) and transplants the six FSR method bodies.

  • The Windows GUI installer ignored -VsPath. The flag reached the headless -Silent path but not the graphical one, so running the normal installer window with multiple Vintage Story installs present picked whatever install auto-detection found first, regardless of what was passed on the command line. The hidden path field behind the GUI now seeds from -VsPath at launch, matching the flag's documented behavior.

  • install-linux.sh could hang forever during the prerequisite check on some systems. Reading ilspycmd's version by piping its live output into head -n1 could deadlock: head exits after the first line and closes its end of the pipe, and the .NET tool writing further output into a closed pipe can block instead of erroring out. The script now reads the tool's full output before parsing it, with a 5s timeout backstop, so the prerequisite check can no longer hang.

  • ilspycmd install/update could fail with Tool 'ilspycmd' is already installed. even after a hang-free run. dotnet tool update --version refuses to move to a version NuGet considers a downgrade, and the fallback to tool install could never succeed either since install always refuses when the tool ID already exists. The update call now passes --allow-downgrade, and the fallback uninstalls first.

Verification

  • Full install pipeline (bootstrap, decompile, 57 patches, build, Cecil patch) passes with both accepted ilspycmd versions, 10.1.0.8386 and 10.1.1.8388: 50/50 methods patched, 93 members injected, zero self-reference errors, patched DLL written.

Notes

Source-only release. See the wiki for install instructions.

v0.2.10

Choose a tag to compare

@Zaldaryon Zaldaryon released this 15 Jul 00:58
v0.2.10
9070c82

Performance

  • FSR 1.0 upscaling. EASU upscales a downsampled scene to native resolution; RCAS applies adaptive sharpening. RenderScale (25-100%) and FsrSharpness (0.0-1.0) appear in the Extra settings tab. At 75% render scale, fill-rate cost drops with no perceptible resolution loss.

Fixes

  • Install crashes after a successful build. Windows PowerShell 5.1 turned routine stderr output into a build-ending error under $ErrorActionPreference = 'Stop', including ilspycmd's own false "not using the latest version" notice and blank lines from dotnet run. bootstrap.ps1, package.ps1, install-windows.ps1, package-linux.ps1, and package-macos.ps1 now shield every native call (ilspycmd, dotnet, git, curl, innoextract, tar, hdiutil, cmake) from this.
  • install-linux.sh rewrite. Interactive prerequisite installer. Detects apt, dnf, zypper, and pacman (SteamOS). Detects .NET SDK 10 even when the system dotnet reports 9.x. Walks through each missing tool before building.
  • ilspycmd version range. .config/ilspycmd-compat.json now accepts 10.1.0.x and 10.1.1.x. bootstrap.sh and bootstrap.ps1 read from it; no hardcoded version.

Notes

Source-only release. See the wiki for install instructions.

v0.2.9

Choose a tag to compare

@Zaldaryon Zaldaryon released this 14 Jul 21:21
v0.2.9
f1dc7dc

Fixes

  • ilspycmd version nag. The pinned decompiler (10.1.0.8386) started refusing to run when a newer version exists on NuGet, printing "You are not using the latest version" and aborting. Bootstrap now accepts any 10.1.0.x or 10.1.1.x without forcing a reinstall. Pin bumped to 10.1.1.8388 (identical decompile output, verified by diff).

Notes

If you downloaded v0.2.8 and hit the "not using the latest version" error during install: this release fixes it. Re-download and re-run the installer.

Source-only release. See the wiki for install instructions.

v0.2.8

Choose a tag to compare

@Zaldaryon Zaldaryon released this 14 Jul 15:01
v0.2.8
ed6a4c9

Performance

  • Entity light batching. Chunk light queries for all visible entities resolve in one pass per chunk segment. 42-67% CPU reduction at 32-512 entities, zero per-frame allocation.
  • Shader state cache. viewMatrix, waterWaveCounter, and the Animation UBO upload once per render pass. Each renderer reads the cached result instead of re-uploading per entity. 83% reduction at 32+ entities.
  • Greedy mesh UI. The Extra settings tab shows MaxMergeWidth/Height sliders when the feature is enabled.

Fixes

  • Background FPS focus debounce. 300ms hysteresis prevents false limiter triggers during world load and rapid alt-tab sequences.
  • Frame pacing timer resolution. timeBeginPeriod(1) on Windows for 1ms sleep granularity. Core-count gate (ProcessorCount > 5) falls back to Yield-only pacing on low-core machines.
  • VS Roofing 1.6.3 LOD. Roof blocks no longer trigger chisel LOD substitution. The gate checks the canChisel attribute before replacing meshes.
  • Thunderlord animation. GearRenderer entities skip the animated block LOD gate via a SkipAnimLod flag.
  • Linux font rendering. Ships vanilla pristine cairo-sharp.dll instead of a recompiled copy. Glyph shape differences gone.

Notes

Source-only release. Clone the repo and run the installer for your platform. See the wiki for instructions.