using System; using HarmonyLib; using Il2CppInterop.Runtime; using RecRoom; using RecRoom.ObjectModel; using UnityEngine; [HarmonyPatch] internal static class UnboundPropFreezePatch { private static readonly bool _disabled = IsDisabled(); private static int _alreadyInert; private static bool _loggedNoRigidbody; private static bool _loggedFailure; private static readonly Type[] Companions = new Type[3] { typeof(EmbodiedObject), typeof(RbexEntity), typeof(TransformEntity) }; internal static bool Enabled => !_disabled; private static bool IsDisabled() { try { string environmentVariable = Environment.GetEnvironmentVariable("RADICADE_UNBOUND_PROP_FREEZE"); if (string.IsNullOrWhiteSpace(environmentVariable)) { return false; } bool result; switch (environmentVariable.Trim().ToLowerInvariant()) { case "0": case "off": case "false": case "no": result = true; break; default: result = false; break; } return result; } catch { return false; } } [HarmonyPostfix] [HarmonyPatch(typeof(RigidbodyEx), "Awake")] private static void Postfix(RigidbodyEx __instance) { if (!Enabled || __instance == null) { return; } try { if (!IsBound(__instance)) { Freeze(__instance); } } catch (Exception ex) { if (!_loggedFailure) { _loggedFailure = true; RadicadeEacBypassPlugin.LogSource.LogWarning((object)("[PropGuard] could not freeze an unbound prop (" + ex.GetType().Name + ": " + ex.Message + "); the prop is left exactly as the game built it.")); } } } private static bool IsBound(RigidbodyEx rigidbodyEx) { Type[] companions = Companions; foreach (Type type in companions) { try { if (rigidbodyEx.GetComponent(Il2CppType.From(type)) != null) { return true; } } catch { return true; } } return false; } private static void Freeze(RigidbodyEx rigidbodyEx) { Rigidbody unityRigidbody = rigidbodyEx.unityRigidbody; if (unityRigidbody == null) { if (!_loggedNoRigidbody) { _loggedNoRigidbody = true; } try { rigidbodyEx.ClearUnityRigidbodyVelocity(); return; } catch { return; } } if (unityRigidbody.isKinematic) { _alreadyInert++; return; } unityRigidbody.isKinematic = true; unityRigidbody.velocity = Vector3.zero; unityRigidbody.angularVelocity = Vector3.zero; } private static string Describe(RigidbodyEx rigidbodyEx) { try { GameObject gameObject = ((Component)rigidbodyEx).gameObject; return (gameObject == null) ? "" : ("'" + gameObject.name + "'"); } catch { return ""; } } }