@chelokot/sneak-out-patches
v0.8.1
Published
Sneak Out reverse-engineering, patching, and runtime mod tooling.
Readme
Sneak Out Runtime Mods
Reverse-engineering notes, runtime mod code, and installation tooling for Sneak Out.
The repository is runtime-mod first:
- no
GameAssembly.dllbyte patches are currently shipped - the patcher installs
BepInEx IL2CPPand selected runtime mods - committed DLL artifacts in
artifacts/runtime_mods/let other people install with--nobuild
One-line installation
The same commands work in Windows PowerShell, Command Prompt, and Linux shells. They require Node.js 20 or newer, but do not require Git, Python, .NET, a repository checkout, or local mod compilation.
Install the current stable default set into an automatically detected Steam installation:
npx -y @chelokot/sneak-out-patches installRemove everything managed by the installer and restore replaced files:
npx -y @chelokot/sneak-out-patches uninstallConfirm or change the detected path and choose every mod individually:
npx -y @chelokot/sneak-out-patches install --interactiveThe CLI downloads the latest payload from GitHub Releases, verifies its SHA-256, checks the installed Steam build and native game fingerprints, installs the pinned BepInEx IL2CPP loader, and validates every selected plugin. Experimental and debug mods remain opt-in; use --all to include them in a noninteractive install.
Useful overrides:
npx -y @chelokot/sneak-out-patches install --game-dir "C:\path\to\Sneak Out"
npx -y @chelokot/sneak-out-patches install --mods keyboard-layout-fix,portal-mode-selector
npx -y @chelokot/sneak-out-patches install --allow-unsupported-buildTooling bootstrap
npm install
npm run tooling:installOn Linux you can use:
make installThe second command bootstraps into .tmp/:
- a repo-managed
.NET SDK - a repo-managed
BepInEx Unity.IL2CPP x64bundle
The runtime mods compile against interop assemblies generated by BepInEx after the game has been started once. Check the complete toolchain and the installed game build with:
npm run doctorExternal prerequisites:
Node.js 20+Python 3
Repository layout
mods/Runtime BepInEx IL2CPP plugins.runtime_mods_manifest.jsonThe single source of truth for runtime mod ids, labels, categories, build paths, and default install settings.supported_game_build.jsonThe supported Steam build and native/interop fingerprints checked bydoctor.mods/Directory.Build.propsShared portable build paths and references for all runtime mod projects.config_templates/runtime_mods/Default config templates consumed by the patcher.artifacts/runtime_mods/Committed runtime mod DLLs for--nobuildinstalls.scripts/Repo bootstrap, build helpers, runtime automation, and profiler configuration.tools/patch_sneak_out.pyInteractive installer, rollback tool, and validator for the game directory.tools/interop_inspector/Helper for inspecting BepInEx-generated interop assemblies.docs/Reverse-engineering notes, gameplay findings, and historical experiments.
Runtime mod catalog
The normal install enables every stable mod below. Network Host Selector and
Alternate Skill Hotkey are opt-in gameplay modifiers; Lobby Test Bot and
Runtime Profiler are development tools. Install any of them with --all or select
them with --interactive.
| Mod id | Name | Default | What it does |
| --- | --- | :---: | --- |
| performance-optimizer | Performance Optimizer | Yes | Preserves compatible interop caches for faster starts, follows the display refresh rate, removes measured main-thread scans and adapts the expensive additional-light shadows/vSync only under sustained low FPS. Normal play keeps its frame histogram in memory and performs no periodic telemetry writes. |
| uniform-seeker-random | Uniform Seeker Random | Yes | Replaces the game's biased/default seeker selection with an equal random choice between eligible real players. |
| portal-mode-selector | Portal Mode Selector | Yes | Adds a stock-styled Maps settings row for choosing Classic or Crown maps before matchmaking, without permanently editing Unity scenes. |
| network-host-selector | Network Host Selector | No | Experimental: lets the party leader choose which real player receives Fusion network authority for the next match. It is disabled by default while invite-to-match reconnection stability is being investigated. |
| minimap | Minimap | Yes | Generates a lightweight camera-aligned floor plan with rounded rooms, doors, pass-through doorway frames, teleport wardrobes, and item rollers from loaded runtime geometry. Zoomed views guide off-screen task rooms and POIs with colored perimeter strips and dots. It shows only the local player and uses no second render camera. |
| mummy-unlock | Mummy Unlock | Yes | Restores Mummy as a selectable hunter, including its shop entry, localized text, abilities and current-client selection flow. |
| unlock-everything | Unlock Everything | Yes | Exposes supported characters, emotes and skill cards, shows every declared skin part (including hidden/unreleased entries) as locally purchasable for exactly 1000 Gold, persists the purchase ledger and subtracts it from the authoritative Gold balance after every refresh, persists loadouts, and restricts live outfit writes to the local input-authority player. Missing client assets appear as blank cards instead of blocking the wardrobe. |
| alternate-skill-hotkey | Alternate Skill Hotkey | No | Maps Left Alt to the character's unequipped alternate active perk through the ordinary skill dispatch path. It is deliberately separate and disabled by default. |
| prop-buff | Prop Buff | Yes | Lets a transformed prop move at 25% speed and cycle through the game's supported prop models with the mouse wheel. Rerolls use the stock all-client prop RPC and preserve the current ability duration and cooldown. |
| start-delay-reducer | Start Now | Yes | Keeps the normal 30-second connection grace period for slow clients but gives the authoritative host a Start now button once the lobby is ready. |
| locker-stun-fix | Locker Stun Fix | Yes | Keeps Boo on a penguin's own locker exit, but prevents the stun and cooldown spend when another player opened the occupied locker first. |
| magic-wardrobe-hook-fix | Magic Wardrobe Hook Fix | Yes | Cancels a pending magic-wardrobe teleport when a Butcher hook interrupts entry, so the pulled player is not snapped back to the wardrobe after the animation finishes. |
| chair-wall-throw-fix | Chair Wall Throw Fix | Yes | Lets an already held chair/stool, barrel or task ingredient be released beside walls: bypasses the stock forward-ray None result and hides its crossed-out E overlay without disabling the shared obstacle detector. Immediately before a chair receives throw velocity, a torso-height wall probe and five held-pose support rays clamp its full projected collider radius to the player's side; overlap fallback compares player/chair obstacle distances before choosing its correction direction. |
| pumpkin-radius-indicator-fix | Pumpkin Radius Indicator Fix | Yes | Makes the persistent hunter-only ring match the authoritative trigger radius. Once triggered, it shows a full-opacity kill-radius ring and a 20%-opacity outer stun-radius ring without changing gameplay radii. |
| ripper-corner-blink-fix | Ripper Corner Blink Fix | Yes | Lets the equipped ReaperHelloThere through-wall perk traverse the game's dedicated room-corner intersection strips even when ordinary scenery is also detected. It does not grant wall blink without the perk. |
| background-loading-guard | Background Loading Guard | Yes | Temporarily keeps Unity updating while a scene loads, then restores the player's previous background-running preference instead of forcing it permanently. |
| keyboard-layout-fix | Keyboard Layout Fix | Yes | Repairs physical WASD movement on Wine with Cyrillic layouts without injecting an entire synthetic keyboard, refreshes visible key labels when the layout changes, and checks again when the game regains focus. |
| proximity-voice-chat | Proximity Voice Chat | Yes | Adds Steam-relayed positional voice with push-to-talk, voice activation and always-on modes, stock-style in-game audio settings, fixed 10-metre distance falloff and wall occlusion. Living players hear living players; ghosts hear living players and other ghosts, while living players cannot hear ghosts. |
| friend-invite-unlock | Friend Invite Unlock | Yes | Keeps offline Steam friends available in the lobby invite list while preserving the normal self, teammate, leave and remove actions. |
| lobby-skill-sandbox | Lobby Skill Sandbox | Yes | Enables the penguin skill panel and lobby-safe slide for practice. Match-only prop transformation is deliberately suppressed because the stock RPC has no safe lobby state and can freeze movement or drop the player through the floor. |
| lobby-test-bot | Lobby Test Bot | No | Adds a native Dummy bot settings row that spawns or removes one inert real Fusion bot and chooses Penguin or Hunter Priority for Classic private tests. A hunter bot automatically confirms the stock Ripper so selection cannot stall. It is excluded from compatibility and host-selection counts. |
| runtime-profiler | Runtime Profiler (Debug) | No | Instruments explicitly selected managed methods and writes timing reports for focused performance investigations. Expensive broad profiling is not enabled by default. |
runtime_mods_manifest.json is the authoritative machine-readable source for these ids,
categories and default states.
Common commands
List runtime mods:
npm run mod:listBuild one runtime mod:
npm run mod:build -- unlock-everythingBuild all runtime mods:
npm run mods:buildThe build helper resolves interop assemblies from SNEAKOUT_INTEROP_DIR, then the repo-local .tmp/runtime-mod/interop cache, then an automatically detected Steam install. Set SNEAKOUT_GAME_DIR when the Steam library cannot be detected. Direct dotnet build calls support the same variables; SNEAKOUT_BEPINEX_CORE_DIR overrides the repo-managed BepInEx references.
Inspect a nonstandard game or interop location:
npm run doctor -- \
--game-dir "/path/to/Sneak Out" \
--interop-dir "/path/to/Sneak Out/BepInEx/interop"Start the interactive installer:
npm run patcherInstall specific runtime mods into an explicit game directory:
npm run patcher -- \
--game-dir "/path/to/Sneak Out" \
--mods unlock-everything,start-delay-reducerInstall from committed artifacts without local builds:
npm run patcher -- \
--game-dir "/path/to/Sneak Out" \
--mods unlock-everything,start-delay-reducer \
--nobuildRollback script-managed changes:
npm run patcher -- --rollback --game-dir "/path/to/Sneak Out"Validate the current install:
npm run patcher -- --validate --game-dir "/path/to/Sneak Out"Patcher behavior
When started without --game-dir, the patcher:
- detects the current operating system
- looks for Steam library folders
- tries to locate the
Sneak Outinstall automatically - asks for confirmation before installing into that directory
The interactive selector is runtime-mod oriented and keyboard driven:
UpandDownMove between runtime mod options.SpaceToggle the highlighted runtime mod.EnterApply the selected install set.
--list-mods prints ids, labels, and categories directly from runtime_mods_manifest.json.
Linux and Proton
When the target install is the Proton Windows build, BepInEx also needs:
XMODIFIERS=@im=none WINEDLLOVERRIDES="winhttp=n,b" %command%The patcher configures that launch option automatically on Linux Steam installs by updating Steam localconfig.vdf for app 2410490. Disabling XIM only for the game keeps GNOME/IBus character translation from swallowing physical gameplay bindings; it does not change the desktop input sources. When Linux GameMode is available, the same per-game command uses gamemoderun; the measured Map02 route improved from 71.49 to 88.40 FPS without lowering render scale or quality.
Runtime automation
Useful commands:
npm run runtime:session
npm run runtime:session:host
npm run performance:session -- --duration-seconds 120 --session baseline
npm run performance:analyze -- .tmp/performance-sessions/<session>
npm run runtime:profiler:configure -- lobby-hotspots
npm run runtime:profiler:offThe performance runner samples the exact game PID, GPU and cgroup I/O, captures only newly changed in-game reports, restores temporary window-manager compatibility state, and closes the test client. The runtime session tooling snapshots multiple real log channels because BepInEx/LogOutput.log is not always populated during automated launches.
See the measured performance report before enabling aggressive graphics overrides. The default Auto preset retains normal visuals until sustained low frame rate triggers the measured additional-shadow/vSync fallback. Heavyweight scene census, interval CSV writes and experimental Unity recorders are opt-in because profiling work can itself cause hitches.
Chair jump geometry replay
The chair release analyser reads the shipped rig|emote_jumpup.kinguin clip, the
complete player rig, the held-item transform, and each chair's real mesh and
collider directly from resources.assets. It replays the exact swept chair box
plus the five diagnostic support rays and labels frames where the old rays miss
a short wall but the volume sweep correctly clamps the chair:
python3 -m pip install UnityPy numpy matplotlib tornado
npm run chair:geometryUse the emote and wall sliders to inspect individual frames, or click Find
false clear to search the exact animation trajectory. --chair chair-a through
chair-d and --chair stool select the real prefab geometry. --save
.tmp/chair-jump.png renders the current default frame without opening a window.
--find-false-clear searches first and then opens or renders the counterexample.
On systems without Tk/Qt/GTK (including a minimal Fedora toolbox), Matplotlib's
WebAgg backend opens the same interactive canvas in the browser; keep the command
running while using it.
The wall transform remains a slider because the historical network log recorded
only EnvironmentCollider, not the transform/path ID of the particular wall.
Interop inspection
Example:
npm run interop:inspect -- \
"/path/to/Sneak Out/BepInEx/interop/Assembly-CSharp.dll" \
"PortalPlayView"Documentation
See docs/README.md.
Historical patching notes are still kept under docs/patching/, but they describe previous binary-patch eras and should not be treated as the current install architecture.
