Releases: milkydelta/OnAirTap
Release list
v1.1.2 - A quickerer bugfix bugfix
I should test things more before pushing them out.
Changes since v1.1.1:
- The default layer mask is output on creation of
SDKRender, instead of on a keypress- This removes the dependency on
UnityEngine.InputLegacyModule, which can cause exceptions if the game has it disabled.
- This removes the dependency on
- The BSIPA project now also imports the csproj.user file, so other people can more easily compile it.
Now that I've had a few downloads, I'd like to say
- If you encounter problems, please open an issue.
- If everything works really well, tag me on bsky. That'd just about make my day.
v1.1.1 - A quick bugfix
Added config validation to layermaskfg and layermaskop on BSIPA. (whoops!)
Press F9 while the camera is active to write the game's default layermask to the logs.
Edit 2026-08-20 23:53
I accidentally broke something else when making this.
If you're on BepInEx or MelonM, use 1.1 instead.
v1.1
The DLL names have changed. If you have an older version installed, delete it before running.
This release is usable only with v2.1 of VRnyan.
The OWML port is not included because it has not been tested. If you want to try it regardless, check v1.1-pre1
Changes since v1.0
User-facing:
- Added OWML port ( #15 #12 )
- Uses a pre-patcher to copy native plugins.
- Changed AssemblyName to include loader.
- Added MelonLoader port ( #7 )
- The default LayerMaskString is changed from empty to a string of 32 zeroes.
- Each render pass (FG,BG,Op) now has it's own layer mask override
- The MMF path has been changed for compatibility with VRnyan v2.1
SpoutSend..config options have been removed.- Now,
Render..controls both rendering and sending
- Now,
Internal:
- HMD position is only fetched when stage and camera exist.
- Loader-specific classes are now in their own namespaces.
- KlakSpout SpoutSender is no longer a MonoBehaviour ( #8 )
ConfigValidation.LayerMaskStringnow logs failure reasons.- New Enum to track current render pass
- Added
ConfigValidation.MemoryPathto check MMF names. Currently unused - MMF name now read from hidden config option
MemoryPath.
Boring Project Stuff:
- Git commit is only fetched for Release config
- BSIPA Release builds no longer have pdb files
- BeatSaberDir is set from
OnAirTap_BSIPA.csproj.usr- I know it's meant to be
.user. Doing that caused pointless warnings.
- I know it's meant to be
- csproj files have loader-specific names.
- BepInEx csproj separated into multiple files for readability.
- KlakSpout native plugin is now a submodule (link)
v1.1-pre1
There's a few changes here. I'll leave explanations for the non-prerelease version.
The MelonLoader port has been built against (and tested with) MelonLoader 0.7.3 on Open Brush v2.30. That's a Mono game.
I'm fairly certain it should work with other Mono games, and I believe it should work with IL2CPP games that have LIV support added through a mod. I'm less sure about IL2CPP games with native LIV support.
Try it out, and drop a message in the supported games issue if you have information.
Requires VRnyan version less than 2.1
v1.0
Changes since v0.6:
User-facing:
- There's a change to how the layer mask override is applied
- The SDK's internal variable isn't modified anymore, so resetting to the original value should work across all games.
- New behaviour for clip plane position/rotation
- Controlled by new config option:
ClipBehaviour - Respects
ClipShouldBeVertical - Value 0 is for previous logic
- Plane centred on clip target
- Plane rotated to face camera position
- Value 1 is for new behaviour (like "that diagram")
- Plane has same rotation as camera
- Plane is positioned at a point along the camera's forward vector such that the clip target will intersect with the plane
- Controlled by new config option:
- The mod should work with games using v2 of the LIV Unity SDK.
- Tested with the current Beat Saber URP beta
- Getting the HMD position (for clip targeting) no longer needs a foreground render.
- Using the MMF's clip position is now also dependent on a settings value.
- It's
0x08, and it's set automatically in LIVnyan 1.3a2, whenever there's a bone being sent.
- It's
Internal:
- As part of the support for SDK 2, the way that I feed data into the existing code has been mostly re-done.
- The SDK v1.5 private
_injectionfields have been replaced with harmony patches that should have the same effects. - Reflection is no longer used.
- The Spout sending patches have been separated from the data-related patches, and could be applied on their own, if someone wants that.
- The SDK v1.5 private
- The camera data struct has a new method to make checking settings more convenient.
Boring project stuff:
- The BSIPA csproj will now copy the Spout and Linux C dlls into the release artifact folder
- I don't have to make the zip myself - it's all automatic!
- The BepInEx csproj now has targets to make a similar release artifact.
- Less work for me!
v0.6
Changes since v0.5:
User-facing:
- Changed Layer Mask in config from int to string
- It's a 32 character string, which is meant to be a valid base 2 number.
- Empty string is treated as 0.
- Mask value of 0 means "don't change the mask"
- If the value is set to 0 after a reload, it should try and restore the original layer mask
- Currently only in Beat Saber
- Added validation to configs
- For Resolution and LayerMaskString
- If there's an invalid value, the field is reset to default
- Configs can now be reloaded without restarting the game
- Automatic for BSIPA
- BepInEx needs a manual call of Reload() - I'll probably add something to watch the file
- Works for all values, except protocol version.
- The empty texture used for blanking spout senders now respects resolution settings.
Internal:
- The Comms classes now have close functions.
- Common plugin has a config class now, so the main class is less cluttered.
- GetPlatform returns an enum instead of a string
- New class in Common: ConfigValidation
- replaces the checks in BepInEx plugin's BindConfigs
This description is mainly so I can remember later. My commit names aren't very helpful.
v0.5
Changes since 0.4:
- csproj Version fields changed from 1.0.0 to 0.5.0.
- Added camera layer mask override.
- Right now, this is a basic int in the config, just so there's a value to apply, but I'd like to change it to something more readable. See #4 for ideas/progress.
- A value of 0 means the override is ignored.
- Changed name of KlakSpout native DLL.
- Fixes #3.
- New name is
OAT_KlakSpout.dll. Location remains the same.
- Prepare for protocol changes in new LIVnyan versions.
- New config value
ProtocolMinorVersionsets the name of the MMF and controls how/what data is read.- Value 0 is for previous behaviour, which is compatible with LIVnyan v1.2.
- Value >= 1 adds 2 ints and 3 floats, and is not quite compatible with LIVnyan v1.3a1.
- New config value to apply resolution from MMF
- New config value to apply clip plane location from MMF
- Helper program
mmf_vnyan.exenow uses protocol version v1.1.
- New config value
v0.4
Changes since 0.3:
- Implement and use logger
- Use the log enabled & log spam flags from the MMF.
- Add config option for blanking the spout senders when LIV destroys assets (usually on scene change).
- Add config option for adjusting the far clip distance (default 5000 in BSIPA, 1000 in BepInEx)
- Set far clip value in pose.farClipPlane (was previously only set in projection matrix)
This time, I built the BSIPA version against v1.40.8
Edit: and also there's options to enable/disable specific spout senders now. I forgot that..
v0.3 Initial Release
I'm writing this down so I remember it later.
I have 2 chains of logic to call this v0.3:
- Logic 1:
- v0.1 was the first demo video
- v0.2 was the second demo video
- v0.3 is the third thing to be shared
- Logic 2:
- v0.1 was the initial implementation
- v0.2 was the second big leap - bridging to the native Linux shared memory.
- v0.3 is the third big leap - having build for multiple loaders, so it works with other mods.
OnAirTap-BSIPA.zip was built against the latest version of Beat Saber.
OnAirTap-BepInEx5.zip was built against the latest Steam version of Open Brush, though it should work with other games.
The Bridge program is needed only on Linux, and is to be run inside the same proton environment as your VNyan instance. My preferred way to do that is with the PROTON_REMOTE_DEBUG_CMD environment variable.