From 6d4fc549d95f9224a2715e85daa14811633d75b5 Mon Sep 17 00:00:00 2001 From: NotAKidoS <37721153+NotAKidoS@users.noreply.github.com> Date: Sun, 28 Dec 2025 20:30:00 -0600 Subject: [PATCH] mass commit of laziness --- .../AvatarQueueSystemTweaks.csproj | 0 .../AvatarQueueSystemTweaks}/Main.cs | 2 +- .../AvatarQueueSystemTweaks}/Patches.cs | 1 - .../Properties/AssemblyInfo.cs | 2 +- .../AvatarQueueSystemTweaks}/README.md | 0 .../AvatarQueueSystemTweaks}/format.json | 0 .../BufferParticleFixer.csproj | 2 + .Deprecated/BufferParticleFixer/Main.cs | 109 + .../Properties/AssemblyInfo.cs | 32 + .Deprecated/BufferParticleFixer/README.md | 14 + .Deprecated/BufferParticleFixer/format.json | 23 + .../CVRGizmos/Properties/AssemblyInfo.cs | 2 +- .../ChatBoxTweaks/ChatBoxTweaks.csproj | 9 + .Deprecated/ChatBoxTweaks/Main.cs | 92 + .../ChatBoxTweaks/Properties/AssemblyInfo.cs | 32 + .Deprecated/ChatBoxTweaks/README.md | 22 + .Deprecated/ChatBoxTweaks/format.json | 23 + .Deprecated/ChatBubbles/ChatBubbles.csproj | 6 + .Deprecated/ChatBubbles/Main.cs | 236 +++ .../ChatBubbles/Properties/AssemblyInfo.cs | 32 + .Deprecated/ChatBubbles/README.md | 19 + .Deprecated/ChatBubbles/format.json | 23 + .../ControlToUnlockEyes.csproj | 9 + .Deprecated/ControlToUnlockEyes/Main.cs | 169 ++ .../Properties/AssemblyInfo.cs | 32 + .Deprecated/ControlToUnlockEyes/README.md | 22 + .Deprecated/ControlToUnlockEyes/format.json | 23 + .Deprecated/FuckCameras/FuckCameras.csproj | 6 + .Deprecated/FuckCameras/Main.cs | 228 ++ .../FuckCameras/Properties/AssemblyInfo.cs | 32 + .Deprecated/FuckCameras/README.md | 19 + .Deprecated/FuckCameras/format.json | 23 + .Deprecated/FuckCohtml2/FuckCohtml2.csproj | 6 + .Deprecated/FuckCohtml2/Main.cs | 57 + .../FuckCohtml2/Properties/AssemblyInfo.cs | 32 + .Deprecated/FuckCohtml2/README.md | 19 + .Deprecated/FuckCohtml2/format.json | 23 + .../Properties/AssemblyInfo.cs | 2 +- .../IFUCKINGHATECAMERAS.csproj | 6 + .Deprecated/IFUCKINGHATECAMERAS/Main.cs | 39 + .../Properties/AssemblyInfo.cs | 32 + .Deprecated/IFUCKINGHATECAMERAS/README.md | 19 + .Deprecated/IFUCKINGHATECAMERAS/format.json | 23 + .../KeepVelocityOnExitFlight.csproj | 0 .../KeepVelocityOnExitFlight}/Main.cs | 4 +- .../Properties/AssemblyInfo.cs | 2 +- .../KeepVelocityOnExitFlight}/README.md | 0 .../KeepVelocityOnExitFlight}/format.json | 0 .../LazyPrune}/LazyPrune.csproj | 0 {LazyPrune => .Deprecated/LazyPrune}/Main.cs | 2 +- .../LazyPrune}/Properties/AssemblyInfo.cs | 2 +- .../LazyPrune}/README.md | 0 .../LazyPrune}/format.json | 0 .Deprecated/SuperAwesomeMod/DepthCameraFix.cs | 16 - .../Interaction/CVRPlayerHand.cs | 2 - .../CVRPlayerInteractionManager.cs | 428 ++-- .../Components/CVRCanvasWrapper.cs | 242 +-- .../Interaction/ControllerRay.cs | 1871 +++++++++++++++++ .../Interaction/Input/CustomInput.cs | 85 + .../Interaction/Input/CustomInputModule.cs | 67 + .../RaycastImpl/CVRPlayerRaycaster.cs | 17 +- .../RaycastImpl/CVRPlayerRaycasterMouse.cs | 16 +- .../CVRPlayerRaycasterTransform.cs | 39 +- .../RaycastImpl/CVRRaycastResult.cs | 3 +- .../Interaction/RaycastImpl/RaycastDebug.cs | 1 - .../UnityExploerer/UEMenuHelper.cs | 362 ++++ .Deprecated/SuperAwesomeMod/Main.cs | 53 +- .../SuperAwesomeMod/SuperAwesomeMod.csproj | 2 +- .../ByeByePerformanceThankYouAMD.csproj | 2 + .../CohtmlRenderForwarder.cs | 0 .../CommandBufferManager.cs | 0 .../ByeByePerformanceThankYouAMD/Main.cs | 89 + .../Properties/AssemblyInfo.cs | 32 + .../ByeByePerformanceThankYouAMD/README.md | 14 + .../ByeByePerformanceThankYouAMD/format.json | 23 + .../LuaToolsExtension/LuaHotReloadManager.cs | 1 - .Experimental/CVRLuaToolsExtension/Main.cs | 1 - .../DummyMenu/Components/DummyMenuManager.cs | 103 + .../Components/DummyMenuPositionHelper.cs | 37 + .Experimental/DummyMenu/CreateDummyMenu.cs | 243 +++ .Experimental/DummyMenu/DummyMenu.csproj | 6 + .Experimental/DummyMenu/Main.cs | 21 + .Experimental/DummyMenu/ModSettings.cs | 64 + .../DummyMenu/Properties/AssemblyInfo.cs | 32 + .Experimental/LuaNetworkVariables/Main.cs | 4 +- .../Properties/AssemblyInfo.cs | 4 +- .Experimental/LuaNetworkVariables/format.json | 23 - .../BTKUI/BtkUiAddon_CAT_OriginShiftMod.cs | 6 +- .../Integrations/BTKUI/BtkuiAddon.cs | 4 +- .../Integrations/BTKUI/BtkuiAddon_Utils.cs | 6 +- .../ThirdPerson/ThirdPersonAddon.cs | 1 + .Experimental/OriginShift/Main.cs | 5 - .../OriginShift/Networking/ModNetwork.cs | 2 +- .../Receivers/OriginShiftEventReceiver.cs | 2 - .../OriginShiftParticleSystemReceiver.cs | 2 +- .../Receivers/OriginShiftRigidbodyReceiver.cs | 2 +- .../OriginShiftTrailRendererReceiver.cs | 2 +- .../OriginShift/OriginShiftManager.cs | 1 - .../OriginShift/Player/OriginShiftMonitor.cs | 2 - .Experimental/OriginShift/Patches.cs | 21 +- .../OriginShift/Properties/AssemblyInfo.cs | 4 +- .Experimental/OriginShift/format.json | 23 - ASTExtension/Properties/AssemblyInfo.cs | 2 +- ASTExtension/format.json | 8 +- ConfigureCalibrationPose/Main.cs | 1 - CustomSpawnPoint/Properties/AssemblyInfo.cs | 2 +- CustomSpawnPoint/format.json | 8 +- .../Properties/AssemblyInfo.cs | 2 +- DoubleTapJumpToExitSeat/format.json | 8 +- FuckToes/Properties/AssemblyInfo.cs | 4 +- FuckToes/format.json | 10 +- PathCamDisabler/Properties/AssemblyInfo.cs | 2 +- PathCamDisabler/format.json | 8 +- PortableCameraAdditions/HarmonyPatches.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 +- .../VisualMods/CameraAdditions.cs | 46 +- PortableCameraAdditions/format.json | 12 +- PropLoadingHexagon/Main.cs | 2 +- PropLoadingHexagon/PropLoadingHexagon.csproj | 2 +- PropLoadingHexagon/Properties/AssemblyInfo.cs | 4 +- PropLoadingHexagon/format.json | 10 +- PropUndoButton/Main.cs | 22 +- PropUndoButton/Properties/AssemblyInfo.cs | 4 +- PropUndoButton/format.json | 10 +- .../Properties/AssemblyInfo.cs | 2 +- .../Components/SteeringWheelPickup.cs | 1 + RCCVirtualSteeringWheel/format.json | 8 +- .../Properties/AssemblyInfo.cs | 2 +- RelativeSyncJitterFix/format.json | 10 +- ScrollFlight/Properties/AssemblyInfo.cs | 2 +- ScrollFlight/format.json | 8 +- ShareBubbles/Properties/AssemblyInfo.cs | 4 +- ShareBubbles/format.json | 8 +- ShowPlayerInSelfMirror/Main.cs | 154 ++ .../Properties/AssemblyInfo.cs | 32 + ShowPlayerInSelfMirror/README.md | 16 + .../ShowPlayerInSelfMirror.csproj | 9 + ShowPlayerInSelfMirror/format.json | 23 + SmootherRay/Main.cs | 3 +- SmootherRay/Properties/AssemblyInfo.cs | 4 +- SmootherRay/SmootherRayer.cs | 4 +- SmootherRay/format.json | 10 +- .../BTKUI/UIAddon.Category.StickersMod.cs | 3 + Stickers/Integrations/BTKUI/UIAddon.Main.cs | 5 +- .../BTKUI/UIAddon.Page.StickerSelect.cs | 3 +- Stickers/Main.cs | 10 +- Stickers/ModSettings.cs | 6 + Stickers/Properties/AssemblyInfo.cs | 6 +- Stickers/Stickers/Enums/StickerSize.cs | 34 + .../Networking/ModNetwork.Constants.cs | 2 +- .../Stickers/Networking/ModNetwork.Inbound.cs | 4 +- .../Networking/ModNetwork.Outbound.cs | 4 +- Stickers/Stickers/StickerData.cs | 15 +- Stickers/Stickers/StickerSystem.Main.cs | 11 +- .../Stickers/StickerSystem.PlayerCallbacks.cs | 4 +- .../StickerSystem.StickerLifecycle.cs | 12 +- Stickers/Stickers/Utilities/StickerCache.cs | 2 - Stickers/format.json | 12 +- ThirdPerson/Patches.cs | 4 +- ThirdPerson/Properties/AssemblyInfo.cs | 2 +- ThirdPerson/format.json | 8 +- Tinyboard/Main.cs | 4 +- Tinyboard/Properties/AssemblyInfo.cs | 2 +- Tinyboard/format.json | 10 +- .../Main.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../format.json | 8 +- 167 files changed, 5471 insertions(+), 675 deletions(-) rename {AvatarQueueSystemTweaks => .Deprecated/AvatarQueueSystemTweaks}/AvatarQueueSystemTweaks.csproj (100%) rename {AvatarQueueSystemTweaks => .Deprecated/AvatarQueueSystemTweaks}/Main.cs (98%) rename {AvatarQueueSystemTweaks => .Deprecated/AvatarQueueSystemTweaks}/Patches.cs (99%) rename {AvatarQueueSystemTweaks => .Deprecated/AvatarQueueSystemTweaks}/Properties/AssemblyInfo.cs (98%) rename {AvatarQueueSystemTweaks => .Deprecated/AvatarQueueSystemTweaks}/README.md (100%) rename {AvatarQueueSystemTweaks => .Deprecated/AvatarQueueSystemTweaks}/format.json (100%) create mode 100644 .Deprecated/BufferParticleFixer/BufferParticleFixer.csproj create mode 100644 .Deprecated/BufferParticleFixer/Main.cs create mode 100644 .Deprecated/BufferParticleFixer/Properties/AssemblyInfo.cs create mode 100644 .Deprecated/BufferParticleFixer/README.md create mode 100644 .Deprecated/BufferParticleFixer/format.json create mode 100644 .Deprecated/ChatBoxTweaks/ChatBoxTweaks.csproj create mode 100644 .Deprecated/ChatBoxTweaks/Main.cs create mode 100644 .Deprecated/ChatBoxTweaks/Properties/AssemblyInfo.cs create mode 100644 .Deprecated/ChatBoxTweaks/README.md create mode 100644 .Deprecated/ChatBoxTweaks/format.json create mode 100644 .Deprecated/ChatBubbles/ChatBubbles.csproj create mode 100644 .Deprecated/ChatBubbles/Main.cs create mode 100644 .Deprecated/ChatBubbles/Properties/AssemblyInfo.cs create mode 100644 .Deprecated/ChatBubbles/README.md create mode 100644 .Deprecated/ChatBubbles/format.json create mode 100644 .Deprecated/ControlToUnlockEyes/ControlToUnlockEyes.csproj create mode 100644 .Deprecated/ControlToUnlockEyes/Main.cs create mode 100644 .Deprecated/ControlToUnlockEyes/Properties/AssemblyInfo.cs create mode 100644 .Deprecated/ControlToUnlockEyes/README.md create mode 100644 .Deprecated/ControlToUnlockEyes/format.json create mode 100644 .Deprecated/FuckCameras/FuckCameras.csproj create mode 100644 .Deprecated/FuckCameras/Main.cs create mode 100644 .Deprecated/FuckCameras/Properties/AssemblyInfo.cs create mode 100644 .Deprecated/FuckCameras/README.md create mode 100644 .Deprecated/FuckCameras/format.json create mode 100644 .Deprecated/FuckCohtml2/FuckCohtml2.csproj create mode 100644 .Deprecated/FuckCohtml2/Main.cs create mode 100644 .Deprecated/FuckCohtml2/Properties/AssemblyInfo.cs create mode 100644 .Deprecated/FuckCohtml2/README.md create mode 100644 .Deprecated/FuckCohtml2/format.json create mode 100644 .Deprecated/IFUCKINGHATECAMERAS/IFUCKINGHATECAMERAS.csproj create mode 100644 .Deprecated/IFUCKINGHATECAMERAS/Main.cs create mode 100644 .Deprecated/IFUCKINGHATECAMERAS/Properties/AssemblyInfo.cs create mode 100644 .Deprecated/IFUCKINGHATECAMERAS/README.md create mode 100644 .Deprecated/IFUCKINGHATECAMERAS/format.json rename {KeepVelocityOnExitFlight => .Deprecated/KeepVelocityOnExitFlight}/KeepVelocityOnExitFlight.csproj (100%) rename {KeepVelocityOnExitFlight => .Deprecated/KeepVelocityOnExitFlight}/Main.cs (93%) rename {KeepVelocityOnExitFlight => .Deprecated/KeepVelocityOnExitFlight}/Properties/AssemblyInfo.cs (98%) rename {KeepVelocityOnExitFlight => .Deprecated/KeepVelocityOnExitFlight}/README.md (100%) rename {KeepVelocityOnExitFlight => .Deprecated/KeepVelocityOnExitFlight}/format.json (100%) rename {LazyPrune => .Deprecated/LazyPrune}/LazyPrune.csproj (100%) rename {LazyPrune => .Deprecated/LazyPrune}/Main.cs (99%) rename {LazyPrune => .Deprecated/LazyPrune}/Properties/AssemblyInfo.cs (98%) rename {LazyPrune => .Deprecated/LazyPrune}/README.md (100%) rename {LazyPrune => .Deprecated/LazyPrune}/format.json (100%) create mode 100644 .Deprecated/SuperAwesomeMod/Interaction/ControllerRay.cs create mode 100644 .Deprecated/SuperAwesomeMod/Interaction/Input/CustomInput.cs create mode 100644 .Deprecated/SuperAwesomeMod/Interaction/Input/CustomInputModule.cs create mode 100644 .Deprecated/SuperAwesomeMod/Interaction/UnityExploerer/UEMenuHelper.cs create mode 100644 .Experimental/ByeByePerformanceThankYouAMD/ByeByePerformanceThankYouAMD.csproj create mode 100644 .Experimental/ByeByePerformanceThankYouAMD/CohtmlRenderForwarder.cs create mode 100644 .Experimental/ByeByePerformanceThankYouAMD/CommandBufferManager.cs create mode 100644 .Experimental/ByeByePerformanceThankYouAMD/Main.cs create mode 100644 .Experimental/ByeByePerformanceThankYouAMD/Properties/AssemblyInfo.cs create mode 100644 .Experimental/ByeByePerformanceThankYouAMD/README.md create mode 100644 .Experimental/ByeByePerformanceThankYouAMD/format.json create mode 100644 .Experimental/DummyMenu/Components/DummyMenuManager.cs create mode 100644 .Experimental/DummyMenu/Components/DummyMenuPositionHelper.cs create mode 100644 .Experimental/DummyMenu/CreateDummyMenu.cs create mode 100644 .Experimental/DummyMenu/DummyMenu.csproj create mode 100644 .Experimental/DummyMenu/Main.cs create mode 100644 .Experimental/DummyMenu/ModSettings.cs create mode 100644 .Experimental/DummyMenu/Properties/AssemblyInfo.cs delete mode 100644 .Experimental/LuaNetworkVariables/format.json delete mode 100644 .Experimental/OriginShift/format.json create mode 100644 ShowPlayerInSelfMirror/Main.cs create mode 100644 ShowPlayerInSelfMirror/Properties/AssemblyInfo.cs create mode 100644 ShowPlayerInSelfMirror/README.md create mode 100644 ShowPlayerInSelfMirror/ShowPlayerInSelfMirror.csproj create mode 100644 ShowPlayerInSelfMirror/format.json create mode 100644 Stickers/Stickers/Enums/StickerSize.cs diff --git a/AvatarQueueSystemTweaks/AvatarQueueSystemTweaks.csproj b/.Deprecated/AvatarQueueSystemTweaks/AvatarQueueSystemTweaks.csproj similarity index 100% rename from AvatarQueueSystemTweaks/AvatarQueueSystemTweaks.csproj rename to .Deprecated/AvatarQueueSystemTweaks/AvatarQueueSystemTweaks.csproj diff --git a/AvatarQueueSystemTweaks/Main.cs b/.Deprecated/AvatarQueueSystemTweaks/Main.cs similarity index 98% rename from AvatarQueueSystemTweaks/Main.cs rename to .Deprecated/AvatarQueueSystemTweaks/Main.cs index 403e33b..ce03ff8 100644 --- a/AvatarQueueSystemTweaks/Main.cs +++ b/.Deprecated/AvatarQueueSystemTweaks/Main.cs @@ -1,4 +1,4 @@ -using MelonLoader; +using MelonLoader; using NAK.AvatarQueueSystemTweaks.Patches; namespace NAK.AvatarQueueSystemTweaks; diff --git a/AvatarQueueSystemTweaks/Patches.cs b/.Deprecated/AvatarQueueSystemTweaks/Patches.cs similarity index 99% rename from AvatarQueueSystemTweaks/Patches.cs rename to .Deprecated/AvatarQueueSystemTweaks/Patches.cs index 74a86ac..f9ef61b 100644 --- a/AvatarQueueSystemTweaks/Patches.cs +++ b/.Deprecated/AvatarQueueSystemTweaks/Patches.cs @@ -1,4 +1,3 @@ -using System.Collections; using ABI_RC.Core; using ABI_RC.Core.IO; using ABI_RC.Core.Networking.IO.Social; diff --git a/AvatarQueueSystemTweaks/Properties/AssemblyInfo.cs b/.Deprecated/AvatarQueueSystemTweaks/Properties/AssemblyInfo.cs similarity index 98% rename from AvatarQueueSystemTweaks/Properties/AssemblyInfo.cs rename to .Deprecated/AvatarQueueSystemTweaks/Properties/AssemblyInfo.cs index 821459b..092e11b 100644 --- a/AvatarQueueSystemTweaks/Properties/AssemblyInfo.cs +++ b/.Deprecated/AvatarQueueSystemTweaks/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -using MelonLoader; +using MelonLoader; using NAK.AvatarQueueSystemTweaks.Properties; using System.Reflection; diff --git a/AvatarQueueSystemTweaks/README.md b/.Deprecated/AvatarQueueSystemTweaks/README.md similarity index 100% rename from AvatarQueueSystemTweaks/README.md rename to .Deprecated/AvatarQueueSystemTweaks/README.md diff --git a/AvatarQueueSystemTweaks/format.json b/.Deprecated/AvatarQueueSystemTweaks/format.json similarity index 100% rename from AvatarQueueSystemTweaks/format.json rename to .Deprecated/AvatarQueueSystemTweaks/format.json diff --git a/.Deprecated/BufferParticleFixer/BufferParticleFixer.csproj b/.Deprecated/BufferParticleFixer/BufferParticleFixer.csproj new file mode 100644 index 0000000..e94f9dc --- /dev/null +++ b/.Deprecated/BufferParticleFixer/BufferParticleFixer.csproj @@ -0,0 +1,2 @@ + + diff --git a/.Deprecated/BufferParticleFixer/Main.cs b/.Deprecated/BufferParticleFixer/Main.cs new file mode 100644 index 0000000..8295e79 --- /dev/null +++ b/.Deprecated/BufferParticleFixer/Main.cs @@ -0,0 +1,109 @@ +using System.Reflection; +using ABI_RC.Core.Networking.API.Responses; +using ABI_RC.Core.Util.AssetFiltering; +using HarmonyLib; +using MelonLoader; +using UnityEngine; + +namespace NAK.BufferParticleFixer; + +public class BufferParticleFixerMod : MelonMod +{ + private static MelonLogger.Instance Logger; + + private static readonly MelonPreferences_Category Category = + MelonPreferences.CreateCategory(nameof(BufferParticleFixer)); + + private static readonly MelonPreferences_Entry EntryFixBufferParticles = + Category.CreateEntry( + identifier: "fix_buffer_particles", + true, + display_name: "Fix Buffer Particles", + description: "Should the mod attempt to fix buffer particles by modifying their lifetime and sub-emitter settings?"); + + public override void OnInitializeMelon() + { + Logger = LoggerInstance; + + HarmonyInstance.Patch( + typeof(SharedFilter).GetMethod(nameof(SharedFilter.ProcessParticleComponent), + BindingFlags.Public | BindingFlags.Static), + postfix: new HarmonyMethod(typeof(BufferParticleFixerMod).GetMethod(nameof(OnProcessParticleComponent), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + } + + private static void OnProcessParticleComponent( + string collectionId, + Component particleComponent, + bool physicsCollision, + CompatibilityVersions compatibilityVersion) + { + if (particleComponent is not ParticleSystem particleSystem) + return; + + if (!EntryFixBufferParticles.Value) + return; + + // Logger.Msg($"Processing particle system on collection '{collectionId}'."); + + if (!IsLikelyBufferParticle(particleSystem)) + return; + + Logger.Msg($"Detected likely buffer particle system '{particleSystem.name}' on collection '{collectionId}'. Applying fix..."); + + // Set start lifetime to 1000 + // All sub-emitters to "Spawn on Birth" + // https://x.com/hfcRedddd/status/1696914565919813679 + + ParticleSystem.MainModule mainModule = particleSystem.main; + + mainModule.startLifetime = 1f; + + for (int i = 0; i < particleSystem.subEmitters.subEmittersCount; i++) + { + ParticleSystem subEmitter = particleSystem.subEmitters.GetSubEmitterSystem(i); + if (subEmitter) particleSystem.subEmitters.SetSubEmitterType(i, ParticleSystemSubEmitterType.Birth); + } + } + + // https://x.com/hfcRedddd/status/1696913727415537807 + private static bool IsLikelyBufferParticle(ParticleSystem ps) + { + // Check if the sub-emitters are children of the particle system + Transform psTransform = ps.transform; + + bool hasSubEmitterNotChild = false; + + ParticleSystem.SubEmittersModule subEmitters = ps.subEmitters; + int subEmitterCount = subEmitters.subEmittersCount; + + for (int i = 0; i < subEmitterCount; i++) + { + ParticleSystem subEmitter = subEmitters.GetSubEmitterSystem(i); + + // Skip null sub-emitters + if (!subEmitter) + { + Logger.Warning($"Particle system '{ps.name}' has a null sub-emitter at index {i}."); + continue; + } + + // If any sub-emitter is not a child of the particle system, it's likely a buffer particle. + // This setup is also what shits into our logs... + if (!subEmitter.transform.IsChildOf(psTransform)) + hasSubEmitterNotChild = true; + } + + if (hasSubEmitterNotChild) + { + // Buffer particles have very short lifetimes + if (!(ps.main.startLifetime.constant > 0.05f)) + return true; + + Logger.Msg($"A potential buffer particle system '{ps.name}' has a start lifetime of {ps.main.startLifetime.constant}, which is longer than expected."); + } + + return false; + } +} \ No newline at end of file diff --git a/.Deprecated/BufferParticleFixer/Properties/AssemblyInfo.cs b/.Deprecated/BufferParticleFixer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..53fab6b --- /dev/null +++ b/.Deprecated/BufferParticleFixer/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.BufferParticleFixer.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.BufferParticleFixer))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.BufferParticleFixer))] + +[assembly: MelonInfo( + typeof(NAK.BufferParticleFixer.BufferParticleFixerMod), + nameof(NAK.BufferParticleFixer), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/BufferParticleFixer" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.BufferParticleFixer.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/BufferParticleFixer/README.md b/.Deprecated/BufferParticleFixer/README.md new file mode 100644 index 0000000..1c4c5bc --- /dev/null +++ b/.Deprecated/BufferParticleFixer/README.md @@ -0,0 +1,14 @@ +# SearchWithSpacesFix + +Fixes search terms that use spaces. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/BufferParticleFixer/format.json b/.Deprecated/BufferParticleFixer/format.json new file mode 100644 index 0000000..f8950ca --- /dev/null +++ b/.Deprecated/BufferParticleFixer/format.json @@ -0,0 +1,23 @@ +{ + "_id": -1, + "name": "SearchWithSpacesFix", + "modversion": "1.0.0", + "gameversion": "2024r177", + "loaderversion": "0.6.1", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Fixes search terms that include spaces.", + "searchtags": [ + "search", + "spaces", + "fix", + "meow" + ], + "requirements": [ + "None" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r42/SearchWithSpacesFix.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/SearchWithSpacesFix/", + "changelog": "- Initial release", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/.Deprecated/CVRGizmos/Properties/AssemblyInfo.cs b/.Deprecated/CVRGizmos/Properties/AssemblyInfo.cs index 8fb1e54..2bffafd 100644 --- a/.Deprecated/CVRGizmos/Properties/AssemblyInfo.cs +++ b/.Deprecated/CVRGizmos/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ using System.Reflection; downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/CVRGizmos" )] -[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")] +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] [assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] diff --git a/.Deprecated/ChatBoxTweaks/ChatBoxTweaks.csproj b/.Deprecated/ChatBoxTweaks/ChatBoxTweaks.csproj new file mode 100644 index 0000000..caeac6b --- /dev/null +++ b/.Deprecated/ChatBoxTweaks/ChatBoxTweaks.csproj @@ -0,0 +1,9 @@ + + + + PlayerCloneAttachment + + + + + diff --git a/.Deprecated/ChatBoxTweaks/Main.cs b/.Deprecated/ChatBoxTweaks/Main.cs new file mode 100644 index 0000000..2cd915f --- /dev/null +++ b/.Deprecated/ChatBoxTweaks/Main.cs @@ -0,0 +1,92 @@ +using System.Reflection; +using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core.UI.UIRework.Managers; +using ABI_RC.Systems.ChatBox; +using ABI_RC.Systems.InputManagement; +using HarmonyLib; +using MelonLoader; + +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.LowLevel; +using UnityEngine.PlayerLoop; + +namespace NAK.ChatBoxTweaks; + +public class ChatBoxTweaksMod : MelonMod +{ + public override void OnInitializeMelon() + { + HarmonyInstance.Patch( + typeof(KeyboardManager).GetMethod(nameof(KeyboardManager.OnKeyboardSubmit), + BindingFlags.NonPublic | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(ChatBoxTweaksMod).GetMethod(nameof(OnPreKeyboardManagerKeyboardSubmit), + BindingFlags.NonPublic | BindingFlags.Static)), + postfix: new HarmonyMethod(typeof(ChatBoxTweaksMod).GetMethod(nameof(OnPostKeyboardManagerKeyboardSubmit), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + } + + private static void OnPreKeyboardManagerKeyboardSubmit(ref KeyboardManager __instance, ref KeyboardManager.OpenSource? __state) + { + __state = __instance.KeyboardOpenSource; + } + + private static void OnPostKeyboardManagerKeyboardSubmit(ref KeyboardManager.OpenSource? __state) + { + if (__state == KeyboardManager.OpenSource.TextComms) ChatBoxAPI.OpenKeyboard(); + } +} + + +/* +public static class NetworkLoopInjector +{ + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void InjectNetworkFixedUpdate() + { + var playerLoop = PlayerLoop.GetCurrentPlayerLoop(); + + // Find the FixedUpdate phase + int fixedUpdateIndex = Array.FindIndex(playerLoop.subSystemList, s => s.type == typeof(FixedUpdate)); + if (fixedUpdateIndex < 0) + { + Debug.LogError("FixedUpdate not found in player loop!"); + return; + } + + var fixedUpdate = playerLoop.subSystemList[fixedUpdateIndex]; + + // Create your custom PlayerLoopSystem + var networkSystem = new PlayerLoopSystem + { + type = typeof(NetworkFixedUpdate), + updateDelegate = NetworkFixedUpdate.Run + }; + + // Insert at the start so it runs before physics, animation, etc. + var subs = fixedUpdate.subSystemList.ToList(); + subs.Insert(0, networkSystem); + fixedUpdate.subSystemList = subs.ToArray(); + + // Reassign and set back + playerLoop.subSystemList[fixedUpdateIndex] = fixedUpdate; + PlayerLoop.SetPlayerLoop(playerLoop); + + Debug.Log("[NetworkLoopInjector] Inserted NetworkFixedUpdate at start of FixedUpdate loop"); + } + + static class NetworkFixedUpdate + { + static int lastStateFrame = -1; + + public static void Run() + { + // Apply your networked object state syncs before physics simulation + Debug.Log("Last State Frame: " + lastStateFrame + " Current Frame: " + Time.frameCount); + lastStateFrame = Time.frameCount; + } + } +} +*/ diff --git a/.Deprecated/ChatBoxTweaks/Properties/AssemblyInfo.cs b/.Deprecated/ChatBoxTweaks/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9444b4d --- /dev/null +++ b/.Deprecated/ChatBoxTweaks/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.ChatBoxTweaks.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.ChatBoxTweaks))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.ChatBoxTweaks))] + +[assembly: MelonInfo( + typeof(NAK.ChatBoxTweaks.ChatBoxTweaksMod), + nameof(NAK.ChatBoxTweaks), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ChatBoxTweaks" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.ChatBoxTweaks.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/ChatBoxTweaks/README.md b/.Deprecated/ChatBoxTweaks/README.md new file mode 100644 index 0000000..b092e40 --- /dev/null +++ b/.Deprecated/ChatBoxTweaks/README.md @@ -0,0 +1,22 @@ +# YouAreMyPropNowWeAreHavingSoftTacosLater + +Lets you bring held, attached, and occupied props through world loads. This is configurable in the mod settings. + +https://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO + +There is special logic in place for bringing air vehicles through world loads. +If above the ground you will be placed up to 20m above the spawnpoint of the next world. + +## Examples +https://fixupx.com/NotAKidoS/status/1910545346922422675 + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/ChatBoxTweaks/format.json b/.Deprecated/ChatBoxTweaks/format.json new file mode 100644 index 0000000..8e68782 --- /dev/null +++ b/.Deprecated/ChatBoxTweaks/format.json @@ -0,0 +1,23 @@ +{ + "_id": 262, + "name": "YouAreMyPropNowWeAreHavingSoftTacosLater", + "modversion": "1.0.0", + "gameversion": "2025r180", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Lets you bring held, attached, and occupied props through world loads. This is configurable in the mod settings.\nhttps://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO\n\nThere is special logic in place for bringing air vehicles through world loads. If above the ground you will be placed up to 20m above the spawnpoint of the next world.", + "searchtags": [ + "prop", + "spawn", + "friend", + "load" + ], + "requirements": [ + "None" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r47/YouAreMyPropNowWeAreHavingSoftTacosLater.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/YouAreMyPropNowWeAreHavingSoftTacosLater/", + "changelog": "- Initial release", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/.Deprecated/ChatBubbles/ChatBubbles.csproj b/.Deprecated/ChatBubbles/ChatBubbles.csproj new file mode 100644 index 0000000..5a8badc --- /dev/null +++ b/.Deprecated/ChatBubbles/ChatBubbles.csproj @@ -0,0 +1,6 @@ + + + + YouAreMineNow + + diff --git a/.Deprecated/ChatBubbles/Main.cs b/.Deprecated/ChatBubbles/Main.cs new file mode 100644 index 0000000..ac42f7d --- /dev/null +++ b/.Deprecated/ChatBubbles/Main.cs @@ -0,0 +1,236 @@ +using System.Reflection; +using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core.Player; +using ABI_RC.Core.Util; +using ABI_RC.Systems.Communications; +using ABI_RC.Systems.GameEventSystem; +using ABI_RC.Systems.RuntimeDebug; +using HarmonyLib; +using MelonLoader; +using UnityEngine; + +namespace NAK.YouAreMyPropNowWeAreHavingSoftTacosLater; + +public class ChatBubblesMod : MelonMod +{ + #region Melon Preferences + + private static readonly MelonPreferences_Category Category = + MelonPreferences.CreateCategory(nameof(YouAreMyPropNowWeAreHavingSoftTacosLater)); + + private static readonly MelonPreferences_Entry EntryChatBubblesKey = + Category.CreateEntry("keyboard_bind", KeyCode.Y, display_name: "Chat Bubbles Key", + description: "Key to open chat bubble input."); + + private static readonly MelonPreferences_Entry EntryBubbleDuration = + Category.CreateEntry("bubble_duration", 5.0f, display_name: "Bubble Duration", + description: "Base duration in seconds for chat bubbles to stay visible."); + + private static readonly MelonPreferences_Entry EntryDurationPerChar = + Category.CreateEntry("duration_per_char", 0.05f, display_name: "Duration Per Character", + description: "Additional duration per character in the message."); + + private static readonly MelonPreferences_Entry EntryPoolSize = + Category.CreateEntry("pool_size", 20, display_name: "Pool Size", + description: "Maximum number of chat bubbles that can be displayed at once."); + + private static readonly MelonPreferences_Entry EntryBubbleColor = + Category.CreateEntry("bubble_color", new Color(1.0f, 1.0f, 1.0f, 1.0f), display_name: "Bubble Color", + description: "Color of chat bubble text."); + + #endregion Melon Preferences + + #region Object Pool + + private class ChatBubble + { + public CVRPlayerEntity Player { get; set; } + public string Message { get; set; } + public float Duration { get; set; } + public float Timer { get; set; } + public bool IsActive { get; set; } + + public void Reset() + { + Player = null; + Message = string.Empty; + Duration = 0f; + Timer = 0f; + IsActive = false; + } + } + + private readonly List _chatBubblePool = []; + private readonly List _activeBubbles = []; + + private void InitializePool() + { + MelonLogger.Msg("Initializing chat bubble pool with size: " + EntryPoolSize.Value); + _chatBubblePool.Clear(); + + for (int i = 0; i < EntryPoolSize.Value; i++) + { + _chatBubblePool.Add(new ChatBubble()); + } + } + + private ChatBubble GetBubbleFromPool() + { + // First try to find an inactive bubble + foreach (var bubble in _chatBubblePool) + { + if (!bubble.IsActive) + { + bubble.Reset(); + bubble.IsActive = true; + _activeBubbles.Add(bubble); + return bubble; + } + } + + // If all bubbles are active, reuse the oldest one + if (_activeBubbles.Count > 0) + { + var oldestBubble = _activeBubbles[0]; + _activeBubbles.RemoveAt(0); + oldestBubble.Reset(); + oldestBubble.IsActive = true; + _activeBubbles.Add(oldestBubble); + return oldestBubble; + } + + // This should never happen if the pool is initialized properly + MelonLogger.Warning("No chat bubbles available in pool!"); + return null; + } + + private void ReturnBubbleToPool(ChatBubble bubble) + { + bubble.IsActive = false; + _activeBubbles.Remove(bubble); + } + + #endregion Object Pool + + #region Melon Events + + public override void OnInitializeMelon() + { + MelonLogger.Msg("Initializing Chat Bubbles Mod"); + InitializePool(); + + CVRGameEventSystem.Communications.TextChat.Local.OnMessageReceived.AddListener(OnLocalMessageReceived); + CVRGameEventSystem.Communications.TextChat.Direct.OnMessageReceived.AddListener(OnGlobalMessageReceived); + CVRGameEventSystem.Communications.TextChat.Global.OnMessageReceived.AddListener(OnDirectMessageReceived); + + HarmonyInstance.Patch( + typeof(ViewManager).GetMethod(nameof(ViewManager.SendToWorldUi), + BindingFlags.NonPublic | BindingFlags.Instance), + postfix: new HarmonyMethod(typeof(ChatBubblesMod).GetMethod(nameof(OnViewManagerSendToWorldUi), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + + MelonLogger.Msg("Chat Bubbles Mod initialized successfully"); + } + + public override void OnUpdate() + { + // Process key input to open chat + if (Input.GetKeyDown(EntryChatBubblesKey.Value)) + { + if (!CVRSyncHelper.IsConnectedToGameNetwork()) + return; + + IsInKeyboardToWriteANiceMessage = true; + ViewManager.Instance.openMenuKeyboard(string.Empty); + } + + // Update and render active chat bubbles + UpdateChatBubbles(); + } + + private void UpdateChatBubbles() + { + // Make a copy of the list to avoid issues when modifying during iteration + var bubblesToUpdate = new List(_activeBubbles); + + foreach (var bubble in bubblesToUpdate) + { + if (bubble.Player == null || bubble.Player.PuppetMaster == null) + { + ReturnBubbleToPool(bubble); + continue; + } + + bubble.Timer += Time.deltaTime; + + if (bubble.Timer >= bubble.Duration) + { + ReturnBubbleToPool(bubble); + continue; + } + + // Draw the bubble text at the player's nameplate position + var nameplatePosition = bubble.Player.PuppetMaster.GetNamePlateWorldPosition(); + // Offset slightly above the nameplate + nameplatePosition.y += 0.2f; + + RuntimeGizmos.DrawText(nameplatePosition, bubble.Message, 5, EntryBubbleColor.Value); + } + } + + #endregion Melon Events + + #region Game Events + + public static bool IsInKeyboardToWriteANiceMessage { get; set; } + + private static void OnViewManagerSendToWorldUi(string value) + { + if (!IsInKeyboardToWriteANiceMessage) return; + IsInKeyboardToWriteANiceMessage = false; + Comms_Manager.SendLocalTextMessage(value); + Comms_Manager.SendDirectTextMessage(CVRPlayerManager.Instance.NetworkPlayers[0].Uuid, value); + Comms_Manager.SendGlobalTextMessage(value); + MelonLogger.Msg("Sending message: " + value); + } + + private void OnLocalMessageReceived(CVRPlayerEntity player, string message) + { + CreateChatBubble(player, message); + MelonLogger.Msg("OnLocalMessageReceived - Player: " + player?.Username + ", Message: " + message); + } + + private void OnDirectMessageReceived(CVRPlayerEntity player, string message) + { + CreateChatBubble(player, message); + MelonLogger.Msg("OnDirectMessageReceived - Player: " + player?.Username + ", Message: " + message); + } + + private void OnGlobalMessageReceived(CVRPlayerEntity player, string message) + { + CreateChatBubble(player, message); + MelonLogger.Msg("OnGlobalMessageReceived - Player: " + player?.Username + ", Message: " + message); + } + + private void CreateChatBubble(CVRPlayerEntity player, string message) + { + if (player == null || player.PuppetMaster == null) + return; + + // Calculate duration based on message length + float baseDuration = EntryBubbleDuration.Value; + float charDuration = EntryDurationPerChar.Value * message.Length; + float totalDuration = Mathf.Clamp(baseDuration + charDuration, baseDuration, 15f); + + ChatBubble bubble = GetBubbleFromPool(); + if (bubble == null) return; + + bubble.Player = player; + bubble.Message = message; + bubble.Duration = totalDuration; + bubble.Timer = 0f; + } + + #endregion Game Events +} \ No newline at end of file diff --git a/.Deprecated/ChatBubbles/Properties/AssemblyInfo.cs b/.Deprecated/ChatBubbles/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8743650 --- /dev/null +++ b/.Deprecated/ChatBubbles/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.YouAreMyPropNowWeAreHavingSoftTacosLater.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.YouAreMyPropNowWeAreHavingSoftTacosLater))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.YouAreMyPropNowWeAreHavingSoftTacosLater))] + +[assembly: MelonInfo( + typeof(NAK.YouAreMyPropNowWeAreHavingSoftTacosLater.ChatBubblesMod), + nameof(NAK.YouAreMyPropNowWeAreHavingSoftTacosLater), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ChatBubbles" +)] + +[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.YouAreMyPropNowWeAreHavingSoftTacosLater.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/ChatBubbles/README.md b/.Deprecated/ChatBubbles/README.md new file mode 100644 index 0000000..9ddff99 --- /dev/null +++ b/.Deprecated/ChatBubbles/README.md @@ -0,0 +1,19 @@ +# YouAreMyPropNowWeAreHavingSoftTacosLater + +Lets you bring held & attached props through world loads. + +https://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO + +## Examples +https://fixupx.com/NotAKidoS/status/1910545346922422675 + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/ChatBubbles/format.json b/.Deprecated/ChatBubbles/format.json new file mode 100644 index 0000000..78c5bbc --- /dev/null +++ b/.Deprecated/ChatBubbles/format.json @@ -0,0 +1,23 @@ +{ + "_id": -1, + "name": "YouAreMyPropNowWeAreHavingSoftTacosLater", + "modversion": "1.0.0", + "gameversion": "2025r179", + "loaderversion": "0.6.1", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Lets you bring held & attached props through world loads.\nhttps://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO", + "searchtags": [ + "prop", + "spawn", + "friend", + "load" + ], + "requirements": [ + "None" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r46/YouAreMyPropNowWeAreHavingSoftTacosLater.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/YouAreMyPropNowWeAreHavingSoftTacosLater/", + "changelog": "- Initial Release", + "embedcolor": "#00FFFF" +} \ No newline at end of file diff --git a/.Deprecated/ControlToUnlockEyes/ControlToUnlockEyes.csproj b/.Deprecated/ControlToUnlockEyes/ControlToUnlockEyes.csproj new file mode 100644 index 0000000..caeac6b --- /dev/null +++ b/.Deprecated/ControlToUnlockEyes/ControlToUnlockEyes.csproj @@ -0,0 +1,9 @@ + + + + PlayerCloneAttachment + + + + + diff --git a/.Deprecated/ControlToUnlockEyes/Main.cs b/.Deprecated/ControlToUnlockEyes/Main.cs new file mode 100644 index 0000000..2afaaad --- /dev/null +++ b/.Deprecated/ControlToUnlockEyes/Main.cs @@ -0,0 +1,169 @@ +using ABI_RC.Core; +using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using ABI_RC.Systems.FaceTracking; +using ABI_RC.Systems.InputManagement; +using MelonLoader; +using UnityEngine; + +namespace NAK.ControlToUnlockEyes; + +public class ControlToUnlockEyesMod : MelonMod +{ + public override void OnInitializeMelon() + { + HarmonyInstance.Patch( + typeof(FaceTrackingManager).GetMethod(nameof(FaceTrackingManager.RegisterBuiltinModules), + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance), + postfix: new HarmonyLib.HarmonyMethod(typeof(ControlToUnlockEyesMod).GetMethod(nameof(OnPostFaceTrackingManagerRegisterBuiltinModules), + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)) + ); + } + + private static void OnPostFaceTrackingManagerRegisterBuiltinModules(FaceTrackingManager __instance) + => __instance.RegisterEyeModule(new DefaultEyeModule()); + + public class DefaultEyeModule : IEyeTrackingModule + { + private const float FixedDistance = 10f; + private bool _useFixedDistance = true; + + private readonly EyeTrackingData _eyeTrackingData = new(); + private bool _dataAvailable; + private bool _running; + + private ControllerRay _activeRay; + private Transform _rayDirectionTransform; + + private CVRHand lastInteractHand = CVRHand.Right; + + public bool Start(bool vr) + { + _running = true; + return true; + } + + public void Stop() + { + _running = false; + } + + public void Update() + { + if (!PlayerSetup.Instance) + return; + + UpdateLastInteractHand(); + UpdateFakedEyeTrackingData(); + } + + private void UpdateLastInteractHand() + { + ControllerRay leftRay = PlayerSetup.Instance.vrRayLeft; + ControllerRay rightRay = PlayerSetup.Instance.vrRayRight; + + if (!MetaPort.Instance.isUsingVr) + { + _activeRay = PlayerSetup.Instance.desktopRay; + _rayDirectionTransform = _activeRay.rayDirectionTransform; + return; + } + + bool leftAvailable = IsHandAvailable(leftRay, CVRHand.Left); + bool rightAvailable = IsHandAvailable(rightRay, CVRHand.Right); + + if (CVRInputManager.Instance.interactLeftDown && leftAvailable) + lastInteractHand = CVRHand.Left; + else if (CVRInputManager.Instance.interactRightDown && rightAvailable) + lastInteractHand = CVRHand.Right; + + _activeRay = GetLastInteractRay(); + _rayDirectionTransform = _activeRay.rayDirectionTransform; + } + + private void UpdateFakedEyeTrackingData() + { + _dataAvailable = _activeRay.CanSelectPlayersAndProps(); + if (!_dataAvailable) + return; + + _eyeTrackingData.blinking = false; + + Transform ourCameraTransform = PlayerSetup.Instance.activeCam.transform; + + Vector3 rayForward = _rayDirectionTransform.forward; + float rayDistance = _useFixedDistance ? FixedDistance : _activeRay.Hit.distance; + + // TODO: dot product check to flip direction if behind camera + + // Convert to camera-local *direction* (normalized) and multiply by selected distance so the gazePoint + // is on a sphere around the camera rather than mapped to a "square". + Vector3 localDir = ourCameraTransform.InverseTransformDirection(rayForward).normalized; + Vector3 localGazePoint = localDir * rayDistance; + + _eyeTrackingData.gazePoint = localGazePoint; + } + + private ControllerRay GetLastInteractRay() + { + if (!MetaPort.Instance.isUsingVr) + return PlayerSetup.Instance.desktopRay; + + ControllerRay leftRay = PlayerSetup.Instance.vrRayLeft; + ControllerRay rightRay = PlayerSetup.Instance.vrRayRight; + + if (lastInteractHand == CVRHand.Left && IsHandAvailable(leftRay, CVRHand.Left)) + return leftRay; + if (lastInteractHand == CVRHand.Right && IsHandAvailable(rightRay, CVRHand.Right)) + return rightRay; + + return GetBestAvailableHand(); + } + + private ControllerRay GetBestAvailableHand() + { + if (!MetaPort.Instance.isUsingVr) + return PlayerSetup.Instance.desktopRay; + + ControllerRay leftRay = PlayerSetup.Instance.vrRayLeft; + ControllerRay rightRay = PlayerSetup.Instance.vrRayRight; + + bool leftAvailable = IsHandAvailable(leftRay, CVRHand.Left); + bool rightAvailable = IsHandAvailable(rightRay, CVRHand.Right); + + if (CVRInputManager.Instance.interactLeftDown && leftAvailable) + return leftRay; + if (CVRInputManager.Instance.interactRightDown && rightAvailable) + return rightRay; + + if (lastInteractHand == CVRHand.Left && leftAvailable) + return leftRay; + if (lastInteractHand == CVRHand.Right && rightAvailable) + return rightRay; + + if (rightAvailable) return rightRay; + if (leftAvailable) return leftRay; + + return rightRay; + } + + private static bool IsHandAvailable(ControllerRay ray, CVRHand hand) + { + if (ray.grabbedObject) + return false; + + if (CVR_MenuManager.Instance.IsViewShown && + CVR_MenuManager.Instance.SelectedQuickMenuHand == hand) + return false; + + return true; + } + + public bool IsRunning() => _running; + public bool IsDataAvailable() => _dataAvailable; + public EyeTrackingData GetTrackingData() => _eyeTrackingData; + public string GetModuleName() => "None"; + public string GetModuleShortName() => "None"; + } +} \ No newline at end of file diff --git a/.Deprecated/ControlToUnlockEyes/Properties/AssemblyInfo.cs b/.Deprecated/ControlToUnlockEyes/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5396117 --- /dev/null +++ b/.Deprecated/ControlToUnlockEyes/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.ControlToUnlockEyes.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.ControlToUnlockEyes))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.ControlToUnlockEyes))] + +[assembly: MelonInfo( + typeof(NAK.ControlToUnlockEyes.ControlToUnlockEyesMod), + nameof(NAK.ControlToUnlockEyes), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ControlToUnlockEyes" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.ControlToUnlockEyes.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/ControlToUnlockEyes/README.md b/.Deprecated/ControlToUnlockEyes/README.md new file mode 100644 index 0000000..b092e40 --- /dev/null +++ b/.Deprecated/ControlToUnlockEyes/README.md @@ -0,0 +1,22 @@ +# YouAreMyPropNowWeAreHavingSoftTacosLater + +Lets you bring held, attached, and occupied props through world loads. This is configurable in the mod settings. + +https://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO + +There is special logic in place for bringing air vehicles through world loads. +If above the ground you will be placed up to 20m above the spawnpoint of the next world. + +## Examples +https://fixupx.com/NotAKidoS/status/1910545346922422675 + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/ControlToUnlockEyes/format.json b/.Deprecated/ControlToUnlockEyes/format.json new file mode 100644 index 0000000..8e68782 --- /dev/null +++ b/.Deprecated/ControlToUnlockEyes/format.json @@ -0,0 +1,23 @@ +{ + "_id": 262, + "name": "YouAreMyPropNowWeAreHavingSoftTacosLater", + "modversion": "1.0.0", + "gameversion": "2025r180", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Lets you bring held, attached, and occupied props through world loads. This is configurable in the mod settings.\nhttps://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO\n\nThere is special logic in place for bringing air vehicles through world loads. If above the ground you will be placed up to 20m above the spawnpoint of the next world.", + "searchtags": [ + "prop", + "spawn", + "friend", + "load" + ], + "requirements": [ + "None" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r47/YouAreMyPropNowWeAreHavingSoftTacosLater.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/YouAreMyPropNowWeAreHavingSoftTacosLater/", + "changelog": "- Initial release", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/.Deprecated/FuckCameras/FuckCameras.csproj b/.Deprecated/FuckCameras/FuckCameras.csproj new file mode 100644 index 0000000..5a8badc --- /dev/null +++ b/.Deprecated/FuckCameras/FuckCameras.csproj @@ -0,0 +1,6 @@ + + + + YouAreMineNow + + diff --git a/.Deprecated/FuckCameras/Main.cs b/.Deprecated/FuckCameras/Main.cs new file mode 100644 index 0000000..ecb06fb --- /dev/null +++ b/.Deprecated/FuckCameras/Main.cs @@ -0,0 +1,228 @@ +using ABI_RC.Core.Util.AssetFiltering; +using System.Reflection; +using HarmonyLib; +using MelonLoader; +using UnityEngine; + +namespace NAK.FuckCameras; + +public class FuckCamerasMod : MelonMod +{ + public override void OnInitializeMelon() + { + HarmonyInstance.Patch( + typeof(SharedFilter).GetMethod(nameof(SharedFilter.ProcessCamera), + BindingFlags.Public | BindingFlags.Static), + postfix: new HarmonyMethod(typeof(FuckCamerasMod).GetMethod(nameof(OnProcessCamera), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + } + + private static void OnProcessCamera(string collectionId, Camera camera) + => camera.gameObject.AddComponent(); + + public class FuckCameraComponent : MonoBehaviour + { + private Camera _cam; + private int _originalMask; + + private Camera _pooledCam; + private bool fuck; + + private void Awake() + { + _originalMask = _cam.cullingMask; + _cam.Reset(); + // _cam.cullingMask = _originalMask; + } + + /*private void OnPreCull() + { + MelonLogger.Msg("PreCull"); + if (!TryGetComponent(out _cam)) return; + + if (fuck) + { + // unset default layer + _originalMask &= ~(1 << 0); + _cam.cullingMask = _originalMask; + Destroy(this); + return; + } + + _originalMask = _cam.cullingMask; + _cam.cullingMask = 0; + fuck = true; + }*/ + + /*private IEnumerator OnPostRender() + { + MelonLogger.Msg("PostRender"); + // Restore the original mask if it has not changed since we set it to 0 + if (_cam.cullingMask == 0) _cam.cullingMask = _originalMask; + + _cam.enabled = false; + yield return new WaitForEndOfFrame(); + _cam.enabled = true; + + MelonLogger.Msg("FuckCameraComponent: OnPostRender called for camera: " + _cam.name); + // Destroy now that we have saved the day + enabled = false; + Destroy(this); + }*/ + } + + + + public class CameraPoolManager : MonoBehaviour + { + private static CameraPoolManager _instance; + public static CameraPoolManager Instance + { + get + { + if (_instance == null) + { + GameObject obj = new("CameraPoolManager"); + obj.SetActive(false); + _instance = obj.AddComponent(); + DontDestroyOnLoad(obj); + } + return _instance; + } + } + + private readonly List _cameraObjects = new(); + + public Camera CreatePooledCamera(Camera source) + { + var go = new GameObject("PooledCamera"); + go.SetActive(false); + var camera = go.AddComponent(); + camera.CopyFrom(source); + _cameraObjects.Add(go); + return camera; + } + + public void RestoreCameraProperties(Camera target, Camera pooledCam) + { + // target.CopyFrom(pooledCam); + CopyCameraProperties(pooledCam, target); + } + + public void ReleasePooledCamera(Camera pooledCam) + { + if (pooledCam != null) + { + var go = pooledCam.gameObject; + _cameraObjects.Remove(go); + Destroy(go); + } + } + + // Skipped known diffs: + // nearClipPlane + // farClipPlane + // fieldOfView + // aspect + // cullingMask + // useOcclusionCulling + // clearFlags + // depthTextureMode + // pixelRect + // targetTexture + + public static void CopyCameraProperties(Camera source, Camera target) + { + if (source == null || target == null) return; + + target.nearClipPlane = source.nearClipPlane; + target.farClipPlane = source.farClipPlane; + + target.fieldOfView = source.fieldOfView; + target.aspect = source.aspect; + + int cullingMask = 0; + + cullingMask = (cullingMask & ~(1 << 0)) | (source.cullingMask & (1 << 0)); + + cullingMask = (cullingMask & ~(1 << 1)) | (source.cullingMask & (1 << 1)); + cullingMask = (cullingMask & ~(1 << 2)) | (source.cullingMask & (1 << 2)); + cullingMask = (cullingMask & ~(1 << 3)) | (source.cullingMask & (1 << 3)); + cullingMask = (cullingMask & ~(1 << 4)) | (source.cullingMask & (1 << 4)); + + cullingMask = (cullingMask & ~(1 << 5)) | (source.cullingMask & (1 << 5)); + cullingMask = (cullingMask & ~(1 << 6)) | (source.cullingMask & (1 << 6)); + cullingMask = (cullingMask & ~(1 << 7)) | (source.cullingMask & (1 << 7)); + cullingMask = (cullingMask & ~(1 << 8)) | (source.cullingMask & (1 << 8)); + + cullingMask = (cullingMask & ~(1 << 9)) | (source.cullingMask & (1 << 9)); + cullingMask = (cullingMask & ~(1 << 10)) | (source.cullingMask & (1 << 10)); + cullingMask = (cullingMask & ~(1 << 11)) | (source.cullingMask & (1 << 11)); + cullingMask = (cullingMask & ~(1 << 12)) | (source.cullingMask & (1 << 12)); + cullingMask = (cullingMask & ~(1 << 13)) | (source.cullingMask & (1 << 13)); + cullingMask = (cullingMask & ~(1 << 14)) | (source.cullingMask & (1 << 14)); + cullingMask = (cullingMask & ~(1 << 15)) | (source.cullingMask & (1 << 15)); + cullingMask = (cullingMask & ~(1 << 16)) | (source.cullingMask & (1 << 16)); + cullingMask = (cullingMask & ~(1 << 17)) | (source.cullingMask & (1 << 17)); + cullingMask = (cullingMask & ~(1 << 18)) | (source.cullingMask & (1 << 18)); + cullingMask = (cullingMask & ~(1 << 19)) | (source.cullingMask & (1 << 19)); + cullingMask = (cullingMask & ~(1 << 20)) | (source.cullingMask & (1 << 20)); + cullingMask = (cullingMask & ~(1 << 21)) | (source.cullingMask & (1 << 21)); + cullingMask = (cullingMask & ~(1 << 22)) | (source.cullingMask & (1 << 22)); + cullingMask = (cullingMask & ~(1 << 23)) | (source.cullingMask & (1 << 23)); + cullingMask = (cullingMask & ~(1 << 24)) | (source.cullingMask & (1 << 24)); + cullingMask = (cullingMask & ~(1 << 25)) | (source.cullingMask & (1 << 25)); + cullingMask = (cullingMask & ~(1 << 26)) | (source.cullingMask & (1 << 26)); + cullingMask = (cullingMask & ~(1 << 27)) | (source.cullingMask & (1 << 27)); + cullingMask = (cullingMask & ~(1 << 28)) | (source.cullingMask & (1 << 28)); + cullingMask = (cullingMask & ~(1 << 29)) | (source.cullingMask & (1 << 29)); + cullingMask = (cullingMask & ~(1 << 30)) | (source.cullingMask & (1 << 30)); + cullingMask = (cullingMask & ~(1 << 31)) | (source.cullingMask & (1 << 31)); + + target.cullingMask = cullingMask; + + target.clearFlags = source.clearFlags; + target.depthTextureMode = source.depthTextureMode; + target.useOcclusionCulling = source.useOcclusionCulling; + target.pixelRect = source.pixelRect; + target.targetTexture = source.targetTexture; + + target.renderingPath = source.renderingPath; + target.allowHDR = source.allowHDR; + target.allowMSAA = source.allowMSAA; + target.allowDynamicResolution = source.allowDynamicResolution; + target.forceIntoRenderTexture = source.forceIntoRenderTexture; + target.orthographic = source.orthographic; + target.orthographicSize = source.orthographicSize; + target.depth = source.depth; + target.eventMask = source.eventMask; + target.layerCullSpherical = source.layerCullSpherical; + target.backgroundColor = source.backgroundColor; + target.clearStencilAfterLightingPass = source.clearStencilAfterLightingPass; + target.usePhysicalProperties = source.usePhysicalProperties; + // target.iso = source.iso; + // target.shutterSpeed = source.shutterSpeed; + // target.aperture = source.aperture; + // target.focusDistance = source.focusDistance; + // target.bladeCount = source.bladeCount; + // target.curvature = source.curvature; + // target.barrelClipping = source.barrelClipping; + // target.anamorphism = source.anamorphism; + // target.enabled = source.enabled; + // target.transform.position = source.transform.position; + // target.transform.rotation = source.transform.rotation; + // target.transform.localScale = source.transform.localScale; + target.focalLength = source.focalLength; + target.sensorSize = source.sensorSize; + target.lensShift = source.lensShift; + target.gateFit = source.gateFit; + target.rect = source.rect; + + target.targetDisplay = source.targetDisplay; + target.stereoSeparation = source.stereoSeparation; + target.stereoConvergence = source.stereoConvergence; + target.stereoTargetEye = source.stereoTargetEye; + } + } +} diff --git a/.Deprecated/FuckCameras/Properties/AssemblyInfo.cs b/.Deprecated/FuckCameras/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7165e1a --- /dev/null +++ b/.Deprecated/FuckCameras/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.FuckCameras.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.FuckCameras))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.FuckCameras))] + +[assembly: MelonInfo( + typeof(NAK.FuckCameras.FuckCamerasMod), + nameof(NAK.FuckCameras), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/FuckCameras" +)] + +[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.FuckCameras.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/FuckCameras/README.md b/.Deprecated/FuckCameras/README.md new file mode 100644 index 0000000..9ddff99 --- /dev/null +++ b/.Deprecated/FuckCameras/README.md @@ -0,0 +1,19 @@ +# YouAreMyPropNowWeAreHavingSoftTacosLater + +Lets you bring held & attached props through world loads. + +https://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO + +## Examples +https://fixupx.com/NotAKidoS/status/1910545346922422675 + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/FuckCameras/format.json b/.Deprecated/FuckCameras/format.json new file mode 100644 index 0000000..78c5bbc --- /dev/null +++ b/.Deprecated/FuckCameras/format.json @@ -0,0 +1,23 @@ +{ + "_id": -1, + "name": "YouAreMyPropNowWeAreHavingSoftTacosLater", + "modversion": "1.0.0", + "gameversion": "2025r179", + "loaderversion": "0.6.1", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Lets you bring held & attached props through world loads.\nhttps://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO", + "searchtags": [ + "prop", + "spawn", + "friend", + "load" + ], + "requirements": [ + "None" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r46/YouAreMyPropNowWeAreHavingSoftTacosLater.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/YouAreMyPropNowWeAreHavingSoftTacosLater/", + "changelog": "- Initial Release", + "embedcolor": "#00FFFF" +} \ No newline at end of file diff --git a/.Deprecated/FuckCohtml2/FuckCohtml2.csproj b/.Deprecated/FuckCohtml2/FuckCohtml2.csproj new file mode 100644 index 0000000..5a8badc --- /dev/null +++ b/.Deprecated/FuckCohtml2/FuckCohtml2.csproj @@ -0,0 +1,6 @@ + + + + YouAreMineNow + + diff --git a/.Deprecated/FuckCohtml2/Main.cs b/.Deprecated/FuckCohtml2/Main.cs new file mode 100644 index 0000000..fa69e9f --- /dev/null +++ b/.Deprecated/FuckCohtml2/Main.cs @@ -0,0 +1,57 @@ +using System.Reflection; +using ABI_RC.Core.UI; +using HarmonyLib; +using MelonLoader; + +namespace NAK.FuckCohtml2; + +public class FuckCohtml2Mod : MelonMod +{ + private static readonly MelonPreferences_Category Category = + MelonPreferences.CreateCategory(nameof(FuckCohtml2)); + + private static readonly MelonPreferences_Entry EntryFixShouldAdvance = + Category.CreateEntry( + identifier: "fix_should_advance", + true, + display_name: "Fix ShouldAdvance", + description: "Fix CohtmlControlledView.ShouldAdvance to respect the Enabled property."); + + private static readonly MelonPreferences_Entry EntryFixShouldRender = + Category.CreateEntry( + identifier: "fix_should_render", + true, + display_name: "Fix ShouldRender", + description: "Fix CohtmlControlledView.ShouldRender to respect the Enabled property."); + + public override void OnInitializeMelon() + { + PatchProperty(nameof(CohtmlControlledView.ShouldAdvance), nameof(OnShouldAdvance)); + PatchProperty(nameof(CohtmlControlledView.ShouldRender), nameof(OnShouldRender)); + } + + private void PatchProperty(string propertyName, string handlerName) + { + PropertyInfo prop = typeof(CohtmlControlledView).GetProperty(propertyName, + BindingFlags.Public | BindingFlags.Instance); + MethodInfo getter = prop!.GetGetMethod(true); + + MethodInfo postfixMethod = typeof(FuckCohtml2Mod).GetMethod(handlerName, + BindingFlags.NonPublic | BindingFlags.Static, null, + [typeof(object), typeof(bool).MakeByRefType()], null); + + HarmonyInstance.Patch(getter, postfix: new HarmonyMethod(postfixMethod)); + } + + private static void OnShouldAdvance(object __instance, ref bool __result) + { + if (!EntryFixShouldAdvance.Value) return; + if (__instance is CohtmlControlledView inst) __result &= inst.Enabled; + } + + private static void OnShouldRender(object __instance, ref bool __result) + { + if (!EntryFixShouldRender.Value) return; + if (__instance is CohtmlControlledView inst) __result &= inst.Enabled; + } +} \ No newline at end of file diff --git a/.Deprecated/FuckCohtml2/Properties/AssemblyInfo.cs b/.Deprecated/FuckCohtml2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..334d3fd --- /dev/null +++ b/.Deprecated/FuckCohtml2/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.FuckCohtml2.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.FuckCohtml2))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.FuckCohtml2))] + +[assembly: MelonInfo( + typeof(NAK.FuckCohtml2.FuckCohtml2Mod), + nameof(NAK.FuckCohtml2), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/FuckCohtml2" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.FuckCohtml2.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/FuckCohtml2/README.md b/.Deprecated/FuckCohtml2/README.md new file mode 100644 index 0000000..9ddff99 --- /dev/null +++ b/.Deprecated/FuckCohtml2/README.md @@ -0,0 +1,19 @@ +# YouAreMyPropNowWeAreHavingSoftTacosLater + +Lets you bring held & attached props through world loads. + +https://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO + +## Examples +https://fixupx.com/NotAKidoS/status/1910545346922422675 + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/FuckCohtml2/format.json b/.Deprecated/FuckCohtml2/format.json new file mode 100644 index 0000000..78c5bbc --- /dev/null +++ b/.Deprecated/FuckCohtml2/format.json @@ -0,0 +1,23 @@ +{ + "_id": -1, + "name": "YouAreMyPropNowWeAreHavingSoftTacosLater", + "modversion": "1.0.0", + "gameversion": "2025r179", + "loaderversion": "0.6.1", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Lets you bring held & attached props through world loads.\nhttps://youtu.be/9P6Jeh-VN58?si=eXTPGyKB_0wq1gZO", + "searchtags": [ + "prop", + "spawn", + "friend", + "load" + ], + "requirements": [ + "None" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r46/YouAreMyPropNowWeAreHavingSoftTacosLater.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/YouAreMyPropNowWeAreHavingSoftTacosLater/", + "changelog": "- Initial Release", + "embedcolor": "#00FFFF" +} \ No newline at end of file diff --git a/.Deprecated/FuckOffUICamera/Properties/AssemblyInfo.cs b/.Deprecated/FuckOffUICamera/Properties/AssemblyInfo.cs index b7a9e9f..8e48465 100644 --- a/.Deprecated/FuckOffUICamera/Properties/AssemblyInfo.cs +++ b/.Deprecated/FuckOffUICamera/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ using System.Reflection; downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/FuckOffUICamera" )] -[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")] +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] [assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] [assembly: MelonColor(255, 246, 25, 99)] // red-pink diff --git a/.Deprecated/IFUCKINGHATECAMERAS/IFUCKINGHATECAMERAS.csproj b/.Deprecated/IFUCKINGHATECAMERAS/IFUCKINGHATECAMERAS.csproj new file mode 100644 index 0000000..5a8badc --- /dev/null +++ b/.Deprecated/IFUCKINGHATECAMERAS/IFUCKINGHATECAMERAS.csproj @@ -0,0 +1,6 @@ + + + + YouAreMineNow + + diff --git a/.Deprecated/IFUCKINGHATECAMERAS/Main.cs b/.Deprecated/IFUCKINGHATECAMERAS/Main.cs new file mode 100644 index 0000000..74307c2 --- /dev/null +++ b/.Deprecated/IFUCKINGHATECAMERAS/Main.cs @@ -0,0 +1,39 @@ +using ABI_RC.Core.Player; +using ABI_RC.Core.Util.AnimatorManager; +using ABI_RC.Systems.GameEventSystem; +using ABI.CCK.Components; +using MelonLoader; +using UnityEngine; + +namespace NAK.IFUCKINGHATECAMERAS; + +public class IFUCKINGHATECAMERASMod : MelonMod +{ + private static readonly MelonPreferences_Category Category = + MelonPreferences.CreateCategory(nameof(IFUCKINGHATECAMERAS)); + + private static readonly MelonPreferences_Entry EntryRunHack = + Category.CreateEntry( + identifier: "run_hack", + true, + display_name: "Run Camera Hack (Avatars Only)?", + description: "Should the camera hack run? Btw I fucking hate cameras."); + + public override void OnInitializeMelon() + { + CVRGameEventSystem.Avatar.OnRemoteAvatarLoad.AddListener(OnRemoteAvatarLoad); + } + + private static void OnRemoteAvatarLoad(CVRPlayerEntity playerEntity, CVRAvatar avatar) + { + if (!EntryRunHack.Value) return; + + // HACK: Fixes a native crash (animating camera off on first frame) due to culling in specific worlds. + // I am unsure the root cause, but the local player doesn't crash, and this is similar to what that does. + + AvatarAnimatorManager AnimatorManager = playerEntity.PuppetMaster.AnimatorManager; + AnimatorManager.Animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; // Set culling mode to always animate + AnimatorManager.Animator.Update(0f); // Update the animator to force it to do the first frame + AnimatorManager.Animator.cullingMode = AnimatorCullingMode.CullUpdateTransforms; // Set to cull update transforms + } +} \ No newline at end of file diff --git a/.Deprecated/IFUCKINGHATECAMERAS/Properties/AssemblyInfo.cs b/.Deprecated/IFUCKINGHATECAMERAS/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4fefcd7 --- /dev/null +++ b/.Deprecated/IFUCKINGHATECAMERAS/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.IFUCKINGHATECAMERAS.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.IFUCKINGHATECAMERAS))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.IFUCKINGHATECAMERAS))] + +[assembly: MelonInfo( + typeof(NAK.IFUCKINGHATECAMERAS.IFUCKINGHATECAMERASMod), + nameof(NAK.IFUCKINGHATECAMERAS), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/IFUCKINGHATECAMERAS" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.IFUCKINGHATECAMERAS.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/IFUCKINGHATECAMERAS/README.md b/.Deprecated/IFUCKINGHATECAMERAS/README.md new file mode 100644 index 0000000..7ff0922 --- /dev/null +++ b/.Deprecated/IFUCKINGHATECAMERAS/README.md @@ -0,0 +1,19 @@ +# Tinyboard + +Makes the keyboard small and smart. + +Few small tweaks to the keyboard: +- Shrinks the keyboard to a size that isn't fit for grandma. +- Adjusts keyboard placement logic to align with the menu that it spawns from. +- Enforces a title on the keyboard input if one is not found. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/IFUCKINGHATECAMERAS/format.json b/.Deprecated/IFUCKINGHATECAMERAS/format.json new file mode 100644 index 0000000..da65a56 --- /dev/null +++ b/.Deprecated/IFUCKINGHATECAMERAS/format.json @@ -0,0 +1,23 @@ +{ + "_id": -1, + "name": "Tinyboard", + "modversion": "1.0.0", + "gameversion": "2025r180", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Few small tweaks to the keyboard:\n- Shrinks the keyboard to a size that isn't fit for grandma.\n- Adjusts keyboard placement logic to align with the menu that it spawns from.\n- Enforces a title on the keyboard input if one is not found.", + "searchtags": [ + "keyboard", + "menu", + "ui", + "input" + ], + "requirements": [ + "None" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r47/Tinyboard.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/Tinyboard/", + "changelog": "- Initial release", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/KeepVelocityOnExitFlight/KeepVelocityOnExitFlight.csproj b/.Deprecated/KeepVelocityOnExitFlight/KeepVelocityOnExitFlight.csproj similarity index 100% rename from KeepVelocityOnExitFlight/KeepVelocityOnExitFlight.csproj rename to .Deprecated/KeepVelocityOnExitFlight/KeepVelocityOnExitFlight.csproj diff --git a/KeepVelocityOnExitFlight/Main.cs b/.Deprecated/KeepVelocityOnExitFlight/Main.cs similarity index 93% rename from KeepVelocityOnExitFlight/Main.cs rename to .Deprecated/KeepVelocityOnExitFlight/Main.cs index a9dc414..994e8bd 100644 --- a/KeepVelocityOnExitFlight/Main.cs +++ b/.Deprecated/KeepVelocityOnExitFlight/Main.cs @@ -1,7 +1,5 @@ -using System.Reflection; -using ABI_RC.Core.Util.AnimatorManager; +using System.Reflection; using ABI_RC.Systems.Movement; -using ABI.CCK.Scripts; using HarmonyLib; using MelonLoader; using UnityEngine; diff --git a/KeepVelocityOnExitFlight/Properties/AssemblyInfo.cs b/.Deprecated/KeepVelocityOnExitFlight/Properties/AssemblyInfo.cs similarity index 98% rename from KeepVelocityOnExitFlight/Properties/AssemblyInfo.cs rename to .Deprecated/KeepVelocityOnExitFlight/Properties/AssemblyInfo.cs index e51a838..e9204cd 100644 --- a/KeepVelocityOnExitFlight/Properties/AssemblyInfo.cs +++ b/.Deprecated/KeepVelocityOnExitFlight/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -using MelonLoader; +using MelonLoader; using NAK.KeepVelocityOnExitFlight.Properties; using System.Reflection; diff --git a/KeepVelocityOnExitFlight/README.md b/.Deprecated/KeepVelocityOnExitFlight/README.md similarity index 100% rename from KeepVelocityOnExitFlight/README.md rename to .Deprecated/KeepVelocityOnExitFlight/README.md diff --git a/KeepVelocityOnExitFlight/format.json b/.Deprecated/KeepVelocityOnExitFlight/format.json similarity index 100% rename from KeepVelocityOnExitFlight/format.json rename to .Deprecated/KeepVelocityOnExitFlight/format.json diff --git a/LazyPrune/LazyPrune.csproj b/.Deprecated/LazyPrune/LazyPrune.csproj similarity index 100% rename from LazyPrune/LazyPrune.csproj rename to .Deprecated/LazyPrune/LazyPrune.csproj diff --git a/LazyPrune/Main.cs b/.Deprecated/LazyPrune/Main.cs similarity index 99% rename from LazyPrune/Main.cs rename to .Deprecated/LazyPrune/Main.cs index 019d2f4..6c2f690 100644 --- a/LazyPrune/Main.cs +++ b/.Deprecated/LazyPrune/Main.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using ABI_RC.Core.EventSystem; using ABI_RC.Core.IO; using ABI_RC.Core.Networking.API.Responses; diff --git a/LazyPrune/Properties/AssemblyInfo.cs b/.Deprecated/LazyPrune/Properties/AssemblyInfo.cs similarity index 98% rename from LazyPrune/Properties/AssemblyInfo.cs rename to .Deprecated/LazyPrune/Properties/AssemblyInfo.cs index 169f34e..299ce21 100644 --- a/LazyPrune/Properties/AssemblyInfo.cs +++ b/.Deprecated/LazyPrune/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -using MelonLoader; +using MelonLoader; using NAK.LazyPrune.Properties; using System.Reflection; diff --git a/LazyPrune/README.md b/.Deprecated/LazyPrune/README.md similarity index 100% rename from LazyPrune/README.md rename to .Deprecated/LazyPrune/README.md diff --git a/LazyPrune/format.json b/.Deprecated/LazyPrune/format.json similarity index 100% rename from LazyPrune/format.json rename to .Deprecated/LazyPrune/format.json diff --git a/.Deprecated/SuperAwesomeMod/DepthCameraFix.cs b/.Deprecated/SuperAwesomeMod/DepthCameraFix.cs index 933cfa6..97fd404 100644 --- a/.Deprecated/SuperAwesomeMod/DepthCameraFix.cs +++ b/.Deprecated/SuperAwesomeMod/DepthCameraFix.cs @@ -3,22 +3,6 @@ using UnityEngine; using UnityEngine.Rendering; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine; -using UnityEngine.Rendering; - -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine; -using UnityEngine.Rendering; - [RequireComponent(typeof(Camera))] public class DepthTextureFix : MonoBehaviour { diff --git a/.Deprecated/SuperAwesomeMod/Interaction/CVRPlayerHand.cs b/.Deprecated/SuperAwesomeMod/Interaction/CVRPlayerHand.cs index 949b638..42fbfd3 100644 --- a/.Deprecated/SuperAwesomeMod/Interaction/CVRPlayerHand.cs +++ b/.Deprecated/SuperAwesomeMod/Interaction/CVRPlayerHand.cs @@ -1,8 +1,6 @@ using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.InteractionSystem.Base; -using ABI_RC.Systems.InputManagement; using UnityEngine; -using UnityEngine.Serialization; namespace ABI_RC.Core.Player.Interaction { diff --git a/.Deprecated/SuperAwesomeMod/Interaction/CVRPlayerInteractionManager.cs b/.Deprecated/SuperAwesomeMod/Interaction/CVRPlayerInteractionManager.cs index 2c0d56e..b31be75 100644 --- a/.Deprecated/SuperAwesomeMod/Interaction/CVRPlayerInteractionManager.cs +++ b/.Deprecated/SuperAwesomeMod/Interaction/CVRPlayerInteractionManager.cs @@ -1,214 +1,214 @@ -using ABI_RC.Core.Player.Interaction.RaycastImpl; -using ABI_RC.Core.Savior; -using ABI_RC.Systems.InputManagement; -using UnityEngine; - -namespace ABI_RC.Core.Player.Interaction -{ - public class CVRPlayerInteractionManager : MonoBehaviour - { - #region Singleton - - public static CVRPlayerInteractionManager Instance { get; private set; } - - #endregion Singleton - - #region Serialized Fields - - [Header("Hand Components")] - [SerializeField] private CVRPlayerHand handVrLeft; - [SerializeField] private CVRPlayerHand handVrRight; - [SerializeField] private CVRPlayerHand handDesktopRight; // Desktop does not have a left hand - - [Header("Raycast Transforms")] - [SerializeField] private Transform raycastTransformVrRight; - [SerializeField] private Transform raycastTransformVrLeft; - [SerializeField] private Transform raycastTransformDesktopRight; - - [Header("Settings")] - [SerializeField] private bool interactionEnabled = true; - [SerializeField] private LayerMask interactionLayerMask = -1; // Default to all layers, will be filtered - - #endregion Serialized Fields - - #region Properties - - private CVRPlayerHand _rightHand; - private CVRPlayerHand _leftHand; - - private CVRPlayerRaycaster _rightRaycaster; - private CVRPlayerRaycaster _leftRaycaster; - - private CVRRaycastResult _rightRaycastResult; - private CVRRaycastResult _leftRaycastResult; - - // Input handler - private CVRPlayerInputHandler _inputHandler; - - // Interaction flags - public bool InteractionEnabled - { - get => interactionEnabled; - set => interactionEnabled = value; - } - - #endregion Properties - - #region Unity Events - - private void Awake() - { - if (Instance != null && Instance != this) - { - Destroy(gameObject); - return; - } - Instance = this; - - // Create the input handler - _inputHandler = gameObject.AddComponent(); - } - - private void Start() - { - // Setup interaction for current device mode - SetupInteractionForDeviceMode(); - - // Listen for VR mode changes - MetaPort.Instance.onVRModeSwitch.AddListener(SetupInteractionForDeviceMode); - } - - private void Update() - { - if (!interactionEnabled) - return; - - // Process right hand - if (_rightRaycaster != null) - { - // Determine raycast flags based on current mode - CVRPlayerRaycaster.RaycastFlags flags = DetermineRaycastFlags(_rightHand); - - // Get raycast results - _rightRaycastResult = _rightRaycaster.GetRaycastResults(flags); - - // Process input based on raycast results - _inputHandler.ProcessInput(CVRHand.Right, _rightRaycastResult); - } - - // Process left hand (if available) - if (_leftRaycaster != null) - { - // Determine raycast flags based on current mode - CVRPlayerRaycaster.RaycastFlags flags = DetermineRaycastFlags(_leftHand); - - // Get raycast results - _leftRaycastResult = _leftRaycaster.GetRaycastResults(flags); - - // Process input based on raycast results - _inputHandler.ProcessInput(CVRHand.Left, _leftRaycastResult); - } - } - - private void OnDestroy() - { - // Clean up event listener - if (MetaPort.Instance != null) - MetaPort.Instance.onVRModeSwitch.RemoveListener(SetupInteractionForDeviceMode); - } - - #endregion Unity Events - - #region Public Methods - - /// - /// Register a custom tool mode - /// - public void RegisterCustomToolMode(System.Action callback) - { - _inputHandler.RegisterCustomTool(callback); - } - - /// - /// Unregister the current custom tool mode - /// - public void UnregisterCustomToolMode() - { - _inputHandler.UnregisterCustomTool(); - } - - /// - /// Set the interaction mode - /// - public void SetInteractionMode(CVRPlayerInputHandler.InteractionMode mode) - { - _inputHandler.SetInteractionMode(mode); - } - - /// - /// Get the raycast result for a specific hand - /// - public CVRRaycastResult GetRaycastResult(CVRHand hand) - { - return hand == CVRHand.Left ? _leftRaycastResult : _rightRaycastResult; - } - - #endregion Public Methods - - #region Private Methods - - private void SetupInteractionForDeviceMode() - { - bool isVr = MetaPort.Instance.isUsingVr; - - if (isVr) - { - // VR mode - _rightHand = handVrRight; - _leftHand = handVrLeft; - - // VR uses the controller transform for raycasting - _rightRaycaster = new CVRPlayerRaycasterTransform(raycastTransformVrRight); - _leftRaycaster = new CVRPlayerRaycasterTransform(raycastTransformVrLeft); - } - else - { - // Desktop mode - _rightHand = handDesktopRight; - _leftHand = null; - - // Desktop uses the mouse position for raycasting when unlocked - Camera desktopCamera = PlayerSetup.Instance.desktopCam; - _rightRaycaster = new CVRPlayerRaycasterMouse(raycastTransformDesktopRight, desktopCamera); - _leftRaycaster = null; - } - - // Set the layer mask for raycasters - if (_rightRaycaster != null) - _rightRaycaster.SetLayerMask(interactionLayerMask); - - if (_leftRaycaster != null) - _leftRaycaster.SetLayerMask(interactionLayerMask); - } - - private static CVRPlayerRaycaster.RaycastFlags DetermineRaycastFlags(CVRPlayerHand hand) - { - // Default to all flags - CVRPlayerRaycaster.RaycastFlags flags = CVRPlayerRaycaster.RaycastFlags.All; - - // Check if hand is holding a pickup - if (hand != null && hand.IsHoldingObject) - { - // When holding an object, only check for COHTML interaction - flags = CVRPlayerRaycaster.RaycastFlags.CohtmlInteract; - } - - // Could add more conditional flag adjustments here based on the current mode - // For example, in a teleport tool mode, you might only want world hits - - return flags; - } - - #endregion Private Methods - } -} \ No newline at end of file +// using ABI_RC.Core.Player.Interaction.RaycastImpl; +// using ABI_RC.Core.Savior; +// using ABI_RC.Systems.InputManagement; +// using UnityEngine; +// +// namespace ABI_RC.Core.Player.Interaction +// { +// public class CVRPlayerInteractionManager : MonoBehaviour +// { +// #region Singleton +// +// public static CVRPlayerInteractionManager Instance { get; private set; } +// +// #endregion Singleton +// +// #region Serialized Fields +// +// [Header("Hand Components")] +// [SerializeField] private CVRPlayerHand handVrLeft; +// [SerializeField] private CVRPlayerHand handVrRight; +// [SerializeField] private CVRPlayerHand handDesktopRight; // Desktop does not have a left hand +// +// [Header("Raycast Transforms")] +// [SerializeField] private Transform raycastTransformVrRight; +// [SerializeField] private Transform raycastTransformVrLeft; +// [SerializeField] private Transform raycastTransformDesktopRight; +// +// [Header("Settings")] +// [SerializeField] private bool interactionEnabled = true; +// [SerializeField] private LayerMask interactionLayerMask = -1; // Default to all layers, will be filtered +// +// #endregion Serialized Fields +// +// #region Properties +// +// private CVRPlayerHand _rightHand; +// private CVRPlayerHand _leftHand; +// +// private CVRPlayerRaycaster _rightRaycaster; +// private CVRPlayerRaycaster _leftRaycaster; +// +// private CVRRaycastResult _rightRaycastResult; +// private CVRRaycastResult _leftRaycastResult; +// +// // Input handler +// private CVRPlayerInputHandler _inputHandler; +// +// // Interaction flags +// public bool InteractionEnabled +// { +// get => interactionEnabled; +// set => interactionEnabled = value; +// } +// +// #endregion Properties +// +// #region Unity Events +// +// private void Awake() +// { +// if (Instance != null && Instance != this) +// { +// Destroy(gameObject); +// return; +// } +// Instance = this; +// +// // Create the input handler +// _inputHandler = gameObject.AddComponent(); +// } +// +// private void Start() +// { +// // Setup interaction for current device mode +// SetupInteractionForDeviceMode(); +// +// // Listen for VR mode changes +// MetaPort.Instance.onVRModeSwitch.AddListener(SetupInteractionForDeviceMode); +// } +// +// private void Update() +// { +// if (!interactionEnabled) +// return; +// +// // Process right hand +// if (_rightRaycaster != null) +// { +// // Determine raycast flags based on current mode +// CVRPlayerRaycaster.RaycastFlags flags = DetermineRaycastFlags(_rightHand); +// +// // Get raycast results +// _rightRaycastResult = _rightRaycaster.GetRaycastResults(flags); +// +// // Process input based on raycast results +// _inputHandler.ProcessInput(CVRHand.Right, _rightRaycastResult); +// } +// +// // Process left hand (if available) +// if (_leftRaycaster != null) +// { +// // Determine raycast flags based on current mode +// CVRPlayerRaycaster.RaycastFlags flags = DetermineRaycastFlags(_leftHand); +// +// // Get raycast results +// _leftRaycastResult = _leftRaycaster.GetRaycastResults(flags); +// +// // Process input based on raycast results +// _inputHandler.ProcessInput(CVRHand.Left, _leftRaycastResult); +// } +// } +// +// private void OnDestroy() +// { +// // Clean up event listener +// if (MetaPort.Instance != null) +// MetaPort.Instance.onVRModeSwitch.RemoveListener(SetupInteractionForDeviceMode); +// } +// +// #endregion Unity Events +// +// #region Public Methods +// +// /// +// /// Register a custom tool mode +// /// +// public void RegisterCustomToolMode(System.Action callback) +// { +// _inputHandler.RegisterCustomTool(callback); +// } +// +// /// +// /// Unregister the current custom tool mode +// /// +// public void UnregisterCustomToolMode() +// { +// _inputHandler.UnregisterCustomTool(); +// } +// +// /// +// /// Set the interaction mode +// /// +// public void SetInteractionMode(CVRPlayerInputHandler.InteractionMode mode) +// { +// _inputHandler.SetInteractionMode(mode); +// } +// +// /// +// /// Get the raycast result for a specific hand +// /// +// public CVRRaycastResult GetRaycastResult(CVRHand hand) +// { +// return hand == CVRHand.Left ? _leftRaycastResult : _rightRaycastResult; +// } +// +// #endregion Public Methods +// +// #region Private Methods +// +// private void SetupInteractionForDeviceMode() +// { +// bool isVr = MetaPort.Instance.isUsingVr; +// +// if (isVr) +// { +// // VR mode +// _rightHand = handVrRight; +// _leftHand = handVrLeft; +// +// // VR uses the controller transform for raycasting +// _rightRaycaster = new CVRPlayerRaycasterTransform(raycastTransformVrRight); +// _leftRaycaster = new CVRPlayerRaycasterTransform(raycastTransformVrLeft); +// } +// else +// { +// // Desktop mode +// _rightHand = handDesktopRight; +// _leftHand = null; +// +// // Desktop uses the mouse position for raycasting when unlocked +// Camera desktopCamera = PlayerSetup.Instance.desktopCam; +// _rightRaycaster = new CVRPlayerRaycasterMouse(raycastTransformDesktopRight, desktopCamera); +// _leftRaycaster = null; +// } +// +// // Set the layer mask for raycasters +// if (_rightRaycaster != null) +// _rightRaycaster.SetLayerMask(interactionLayerMask); +// +// if (_leftRaycaster != null) +// _leftRaycaster.SetLayerMask(interactionLayerMask); +// } +// +// private static CVRPlayerRaycaster.RaycastFlags DetermineRaycastFlags(CVRPlayerHand hand) +// { +// // Default to all flags +// CVRPlayerRaycaster.RaycastFlags flags = CVRPlayerRaycaster.RaycastFlags.All; +// +// // Check if hand is holding a pickup +// if (hand != null && hand.IsHoldingObject) +// { +// // When holding an object, only check for COHTML interaction +// flags = CVRPlayerRaycaster.RaycastFlags.CohtmlInteract; +// } +// +// // Could add more conditional flag adjustments here based on the current mode +// // For example, in a teleport tool mode, you might only want world hits +// +// return flags; +// } +// +// #endregion Private Methods +// } +// } \ No newline at end of file diff --git a/.Deprecated/SuperAwesomeMod/Interaction/Components/CVRCanvasWrapper.cs b/.Deprecated/SuperAwesomeMod/Interaction/Components/CVRCanvasWrapper.cs index 2ec46bd..382487b 100644 --- a/.Deprecated/SuperAwesomeMod/Interaction/Components/CVRCanvasWrapper.cs +++ b/.Deprecated/SuperAwesomeMod/Interaction/Components/CVRCanvasWrapper.cs @@ -1,121 +1,121 @@ -using ABI_RC.Core.Base; -using ABI_RC.Core.Player; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -namespace NAK.SuperAwesomeMod.Components -{ - public class CVRCanvasWrapper : MonoBehaviour - { - public bool IsInteractable = true; - public float MaxInteractDistance = 10f; - - private Canvas _canvas; - private GraphicRaycaster _graphicsRaycaster; - private static readonly List _raycastResults = new(); - private static readonly PointerEventData _pointerEventData = new(EventSystem.current); - - private static Selectable _workingSelectable; - private Camera _camera; - private RectTransform _rectTransform; - - #region Unity Events - - private void Awake() - { - if (!TryGetComponent(out _canvas) - || _canvas.renderMode != RenderMode.WorldSpace) - { - IsInteractable = false; - return; - } - - _rectTransform = _canvas.GetComponent(); - } - - private void Start() - { - _graphicsRaycaster = _canvas.gameObject.AddComponent(); - _camera = PlayerSetup.Instance.activeCam; - _canvas.worldCamera = _camera; - } - - #endregion Unity Events - - #region Public Methods - - public bool GetGraphicsHit(Ray worldRay, out RaycastResult result) - { - result = default; - - if (!IsInteractable || _camera == null) return false; - - // Get the plane of the canvas - Plane canvasPlane = new(transform.forward, transform.position); - - // Find where the ray intersects the canvas plane - if (!canvasPlane.Raycast(worldRay, out float distance)) - return false; - - // Get the world point of intersection - Vector3 worldHitPoint = worldRay.origin + worldRay.direction * distance; - - // Check if hit point is within max interaction distance - if (Vector3.Distance(worldRay.origin, worldHitPoint) > MaxInteractDistance) - return false; - - // Check if hit point is within canvas bounds - Vector3 localHitPoint = transform.InverseTransformPoint(worldHitPoint); - Rect canvasRect = _rectTransform.rect; - if (!canvasRect.Contains(new Vector2(localHitPoint.x, localHitPoint.y))) - return false; - - // Convert world hit point to screen space - Vector2 screenPoint = _camera.WorldToScreenPoint(worldHitPoint); - - // Update pointer event data - _pointerEventData.position = screenPoint; - _pointerEventData.delta = Vector2.zero; - - // Clear previous results and perform raycast - _raycastResults.Clear(); - _graphicsRaycaster.Raycast(_pointerEventData, _raycastResults); - - // Early out if no hits - if (_raycastResults.Count == 0) - { - //Debug.Log($"No hits on canvas {_canvas.name}"); - return false; - } - - // Find first valid interactive UI element - foreach (RaycastResult hit in _raycastResults) - { - if (!hit.isValid) - { - //Debug.Log($"Invalid hit on canvas {_canvas.name}"); - continue; - } - - // Check if the hit object has a Selectable component and is interactable - GameObject hitObject = hit.gameObject; - if (!hitObject.TryGetComponent(out _workingSelectable) - || !_workingSelectable.interactable) - { - //Debug.Log($"Non-interactable hit on canvas {_canvas.name} - {hitObject.name}"); - continue; - } - - //Debug.Log($"Hit on canvas {_canvas.name} with {hitObject.name}"); - - result = hit; - return true; - } - - return false; - } - - #endregion Public Methods - } -} \ No newline at end of file +// using ABI_RC.Core.Base; +// using ABI_RC.Core.Player; +// using UnityEngine; +// using UnityEngine.EventSystems; +// using UnityEngine.UI; +// +// namespace NAK.SuperAwesomeMod.Components +// { +// public class CVRCanvasWrapper : MonoBehaviour +// { +// public bool IsInteractable = true; +// public float MaxInteractDistance = 10f; +// +// private Canvas _canvas; +// private GraphicRaycaster _graphicsRaycaster; +// private static readonly List _raycastResults = new(); +// private static readonly PointerEventData _pointerEventData = new(EventSystem.current); +// +// private static Selectable _workingSelectable; +// private Camera _camera; +// private RectTransform _rectTransform; +// +// #region Unity Events +// +// private void Awake() +// { +// if (!TryGetComponent(out _canvas) +// || _canvas.renderMode != RenderMode.WorldSpace) +// { +// IsInteractable = false; +// return; +// } +// +// _rectTransform = _canvas.GetComponent(); +// } +// +// private void Start() +// { +// _graphicsRaycaster = _canvas.gameObject.AddComponent(); +// _camera = PlayerSetup.Instance.activeCam; +// _canvas.worldCamera = _camera; +// } +// +// #endregion Unity Events +// +// #region Public Methods +// +// public bool GetGraphicsHit(Ray worldRay, out RaycastResult result) +// { +// result = default; +// +// if (!IsInteractable || _camera == null) return false; +// +// // Get the plane of the canvas +// Plane canvasPlane = new(transform.forward, transform.position); +// +// // Find where the ray intersects the canvas plane +// if (!canvasPlane.Raycast(worldRay, out float distance)) +// return false; +// +// // Get the world point of intersection +// Vector3 worldHitPoint = worldRay.origin + worldRay.direction * distance; +// +// // Check if hit point is within max interaction distance +// if (Vector3.Distance(worldRay.origin, worldHitPoint) > MaxInteractDistance) +// return false; +// +// // Check if hit point is within canvas bounds +// Vector3 localHitPoint = transform.InverseTransformPoint(worldHitPoint); +// Rect canvasRect = _rectTransform.rect; +// if (!canvasRect.Contains(new Vector2(localHitPoint.x, localHitPoint.y))) +// return false; +// +// // Convert world hit point to screen space +// Vector2 screenPoint = _camera.WorldToScreenPoint(worldHitPoint); +// +// // Update pointer event data +// _pointerEventData.position = screenPoint; +// _pointerEventData.delta = Vector2.zero; +// +// // Clear previous results and perform raycast +// _raycastResults.Clear(); +// _graphicsRaycaster.Raycast(_pointerEventData, _raycastResults); +// +// // Early out if no hits +// if (_raycastResults.Count == 0) +// { +// //Debug.Log($"No hits on canvas {_canvas.name}"); +// return false; +// } +// +// // Find first valid interactive UI element +// foreach (RaycastResult hit in _raycastResults) +// { +// if (!hit.isValid) +// { +// //Debug.Log($"Invalid hit on canvas {_canvas.name}"); +// continue; +// } +// +// // Check if the hit object has a Selectable component and is interactable +// GameObject hitObject = hit.gameObject; +// if (!hitObject.TryGetComponent(out _workingSelectable) +// || !_workingSelectable.interactable) +// { +// //Debug.Log($"Non-interactable hit on canvas {_canvas.name} - {hitObject.name}"); +// continue; +// } +// +// //Debug.Log($"Hit on canvas {_canvas.name} with {hitObject.name}"); +// +// result = hit; +// return true; +// } +// +// return false; +// } +// +// #endregion Public Methods +// } +// } \ No newline at end of file diff --git a/.Deprecated/SuperAwesomeMod/Interaction/ControllerRay.cs b/.Deprecated/SuperAwesomeMod/Interaction/ControllerRay.cs new file mode 100644 index 0000000..06edaf5 --- /dev/null +++ b/.Deprecated/SuperAwesomeMod/Interaction/ControllerRay.cs @@ -0,0 +1,1871 @@ +/*using System; +using System.Collections.Generic; +using ABI.CCK.Components; +using ABI_RC.Core.AudioEffects; +using ABI_RC.Core.Base; +using ABI_RC.Core.Networking.IO.Social; +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using ABI_RC.Core.UI; +using ABI_RC.Core.InteractionSystem.Base; +using ABI_RC.Scripting.Attributes; +using ABI_RC.Systems.InputManagement; +using ABI_RC.Systems.RuntimeDebug; +using ABI.Scripting.CVRSTL.Client; +using HighlightPlus; +using TMPro; +using Unity.XR.OpenVR; +using Unity.XR.PXR; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.Serialization; +using UnityEngine.UI; +using UnityEngine.XR.Management; +using Button = UnityEngine.UI.Button; +using EventTrigger = UnityEngine.EventSystems.EventTrigger; +using Slider = UnityEngine.UI.Slider; +using Toggle = UnityEngine.UI.Toggle; + +namespace ABI_RC.Core.InteractionSystem +{ + [AvailableToScripting( + targetModule: TargetModule, + inheritFrom: typeof(MonoBehaviour), + optInMembers: true)] + public class ControllerRay : MonoBehaviour + { + public const string TargetModule = LuaScriptFactory.ModuleNames.CVR; + + private const float MAX_RAYCAST_LENGTH = 100f; + + [AvailableToScripting(@readonly: true)] + public Vector3 RayDirection = new Vector3(0,-0.2f,1f); + + [AvailableToScripting(@readonly: true)] + public CVRHand hand; + + [AvailableToScripting(@readonly: true)] + public bool isInteractionRay = true; + + [FormerlySerializedAs("triggerGazeEvents")] public bool triggerHoverEvents = true; + + public bool shouldPhysicalInteraction = false; + + public VelocityTracker pickupVelocityTracker; + + public LineRenderer lineRenderer; + + [FormerlySerializedAs("_vrActive")] [SerializeField] bool vrActive; + + [AvailableToScripting(@readonly: true)] + [SerializeField] private Transform hitTransform; + [SerializeField] float thickness = 0.002f; + + [AvailableToScripting(@readonly: true)] + [SerializeField] internal Pickupable grabbedObject; + + public LayerMask uiMask; + public LayerMask generalMask; + + [AvailableToScripting(@readonly: true)] + public Transform controllerTransform; + + [AvailableToScripting(@readonly: true)] + public bool enabled; + + [AvailableToScripting(@readonly: true)] + public bool isDesktopRay; + + [AvailableToScripting(@readonly: true)] + public bool isHeadRay; + + [AvailableToScripting(@readonly: true)] + public ControllerRay otherRay; + + public bool uiActive; + + public Material highlightMaterial; + + private float _lastTrigger; + private float _lastGrip; + private bool _objectWasHit = false; + + private CohtmlControlledView _lastView; + private Vector2 _lastUiCoords; + private float _lastHitDistance; + + private GameObject lastTarget; + private GameObject highlightGameObject; + private GameObject lastTelepathicGrabTarget; + private GameObject lastProximityGrabTarget; + private Slider lastSlider; + private RectTransform lastSliderRect; + private EventTrigger lastEventTrigger; + private ScrollRect lastScrollView; + private RectTransform lastScrollViewRect; + private Vector2 scrollStartPositionView; + private Vector2 scrollStartPositionContent; + + private Button lastButton; + private Dropdown lastDropdown; + private Toggle lastToggle; + private InputField lastInputField; + private TMP_InputField lastTMPInputField; + [SerializeField] + private Interactable lastInteractable; + + [SerializeField] + private Pickupable _telepathicPickupCandidate; + private bool _telepathicPickupTargeted; + private float _telepathicPickupTimer = 0f; + private float _telepathicPickupResetTime = 0.5f; + private bool _telepathicPickupLocked = false; + private List _positionMemory = new List(); + private List _timeMemory = new List(); + + private bool _enableHighlight; + private bool _enableSmoothRay; + + public Transform rayDirectionTransform; + public Transform attachmentPoint; + public Transform pivotPoint; + public float attachmentDistance = 0.2f; + public float currentAttachmentDistance = 0.2f; + + public Transform backupRayFor; + public GameObject backupCrossHair; + + private bool _enableTelepathicGrab = true; + private float _telepathicGrabMaxDistance = 50f; + + private bool _gripToGrab; + + public Vector3 HitPoint => _hit.point; + + private RaycastHit _hit; + private readonly RaycastHit[] _hits = new RaycastHit[10]; + /// + /// Comparer used to sort arrays of RaycastHits, it will result in an array where the first indexes are the closest ones. + /// + private readonly Comparer _hitsComparer = Comparer.Create((hit1, hit2) => hit1.distance.CompareTo(hit2.distance)); + + #region Proximity Grab Fields + + public const string ProximityGrabEnabled = "ExperimentalProximityGrabEnabled"; + + private bool _proximityGrabEnabled; + public const string ProximityGrabVisualizers = "ExperimentalProximityGrabVisualizers"; + public const string ProximityGrabRadiusScale = "ExperimentalProximityGrabRadiusScale"; + + public const float ProximityGrabRadiusScaleDefault = 0.1f; + private bool _proximityGrabVisualizers; + + private float _proximityDetectionRadiusRelativeValue = ProximityGrabRadiusScaleDefault; + private float ProximityDetectionRadius => _proximityDetectionRadiusRelativeValue * PlayerSetup.Instance.GetPlaySpaceScale(); + + private readonly Collider[] _proximityColliders = new Collider[15]; + + #endregion + + //Inputs + private bool _interactDown = false; + private Pickupable _proximityColliderClosestPickup; + private bool _proximityCalculatedThisFrame; + private bool _interactUp = false; + private bool _interact = false; + private bool _gripDown = false; + private bool _gripUp = false; + private bool _grip = false; + private bool _isTryingToPickup = false; + private bool _drop = false; + + private bool _hitUIInternal = false; + + private void Start() + { + vrActive = MetaPort.Instance.isUsingVr; + + #if !PLATFORM_ANDROID + bool isOpenVR = XRGeneralSettings.Instance.Manager.activeLoader is OpenVRLoader; + if (!isOpenVR) + { + transform.localPosition = new Vector3(0.001f, 0.021f, -0.009f); + transform.localRotation = new Quaternion(0.50603801f, 0.0288440064f, 0.0147214793f, 0.861903071f); + } + #else + bool isPxr = XRGeneralSettings.Instance.Manager.activeLoader is PXR_Loader; + if (!isPxr) + { + transform.localPosition = new Vector3(0.001f, 0.021f, -0.009f); + transform.localRotation = new Quaternion(0.50603801f, 0.0288440064f, 0.0147214793f, 0.861903071f); + } + else + { + transform.localPosition = new Vector3(0.001f, 0.021f, -0.009f); + transform.localRotation = new Quaternion(0.30603801f, 0.0288440064f, 0.0147214793f, 0.861903071f); + } + #endif + + // Fallback + if (controllerTransform == null) + controllerTransform = transform; + + _enableHighlight = MetaPort.Instance.settings.GetSettingsBool("GeneralInteractableHighlight"); + _enableTelepathicGrab = MetaPort.Instance.settings.GetSettingsBool("GeneralTelepathicGrip"); + _gripToGrab = MetaPort.Instance.settings.GetSettingsBool("ControlUseGripToGrab"); + _enableSmoothRay = MetaPort.Instance.settings.GetSettingsBool("ControlSmoothRaycast"); + _proximityGrabEnabled = MetaPort.Instance.settings.GetSettingsBool(ProximityGrabEnabled); + _proximityGrabVisualizers = MetaPort.Instance.settings.GetSettingsBool(ProximityGrabVisualizers) || MetaPort.Instance.showProximityGrabVisualizers; + MetaPort.Instance.settings.settingBoolChanged.AddListener(SettingsBoolChanged); + + _proximityDetectionRadiusRelativeValue = MetaPort.Instance.settings.GetSettingsFloat(ProximityGrabRadiusScale); + MetaPort.Instance.settings.settingFloatChanged.AddListener(SettingFloatChanged); + + // RayDirection object, we smooth to combat jitter hands for the ray, but not pickups + rayDirectionTransform = new GameObject("RayDirection").transform; + rayDirectionTransform.SetParent(transform); + rayDirectionTransform.SetLocalPositionAndRotation(RayDirection * attachmentDistance, Quaternion.identity); + rayDirectionTransform.localScale = Vector3.one; + gameObject.BroadcastMessage("RayDirectionTransformUpdated",SendMessageOptions.DontRequireReceiver); + + // Attachment point, snaps to the object collider on grab, used for object push/pull + attachmentPoint = new GameObject("AttachmentPoint").transform; + attachmentPoint.SetParent(transform); + attachmentPoint.SetLocalPositionAndRotation(RayDirection * attachmentDistance, Quaternion.identity); + attachmentPoint.localScale = Vector3.one; + + // Pivot point, used purely for object rotation, makes the math easy + pivotPoint = new GameObject("PivotPoint").transform; + pivotPoint.SetParent(attachmentPoint); + pivotPoint.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); + pivotPoint.localScale = Vector3.one; + + if (lineRenderer != null) + { + lineRenderer.sortingOrder = 10; + } + + pickupVelocityTracker = pivotPoint.AddComponentIfMissing(); + } + + private void OnDisable() + { + if (backupCrossHair) backupCrossHair.SetActive(true); + } + + public void UpdateGrabDistance(float distance = 0.2f) + { + Vector3 lossyScale = attachmentPoint.lossyScale; + Vector3 scale = new(1f/lossyScale.x, 1f/lossyScale.y, 1f/lossyScale.z); + currentAttachmentDistance = distance; + scale.Scale(RayDirection); + attachmentPoint.localPosition = scale * distance; + } + + public void SetPivotRotation(Quaternion rot) + { + pivotPoint.rotation = rot; + } + + public void ResetPivotRotation() + { + pivotPoint.localRotation = Quaternion.identity; + } + + private void SettingsBoolChanged(string name, bool value) + { + if (name == "GeneralInteractableHighlight") + _enableHighlight = value; + + if (name == "GeneralTelepathicGrip") + _enableTelepathicGrab = value; + + if (name == "ControlUseGripToGrab") + _gripToGrab = value; + + if (name == "ControlSmoothRaycast") + _enableSmoothRay = value; + + if (name == ProximityGrabEnabled) + _proximityGrabEnabled = value; + + if (name == ProximityGrabVisualizers) + _proximityGrabVisualizers = value; + } + + private void SettingFloatChanged(string settingName, float value) + { + if (settingName == ProximityGrabRadiusScale) + _proximityDetectionRadiusRelativeValue = value; + } + + public bool IsInteracting() + { + bool shouldDisplay = _interact || _grip || _objectWasHit; + return shouldDisplay; + } + + public void ClearGrabbedObject() + { + grabbedObject = null; + } + + private RaycastHit SphereCast(float offset, float radius, float maxDistance) + { + // Might be slower? + //_proximityColliders[0] = new(); + //Physics.SphereCastNonAlloc + + Physics.SphereCast + (transform.TransformPoint(RayDirection * offset), + radius, + transform.TransformDirection(RayDirection), + out RaycastHit output, + maxDistance, + (1 << CVRLayers.MirrorReflection), // generalMask |= (1 << CVRLayers.MirrorReflection), + QueryTriggerInteraction.Collide); + + //return _proximityColliders[0]; + return output; + } + + private void UpdateBackupRay() + { + if (backupRayFor != null) + { + isInteractionRay = uiActive = backupRayFor.localPosition == Vector3.zero; + backupCrossHair.SetActive(isInteractionRay); + if (otherRay != null) otherRay.isInteractionRay = !isInteractionRay; + } + } + + private bool CanSelectPlayersAndProps() + { + if (ViewManager.Instance.IsAnyMenuOpen) + return true; + + if (isDesktopRay + && CVRInputManager.Instance.unlockMouse) + return true; + + return false; + } + + private void UpdateInteractionMask() + { + if (CanSelectPlayersAndProps()) + { + generalMask |= (1 << CVRLayers.PlayerNetwork); + } + else + { + generalMask &= ~(1 << CVRLayers.PlayerNetwork); + } + + generalMask &= ~(1 << CVRLayers.Water); + } + + private void ResetPointAtUI() + { + if (isInteractionRay + && !isDesktopRay + && !isHeadRay) + { + if (hand == CVRHand.Left) + { + CVRInputManager.Instance.leftControllerPointingMenu = false; + CVRInputManager.Instance.leftControllerPointingCanvas = false; + } + else + { + CVRInputManager.Instance.rightControllerPointingMenu = false; + CVRInputManager.Instance.rightControllerPointingCanvas = false; + } + } + } + + private void UpdateInputs() + { + _interactDown = false; + _interactUp = false; + _interact = false; + _gripDown = false; + _gripUp = false; + _grip = false; + + _isTryingToPickup = false; + _drop = false; + + if (isInteractionRay) + { + _interactDown = hand == CVRHand.Left ? CVRInputManager.Instance.interactLeftDown : CVRInputManager.Instance.interactRightDown; + _interactUp = hand == CVRHand.Left ? CVRInputManager.Instance.interactLeftUp : CVRInputManager.Instance.interactRightUp; + _interact = (hand == CVRHand.Left ? CVRInputManager.Instance.interactLeftValue : CVRInputManager.Instance.interactRightValue) > 0.8f; + _gripDown = hand == CVRHand.Left ? CVRInputManager.Instance.gripLeftDown : CVRInputManager.Instance.gripRightDown; + _gripUp = hand == CVRHand.Left ? CVRInputManager.Instance.gripLeftUp : CVRInputManager.Instance.gripRightUp; + _grip = (hand == CVRHand.Left ? CVRInputManager.Instance.gripLeftValue : CVRInputManager.Instance.gripRightValue) > 0.8f; + + if (!MetaPort.Instance.isUsingVr) + { + // Non-VR mode: Use grip for pickup and drop + _isTryingToPickup = _gripDown; + _drop = _gripUp || CVRInputManager.Instance.drop; + } + else if (_gripToGrab) + { + // VR mode with grip-to-grab enabled + _isTryingToPickup = _gripDown; + _drop = _gripUp; + } + else + { + // VR mode with interact button + _isTryingToPickup = _interactDown; + _drop = _gripDown; + } + } + } + + private void CheckExitPropModes() + { + if (_gripDown && PlayerSetup.Instance.GetCurrentPropSelectionMode() != PlayerSetup.PropSelectionMode.None) + { + PlayerSetup.Instance.ClearPropToSpawn(); + } + } + + private void HandleTelepathicGrip() + { + if (!_telepathicPickupLocked) + { + if (_telepathicPickupCandidate != null && _telepathicPickupTargeted) + { + SetTelepathicGrabTargetHighlight(_telepathicPickupCandidate.gameObject); + if (_interactDown) _telepathicPickupLocked = true; + } + else if (_telepathicPickupCandidate != null) + { + _telepathicPickupTimer += Time.deltaTime; + if (_telepathicPickupTimer >= _telepathicPickupResetTime) + { + ClearTelepathicGrabTargetHighlight(); + _telepathicPickupCandidate = null; + _telepathicPickupTimer = 0f; + } + } + else if (_telepathicPickupCandidate == null) + { + _telepathicPickupTimer = 0f; + } + + _telepathicPickupTargeted = false; + } + else + { + if (_positionMemory.Count >= 5) + { + _positionMemory.RemoveAt(0); + _timeMemory.RemoveAt(0); + } + _positionMemory.Add(transform.parent.localPosition); + _timeMemory.Add(Time.deltaTime); + + if (_positionMemory.Count >= 5) + { + Vector3 velocity = _positionMemory[4] - _positionMemory[0]; + float time = 0; + foreach (float v in _timeMemory) + { + time += v; + } + + if (MetaPort.Instance.isUsingVr) + { + if ((velocity * (1 / time)).magnitude >= 0.5f) + { + if (_telepathicPickupCandidate != null) + { + _telepathicPickupCandidate.FlingTowardsTarget(transform.position); + ClearTelepathicGrabTargetHighlight(); + } + + _telepathicPickupCandidate = null; + _telepathicPickupTimer = 0f; + _telepathicPickupLocked = false; + + _positionMemory.Clear(); + _timeMemory.Clear(); + } + } + else + { + if (CVRInputManager.Instance.objectPushPull <= -2) + { + if (_telepathicPickupCandidate != null) + { + _telepathicPickupCandidate.FlingTowardsTarget(transform.position); + ClearTelepathicGrabTargetHighlight(); + } + + _telepathicPickupCandidate = null; + _telepathicPickupTimer = 0f; + _telepathicPickupLocked = false; + + _positionMemory.Clear(); + _timeMemory.Clear(); + } + } + } + + if (_interactUp) + { + if (_telepathicPickupCandidate != null) ClearTelepathicGrabTargetHighlight(); + _telepathicPickupCandidate = null; + _telepathicPickupTimer = 0f; + _telepathicPickupLocked = false; + + _positionMemory.Clear(); + _timeMemory.Clear(); + } + } + } + + private void HandleGrabbedObjects() + { + if (grabbedObject == null) return; + + // pickup rotation + if (grabbedObject.IsObjectRotationAllowed) + { + Quaternion rotationX = Quaternion.AngleAxis(-CVRInputManager.Instance.objectRotationValue.x * 20f, transform.up); + Quaternion rotationY = Quaternion.AngleAxis(CVRInputManager.Instance.objectRotationValue.y * 20f, transform.right); + pivotPoint.rotation = rotationX * rotationY * pivotPoint.rotation; + } + + // pickup push/pull + if (grabbedObject.IsObjectPushPullAllowed) + { + float newDistance = currentAttachmentDistance + 0.1f + * CVRInputManager.Instance.objectPushPull * PlayerSetup.Instance.GetPlaySpaceScale(); + if (Mathf.Abs(newDistance - currentAttachmentDistance) > float.Epsilon) + UpdateGrabDistance(Mathf.Clamp(newDistance, 0f, grabbedObject.MaxPushDistance)); + } + + // pickup interaction + if (_interactDown) grabbedObject.UseDown(new InteractionContext(this)); + if (_interactUp) grabbedObject.UseUp(new InteractionContext(this)); + + Interactable interactable = grabbedObject.gameObject.GetComponent(); + + // interaction + if (grabbedObject.IsObjectUseAllowed && interactable != null) + { + if (_interactDown) interactable.InteractDown(new InteractionContext(this), this); + if (_interactUp) interactable.InteractUp(new InteractionContext(this), this); + } + + if (!grabbedObject.IsAutoHold && _drop) DropObject(); + else if (grabbedObject.IsAutoHold && CVRInputManager.Instance.drop) DropObject(true); + + DisableLineRenderer(); + + DisableProximityGrabHighlight(); + + if (_telepathicPickupCandidate != null) + { + ClearTelepathicGrabTargetHighlight(); + _telepathicPickupCandidate = null; + } + } + + private bool HandleMenuUIInteraction() + { + //Swap Ray if applicable + if (_interactDown && _hitUIInternal && !uiActive) + { + uiActive = true; + if (otherRay) otherRay.uiActive = false; + CVR_MenuManager.Instance.lastInteractedHand = hand; + } + + if (!uiActive) + return false; + + Ray menuRay = new Ray(rayDirectionTransform.position, rayDirectionTransform.TransformDirection(RayDirection)); + CohtmlControlledView hitView = CohtmlViewInputHandler.Instance.RayToView(menuRay, out float hitDistance, out Vector2 hitCoords); + + if (hitView == null) + return false; + + float minDistance = 0.15f * PlayerSetup.Instance.GetPlaySpaceScale(); + + // physical-like touch, very satisfying + if (shouldPhysicalInteraction && (hitDistance < minDistance && _lastHitDistance >= minDistance)) + CohtmlViewInputHandler.Instance.DoViewInput(hitView, hitCoords, true, false, 0f); + else if (shouldPhysicalInteraction && (hitDistance >= minDistance && _lastHitDistance < minDistance)) + CohtmlViewInputHandler.Instance.DoViewInput(hitView, hitCoords, false, true, 0f); + else + CohtmlViewInputHandler.Instance.DoViewInput(hitView, hitCoords, _interactDown, _interactUp, + CVRInputManager.Instance.scrollValue); + + if (_lastView != null && hitView != _lastView) + CohtmlViewInputHandler.Instance.ReleaseViewInput(_lastView, _lastUiCoords); + + _lastView = hitView; + _lastUiCoords = hitCoords; + _lastHitDistance = hitDistance; + _objectWasHit = true; + + if (isInteractionRay && !isDesktopRay && !isHeadRay) + { + if (hand == CVRHand.Left) + CVRInputManager.Instance.leftControllerPointingMenu = true; + else + CVRInputManager.Instance.rightControllerPointingMenu = true; + } + + if (lineRenderer) + { + lineRenderer.enabled = true; + lineRenderer.SetPosition(0, lineRenderer.transform.InverseTransformPoint(rayDirectionTransform.position)); + lineRenderer.SetPosition(1, lineRenderer.transform.InverseTransformPoint(rayDirectionTransform.position + rayDirectionTransform.TransformDirection(RayDirection) * hitDistance)); + } + + return true; + } + + private void DisableLineRenderer() + { + if (lineRenderer) + lineRenderer.enabled = false; + + } + + private void DisableProximityGrabHighlight() + { + if (!_proximityCalculatedThisFrame) + ClearProximityGrabTargetHighlight(); + _proximityCalculatedThisFrame = false; + } + + private void HandleMenuUIInteractionRelease() + { + if (_lastView == null) return; + if (!_interactUp && uiActive) return; + CohtmlViewInputHandler.Instance.ReleaseViewInput(_lastView, _lastUiCoords); + _lastView = null; + } + + private bool FindTargets(out bool hitUiInternal) + { + const int uiInternalMask = 1 << CVRLayers.UIInternal; + + // Transform the point and direction from local to world space + Vector3 origin = rayDirectionTransform.TransformPoint(RayDirection * -0.15f); + Vector3 direction = rayDirectionTransform.TransformDirection(RayDirection); + + // Ray Cast to the internal UI layer + int hitCount = Physics.RaycastNonAlloc(origin, direction, _hits, MAX_RAYCAST_LENGTH, uiInternalMask); + + // Sort hits by distance (closer hits first) + Array.Sort(_hits, 0, hitCount, _hitsComparer); + + // Iterate through the internal UI layers + for (int i = 0; i < hitCount; i++) + { + RaycastHit hit = _hits[i]; + Collider hitCollider = hit.collider; + + // Ignore Quick Menu from the menu holding ray cast hand + if (!isDesktopRay && !isHeadRay && CVR_MenuManager.Instance.IsQuickMenuOpen && + hand == CVR_MenuManager.Instance.SelectedQuickMenuHand && + hitCollider == CVR_MenuManager.Instance.quickMenuCollider && + !CVRInputManager.Instance.oneHanded) + continue; + + _hit = hit; + hitTransform = hit.collider.transform; + hitUiInternal = true; + return true; + } + + // General mask except Mirror Reflection and UI Internal (Since we already looked for it) + int generalLayersMask = generalMask & ~(1 << CVRLayers.MirrorReflection) & ~uiInternalMask; + + // Ray Cast to the general layers + if (Physics.Raycast(origin, direction, out _hit, MAX_RAYCAST_LENGTH, generalLayersMask)) + { + hitTransform = _hit.collider.transform; + hitUiInternal = false; + return true; + } + + DisableLineRenderer(); + _objectWasHit = false; + + if (lastInteractable != null) + { + if (triggerHoverEvents) lastInteractable.HoverExit(new InteractionContext(this, PlayerSetup.PlayerLocalId), this); + // interactable handles ignoring if we didn't already interact + lastInteractable.InteractUp(new InteractionContext(this, PlayerSetup.PlayerLocalId), this); + lastInteractable = null; + } + + lastSlider = null; + + if (isInteractionRay) CVR_MenuManager.Instance.SetHandTarget("", "", "", Vector3.zero, "", hand); + if (triggerHoverEvents) CVR_MenuManager.Instance.SetViewTarget("", "", "", Vector3.zero, ""); + + ClearTargetHighlight(); + hitUiInternal = false; + return false; + } + + private Pickupable CheckPickupDirect() + { + Pickupable pickup = hitTransform.GetComponent(); + + if (pickup == null + || !pickup.CanPickup) + return null; + + if (pickup.MaxGrabDistance < _hit.distance) return null; + + if (_enableTelepathicGrab && !pickup.IsGrabbedByMe) + { + _telepathicPickupCandidate = pickup; + _telepathicPickupTargeted = true; + } + + return pickup; + } + + private PlayerDescriptor HandlePlayerClicked() + { + if (PlayerSetup.Instance.GetCurrentPropSelectionMode() + != PlayerSetup.PropSelectionMode.None) + return null; + + PlayerDescriptor descriptor = null; + if (CanSelectPlayersAndProps() && hitTransform.TryGetComponent(out descriptor)) + if (_interactDown) Users.ShowDetails(descriptor.ownerId); + + return descriptor; + } + + private Interactable HandleInteractable() + { + Interactable interactable = hitTransform.GetComponent(); + + // this handles swapping interactables when the raycast hits anything, otherwise + // FindObjects handles resetting when *nothing* is hit + // TODO: rework this so lastInteractable cannot be updated if an interaction is in progress + + if (interactable != lastInteractable) + { + if (triggerHoverEvents) + { + if (lastInteractable) lastInteractable.HoverExit(new InteractionContext(this, PlayerSetup.PlayerLocalId), this); + if (interactable) interactable.HoverEnter(new InteractionContext(this, PlayerSetup.PlayerLocalId), this); + } + + // interactable handles ignoring if we didn't already interact + if (lastInteractable) lastInteractable.InteractUp(new InteractionContext(this, PlayerSetup.PlayerLocalId), this); + + lastInteractable = interactable; + } + + if (interactable == null) return null; + + // Ignore interactable interactions if in prop delete or spawn mode + if (!isInteractionRay || PlayerSetup.Instance.GetCurrentPropSelectionMode() != PlayerSetup.PropSelectionMode.None) + return interactable; + + if (interactable.IsInteractableWithinRange(transform.position)) + { + if (_interactDown) interactable.InteractDown(new InteractionContext(this, PlayerSetup.PlayerLocalId), this); + if (_interactUp) interactable.InteractUp(new InteractionContext(this, PlayerSetup.PlayerLocalId), this); + } + + return interactable; + } + + private CVRSpawnable HandleSpawnableClicked() + { + CVRSpawnable spawnable = hitTransform.GetComponentInParent(); + if (spawnable == null) return null; + + PlayerSetup.PropSelectionMode selectionMode = PlayerSetup.Instance.GetCurrentPropSelectionMode(); + switch (selectionMode) + { + case PlayerSetup.PropSelectionMode.None: + { + // Click a prop while a menu is open to open the details menu + if (_interactDown + && CanSelectPlayersAndProps() + && spawnable.TryGetComponent(out CVRAssetInfo assetInfo)) + { + // Open the details menu of the spawnable + ViewManager.Instance.GetPropDetails(assetInfo.objectId); + ViewManager.Instance.UiStateToggle(true); + + _interactDown = false; // Consume the click + } + break; + } + case PlayerSetup.PropSelectionMode.Delete: + { + // Click a prop while in delete mode to delete it + if (_interactDown + && spawnable.ownerId != "SYSTEM" + && spawnable.ownerId != "LocalServer") + { + spawnable.Delete(); + _interactDown = false; // Consume the click + return null; // Don't return the spawnable, it's been deleted + } + break; + } + } + + // Return normal prop hover + return spawnable; + } + + private bool HandleUnityUI() + { + if (isDesktopRay && Cursor.lockState != CursorLockMode.Locked) + return false; // Unity does this for us + + Canvas canvas = hitTransform.GetComponentInParent(); + + Button button = hitTransform.GetComponent