Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of AlwaysWingsView v4.0.1
AlwaysWingsView.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOJP.AlwaysWingsView { [BepInPlugin("REPOJP.AlwaysWingsView", "AlwaysWingsView", "2.1.1")] public sealed class AlwaysWingsViewPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(ItemUpgradePlayerTumbleWingsLogic), "Start")] private static class ItemUpgradePlayerTumbleWingsLogic_Start_Patch { private static void Postfix(ItemUpgradePlayerTumbleWingsLogic __instance) { RequestDelayedReapplyStatic("wingsLogicStart"); } } [HarmonyPatch(typeof(ItemUpgradePlayerTumbleWingsLogic), "LoopSound")] private static class ItemUpgradePlayerTumbleWingsLogic_LoopSound_Patch { private static void Postfix(ItemUpgradePlayerTumbleWingsLogic __instance) { if ((Object)(object)Instance == (Object)null) { return; } string text = "off"; try { text = NormalizeMode(Instance._mode.Value); } catch { text = "off"; } if (text == "off" || IsNullUnity(__instance)) { return; } PlayerAvatar localAvatar = GetLocalAvatar(); if (IsNullUnity(localAvatar)) { return; } try { if (IsNullUnity(__instance.playerAvatar) || (Object)(object)__instance.playerAvatar != (Object)(object)localAvatar) { return; } } catch { return; } ApplyWingAudioMuteState(__instance, text); } } [HarmonyPatch(typeof(ItemUpgradePlayerTumbleWingsLogic), "FixedUpdate")] private static class ItemUpgradePlayerTumbleWingsLogic_FixedUpdate_Patch { private static void Prefix(ItemUpgradePlayerTumbleWingsLogic __instance, ref float __state) { __state = -1f; if (!ShouldAllowHostPinkFlight(__instance)) { return; } try { __state = __instance.tumbleWingPinkTimer; if (__instance.tumbleWingPinkTimer > 0f) { __instance.tumbleWingPinkTimer = 0f; } if (__instance.tumbleWingTimer < 1.15f) { __instance.tumbleWingTimer = 1.15f; } if (!IsNullUnity(__instance.playerAvatar)) { __instance.playerAvatar.upgradeTumbleWingsVisualsActive = true; } } catch (Exception ex) { LogWarn("Host pink flight prefix failed\n" + ex); } } private static void Postfix(ItemUpgradePlayerTumbleWingsLogic __instance, float __state) { if (__state < 0f) { return; } try { if (__state > 0f) { __instance.tumbleWingPinkTimer = Mathf.Max(__state, 1.15f); } if (!IsNullUnity(__instance.playerAvatar)) { __instance.playerAvatar.upgradeTumbleWingsVisualsActive = true; } __instance.WingsSetPinkColors(); } catch (Exception ex) { LogWarn("Host pink flight postfix failed\n" + ex); } } } [HarmonyPatch(typeof(ItemUpgradePlayerTumbleWingsLogic), "TurnOffWings")] private static class ItemUpgradePlayerTumbleWingsLogic_TurnOffWings_Patch { private static bool Prefix(ItemUpgradePlayerTumbleWingsLogic __instance) { if (!ShouldAllowHostPinkFlight(__instance)) { return true; } try { __instance.tumbleWingTimer = 1.15f; if (!IsNullUnity(__instance.playerAvatar)) { __instance.playerAvatar.upgradeTumbleWingsVisualsActive = true; } __instance.WingsSetPinkColors(); } catch (Exception ex) { LogWarn("Host pink TurnOff suppression failed\n" + ex); } return false; } } [HarmonyPatch(typeof(PlayerAvatar), "UpgradeTumbleWingsVisualsActiveRPC")] private static class PlayerAvatar_UpgradeTumbleWingsVisualsActiveRPC_Patch { private static void Postfix(PlayerAvatar __instance) { if ((Object)(object)Instance == (Object)null) { return; } PlayerAvatar localAvatar = GetLocalAvatar(); if (!IsNullUnity(localAvatar) && !((Object)(object)__instance != (Object)(object)localAvatar)) { string text = NormalizeMode(Instance._mode.Value); if (!(text == "off")) { RequestDelayedReapplyStatic("wingsRpc"); } } } } [CompilerGenerated] private sealed class <CoApplyWhenReady>d__25 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string reason; public AlwaysWingsViewPlugin <>4__this; private float <end>5__1; private PlayerAvatar <local>5__2; private ItemUpgradePlayerTumbleWingsLogic <logic>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CoApplyWhenReady>d__25(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <local>5__2 = null; <logic>5__3 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <end>5__1 = Time.realtimeSinceStartup + 20f; break; case 1: <>1__state = -1; <local>5__2 = null; break; } if (Time.realtimeSinceStartup < <end>5__1) { <local>5__2 = GetLocalAvatar(); if (!IsNullUnity(<local>5__2)) { <logic>5__3 = GetLocalWingsLogic(<local>5__2); if (!IsNullUnity(<logic>5__3)) { <>4__this.ApplyModeBestEffort(reason); return false; } <logic>5__3 = null; } <>2__current = null; <>1__state = 1; return true; } LogWarn("Apply skipped timeout reason=" + reason); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CoDelayedReapply>d__52 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string reason; public AlwaysWingsViewPlugin <>4__this; private float <delay>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CoDelayedReapply>d__52(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <delay>5__1 = 0.15f; try { <delay>5__1 = Mathf.Clamp(<>4__this._reapplyAfterVisualRefreshSeconds.Value, 0f, 2f); } catch { <delay>5__1 = 0.15f; } if (<delay>5__1 > 0f) { <>2__current = (object)new WaitForSeconds(<delay>5__1); <>1__state = 1; return true; } <>2__current = null; <>1__state = 2; return true; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } <>4__this.ApplyModeBestEffort("delayedReapply:" + reason); <>4__this._delayedReapplyCo = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CoNetworkStateSync>d__26 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public AlwaysWingsViewPlugin <>4__this; private WaitForSeconds <wait>5__1; private Exception <ex>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CoNetworkStateSync>d__26(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <ex>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(1f); break; case 1: <>1__state = -1; break; } try { <>4__this.ResetHostSupportConfirmationForCurrentState(); <>4__this.SyncHostSupportRoomProperty(); <>4__this.SyncPhotonPinkRequestProperty(); } catch (Exception ex) { <ex>5__2 = ex; LogWarn("Photon state sync failed\n" + <ex>5__2); } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <CoWingsKeepAlive>d__29 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string mode; public AlwaysWingsViewPlugin <>4__this; private PlayerAvatar <local>5__1; private float <interval>5__2; private ItemUpgradePlayerTumbleWingsLogic <logic>5__3; private string <currentMode>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CoWingsKeepAlive>d__29(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <local>5__1 = null; <logic>5__3 = null; <currentMode>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; <local>5__1 = null; break; } <local>5__1 = GetLocalAvatar(); if (!IsNullUnity(<local>5__1)) { <logic>5__3 = GetLocalWingsLogic(<local>5__1); if (!IsNullUnity(<logic>5__3)) { <currentMode>5__4 = NormalizeMode(<>4__this._mode.Value); ApplyWingAudioMuteState(<logic>5__3, <currentMode>5__4); if (<currentMode>5__4 != mode && <currentMode>5__4 != "off") { mode = <currentMode>5__4; <>4__this._activeMode = <currentMode>5__4; } <>4__this.ApplyWingsNow(<local>5__1, mode, "loopTick"); <currentMode>5__4 = null; } <logic>5__3 = null; } <interval>5__2 = 0.35f; try { <interval>5__2 = Mathf.Clamp(<>4__this._keepAliveIntervalSeconds.Value, 0.1f, 2f); } catch { <interval>5__2 = 0.35f; } <>2__current = (object)new WaitForSeconds(<interval>5__2); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "REPOJP.AlwaysWingsView"; public const string PluginName = "AlwaysWingsView"; public const string PluginVersion = "2.1.1"; private const string RoomPropertyHostPinkFlightSupport = "REPOJP_AWV_HostPinkFlight"; private const string PlayerPropertyPinkRequested = "REPOJP_AWV_PinkRequested"; private static ManualLogSource Log; private static AlwaysWingsViewPlugin Instance; private ConfigEntry<string> _mode; private ConfigEntry<bool> _muteWingLoopSound; private ConfigEntry<float> _keepAliveIntervalSeconds; private ConfigEntry<float> _reapplyAfterVisualRefreshSeconds; private Harmony _harmony; private Coroutine _wingsLoopCo; private Coroutine _networkSyncCo; private Coroutine _delayedReapplyCo; private string _activeMode = "off"; private bool _pinkFallbackUsingBlue; private bool _hostPinkFlightSupportConfirmedThisRoom; private string _hostPinkFlightSupportConfirmedRoomName = string.Empty; private float _nextHostSupportCheckTime; private void Awake() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Instance = this; try { ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } catch (Exception ex) { LogWarn("Persist setup failed\n" + ex); } _mode = ((BaseUnityPlugin)this).Config.Bind<string>("General", "TumbleWingsMode", "blue", new ConfigDescription("Auto tumble wings mode. Values: off, blue, pink. 自動翼モード off blue pink のみ", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "off", "blue", "pink" }), Array.Empty<object>())); _muteWingLoopSound = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "MuteWingLoopSound", true, "Mute blue and pink wing loop sound without changing the display flow. 既存の羽表示処理を変えずに青羽とピンク羽のループ音のみ無音化"); _keepAliveIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Runtime", "KeepAliveIntervalSeconds", 0.35f, new ConfigDescription("Wing visual reapply interval seconds. 羽表示再適用間隔秒数", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>())); _reapplyAfterVisualRefreshSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Runtime", "ReapplyAfterVisualRefreshSeconds", 0.15f, new ConfigDescription("Delay before reapplying after cosmetic or visual refresh. コスメや表示更新後の再適用遅延秒数", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); _harmony = new Harmony("REPOJP.AlwaysWingsView"); _harmony.PatchAll(typeof(AlwaysWingsViewPlugin).Assembly); PatchOptionalVisualRefreshMethods(); _mode.SettingChanged += OnConfigChanged; _muteWingLoopSound.SettingChanged += OnConfigChanged; _keepAliveIntervalSeconds.SettingChanged += OnConfigChanged; _reapplyAfterVisualRefreshSeconds.SettingChanged += OnConfigChanged; SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.activeSceneChanged += OnActiveSceneChanged; _networkSyncCo = ((MonoBehaviour)this).StartCoroutine(CoNetworkStateSync()); ((MonoBehaviour)this).StartCoroutine(CoApplyWhenReady("initial")); LogInfo("Loaded v2.1.1"); } private void OnDestroy() { try { SceneManager.sceneLoaded -= OnSceneLoaded; SceneManager.activeSceneChanged -= OnActiveSceneChanged; } catch { } try { _mode.SettingChanged -= OnConfigChanged; _muteWingLoopSound.SettingChanged -= OnConfigChanged; _keepAliveIntervalSeconds.SettingChanged -= OnConfigChanged; _reapplyAfterVisualRefreshSeconds.SettingChanged -= OnConfigChanged; } catch { } StopWingsLoop(); if (_networkSyncCo != null) { ((MonoBehaviour)this).StopCoroutine(_networkSyncCo); _networkSyncCo = null; } if (_delayedReapplyCo != null) { ((MonoBehaviour)this).StopCoroutine(_delayedReapplyCo); _delayedReapplyCo = null; } try { ClearPhotonPinkRequestProperty(); } catch { } try { if (_harmony != null) { _harmony.UnpatchSelf(); } } catch { } } private void OnConfigChanged(object sender, EventArgs args) { SyncPhotonPinkRequestProperty(); ApplyModeBestEffort("configChanged"); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { ResetHostSupportConfirmationForCurrentState(); SyncPhotonPinkRequestProperty(); ((MonoBehaviour)this).StartCoroutine(CoApplyWhenReady("sceneLoaded:" + ((Scene)(ref scene)).name)); } private void OnActiveSceneChanged(Scene from, Scene to) { ResetHostSupportConfirmationForCurrentState(); SyncPhotonPinkRequestProperty(); ((MonoBehaviour)this).StartCoroutine(CoApplyWhenReady("activeSceneChanged:" + ((Scene)(ref to)).name)); } [IteratorStateMachine(typeof(<CoApplyWhenReady>d__25))] private IEnumerator CoApplyWhenReady(string reason) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CoApplyWhenReady>d__25(0) { <>4__this = this, reason = reason }; } [IteratorStateMachine(typeof(<CoNetworkStateSync>d__26))] private IEnumerator CoNetworkStateSync() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CoNetworkStateSync>d__26(0) { <>4__this = this }; } private void ApplyModeBestEffort(string reason) { string text = NormalizeMode(_mode.Value); PlayerAvatar localAvatar = GetLocalAvatar(); if (IsNullUnity(localAvatar)) { return; } ItemUpgradePlayerTumbleWingsLogic localWingsLogic = GetLocalWingsLogic(localAvatar); if (!IsNullUnity(localWingsLogic)) { ResetHostSupportConfirmationForCurrentState(); SyncHostSupportRoomProperty(); SyncPhotonPinkRequestProperty(); ApplyWingAudioMuteState(localWingsLogic, text); switch (text) { case "off": StopWingsLoop(); TrySetWings(localAvatar, visualsActive: false, pink: true, "mode=off " + reason); ForceWingVisualFields(localWingsLogic, visualsActive: false, pink: false, "mode=off " + reason); _activeMode = "off"; break; case "blue": StartWingsLoop(localAvatar, "blue", reason); break; case "pink": StartWingsLoop(localAvatar, "pink", reason); break; } } } private void StartWingsLoop(PlayerAvatar local, string mode, string reason) { StopWingsLoop(); _activeMode = mode; ApplyWingsNow(local, mode, "oneshot " + reason); _wingsLoopCo = ((MonoBehaviour)this).StartCoroutine(CoWingsKeepAlive(mode)); } [IteratorStateMachine(typeof(<CoWingsKeepAlive>d__29))] private IEnumerator CoWingsKeepAlive(string mode) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CoWingsKeepAlive>d__29(0) { <>4__this = this, mode = mode }; } private void ApplyWingsNow(PlayerAvatar local, string mode, string reason) { if (IsNullUnity(local)) { return; } ItemUpgradePlayerTumbleWingsLogic localWingsLogic = GetLocalWingsLogic(local); if (IsNullUnity(localWingsLogic)) { return; } switch (mode) { case "off": _pinkFallbackUsingBlue = false; TrySetWings(local, visualsActive: false, pink: true, "mode=off " + reason); ForceWingVisualFields(localWingsLogic, visualsActive: false, pink: false, "mode=off " + reason); break; case "blue": _pinkFallbackUsingBlue = false; TrySetWings(local, visualsActive: true, pink: false, "mode=blue " + reason); ForceWingVisualFields(localWingsLogic, visualsActive: true, pink: false, "mode=blue " + reason); break; case "pink": { bool flag = HasHostPinkFlightSupport(); if (!flag && IsLocalPinkFlightFallbackBlueActive(local)) { _pinkFallbackUsingBlue = true; TrySetWings(local, visualsActive: true, pink: false, "mode=pink blueFallback " + reason); ForceWingVisualFields(localWingsLogic, visualsActive: true, pink: false, "mode=pink blueFallback " + reason); } else { _pinkFallbackUsingBlue = false; TrySetWings(local, visualsActive: true, pink: true, flag ? ("mode=pink hostSupport " + reason) : ("mode=pink fallbackIdle " + reason)); ForceWingVisualFields(localWingsLogic, visualsActive: true, pink: true, "mode=pink " + reason); } break; } } } private void StopWingsLoop() { if (_wingsLoopCo != null) { ((MonoBehaviour)this).StopCoroutine(_wingsLoopCo); _wingsLoopCo = null; } _pinkFallbackUsingBlue = false; } private static void TrySetWings(PlayerAvatar avatar, bool visualsActive, bool pink, string reason) { if (IsNullUnity(avatar)) { return; } try { avatar.UpgradeTumbleWingsVisualsActive(visualsActive, pink); } catch (Exception ex) { LogError("Wings apply failed reason=" + reason + "\n" + ex); } } private static void ForceWingVisualFields(ItemUpgradePlayerTumbleWingsLogic logic, bool visualsActive, bool pink, string reason) { if (IsNullUnity(logic)) { return; } try { PlayerAvatar playerAvatar = logic.playerAvatar; if (!IsNullUnity(playerAvatar)) { playerAvatar.upgradeTumbleWingsVisualsActive = visualsActive; } if (visualsActive) { if (logic.tumbleWingTimer < 1.15f) { logic.tumbleWingTimer = 1.15f; } if (pink) { logic.tumbleWingPinkTimer = Mathf.Max(logic.tumbleWingPinkTimer, 1.15f); logic.WingsSetPinkColors(); } else { logic.tumbleWingPinkTimer = 0f; logic.WingsSetOriginalColors(); } } else { logic.tumbleWingPinkTimer = 0f; } } catch (Exception ex) { LogWarn("Force wing fields failed reason=" + reason + "\n" + ex); } } private static PlayerAvatar GetLocalAvatar() { try { return PlayerAvatar.instance; } catch { return null; } } private static ItemUpgradePlayerTumbleWingsLogic GetLocalWingsLogic(PlayerAvatar avatar) { if (IsNullUnity(avatar)) { return null; } try { if (!IsNullUnity(avatar.upgradeTumbleWingsLogic)) { return avatar.upgradeTumbleWingsLogic; } } catch { } try { return ((Component)avatar).GetComponentInChildren<ItemUpgradePlayerTumbleWingsLogic>(true); } catch { return null; } } private static bool IsLocalPinkFlightFallbackBlueActive(PlayerAvatar avatar) { //IL_0142: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Instance == (Object)null) { return false; } if (NormalizeMode(Instance._mode.Value) != "pink") { return false; } if (IsNullUnity(avatar)) { return false; } PlayerAvatar localAvatar = GetLocalAvatar(); if (IsNullUnity(localAvatar) || (Object)(object)avatar != (Object)(object)localAvatar) { return false; } try { if (avatar.upgradeTumbleWings <= 0f) { return false; } } catch { return false; } PlayerTumble val = null; try { val = avatar.tumble; } catch { val = null; } if (IsNullUnity(val)) { return false; } try { if (!val.isTumbling) { return false; } if (!val.isPlayerInputTriggered && val.tumbleOverride) { return false; } if ((Object)(object)val.physGrabObject == (Object)null) { return false; } if (val.physGrabObject.playerGrabbing.Count > 0) { return false; } if (SemiFunc.OnGroundCheck(((Component)val).transform.position, 1f, val.physGrabObject)) { return false; } } catch { return false; } return true; } private static bool ShouldAllowHostPinkFlight(ItemUpgradePlayerTumbleWingsLogic logic) { //IL_012f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Instance == (Object)null) { return false; } if (IsNullUnity(logic)) { return false; } PlayerAvatar val = null; try { val = logic.playerAvatar; } catch { val = null; } if (IsNullUnity(val)) { return false; } try { if (val.upgradeTumbleWings <= 0f) { return false; } } catch { return false; } if (!HasPinkFlightAuthorityForAvatar(val)) { return false; } PlayerTumble val2 = null; try { val2 = val.tumble; } catch { val2 = null; } if (IsNullUnity(val2)) { return false; } try { if (!val2.isTumbling) { return false; } if (!val2.isPlayerInputTriggered && val2.tumbleOverride) { return false; } if ((Object)(object)val2.physGrabObject == (Object)null) { return false; } if (val2.physGrabObject.playerGrabbing.Count > 0) { return false; } if (SemiFunc.OnGroundCheck(((Component)val2).transform.position, 1f, val2.physGrabObject)) { return false; } } catch { return false; } return true; } private static bool HasPinkFlightAuthorityForAvatar(PlayerAvatar avatar) { if ((Object)(object)Instance == (Object)null) { return false; } if (IsNullUnity(avatar)) { return false; } if (!SemiFunc.IsMultiplayer()) { return NormalizeMode(Instance._mode.Value) == "pink"; } if (!PhotonNetwork.InRoom) { return false; } if (!PhotonNetwork.IsMasterClient) { return false; } return GetAvatarPinkRequested(avatar); } private static bool GetAvatarPinkRequested(PlayerAvatar avatar) { if (IsNullUnity(avatar)) { return false; } PhotonView val = null; try { val = ((Component)avatar).GetComponent<PhotonView>(); } catch { val = null; } if ((Object)(object)val == (Object)null || val.Owner == null) { return false; } return TryGetBoolProperty(val.Owner.CustomProperties, "REPOJP_AWV_PinkRequested"); } private void ResetHostSupportConfirmationForCurrentState() { if (!SemiFunc.IsMultiplayer() || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { _hostPinkFlightSupportConfirmedThisRoom = false; _hostPinkFlightSupportConfirmedRoomName = string.Empty; _nextHostSupportCheckTime = 0f; return; } string text = PhotonNetwork.CurrentRoom.Name ?? string.Empty; if (!string.Equals(_hostPinkFlightSupportConfirmedRoomName, text, StringComparison.Ordinal)) { _hostPinkFlightSupportConfirmedThisRoom = false; _hostPinkFlightSupportConfirmedRoomName = text; _nextHostSupportCheckTime = 0f; } } private static bool HasHostPinkFlightSupport() { if ((Object)(object)Instance == (Object)null) { return false; } if (!SemiFunc.IsMultiplayer()) { return true; } if (!PhotonNetwork.InRoom) { Instance._hostPinkFlightSupportConfirmedThisRoom = false; Instance._hostPinkFlightSupportConfirmedRoomName = string.Empty; Instance._nextHostSupportCheckTime = 0f; return false; } if (PhotonNetwork.IsMasterClient) { return true; } Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom == null) { Instance._hostPinkFlightSupportConfirmedThisRoom = false; Instance._hostPinkFlightSupportConfirmedRoomName = string.Empty; Instance._nextHostSupportCheckTime = 0f; return false; } string text = currentRoom.Name ?? string.Empty; if (!string.Equals(Instance._hostPinkFlightSupportConfirmedRoomName, text, StringComparison.Ordinal)) { Instance._hostPinkFlightSupportConfirmedThisRoom = false; Instance._hostPinkFlightSupportConfirmedRoomName = text; Instance._nextHostSupportCheckTime = 0f; } if (Instance._hostPinkFlightSupportConfirmedThisRoom) { return true; } if (Time.realtimeSinceStartup < Instance._nextHostSupportCheckTime) { return false; } Instance._nextHostSupportCheckTime = Time.realtimeSinceStartup + 3f; bool flag = TryGetBoolProperty(((RoomInfo)currentRoom).CustomProperties, "REPOJP_AWV_HostPinkFlight"); if (flag) { Instance._hostPinkFlightSupportConfirmedThisRoom = true; Instance._hostPinkFlightSupportConfirmedRoomName = text; } return flag; } private void SyncHostSupportRoomProperty() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient) { Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom != null && !TryGetBoolProperty(((RoomInfo)currentRoom).CustomProperties, "REPOJP_AWV_HostPinkFlight")) { Hashtable val = new Hashtable(); val[(object)"REPOJP_AWV_HostPinkFlight"] = true; currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } } private void SyncPhotonPinkRequestProperty() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown if (!SemiFunc.IsMultiplayer() || !PhotonNetwork.InRoom) { return; } Player localPlayer = PhotonNetwork.LocalPlayer; if (localPlayer != null) { bool flag = NormalizeMode(_mode.Value) == "pink"; bool flag2 = TryGetBoolProperty(localPlayer.CustomProperties, "REPOJP_AWV_PinkRequested"); if (flag2 != flag) { Hashtable val = new Hashtable(); val[(object)"REPOJP_AWV_PinkRequested"] = flag; localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } } private void ClearPhotonPinkRequestProperty() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom) { Player localPlayer = PhotonNetwork.LocalPlayer; if (localPlayer != null && TryGetBoolProperty(localPlayer.CustomProperties, "REPOJP_AWV_PinkRequested")) { Hashtable val = new Hashtable(); val[(object)"REPOJP_AWV_PinkRequested"] = false; localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } } private static bool TryGetBoolProperty(Hashtable props, string key) { if (props == null || string.IsNullOrEmpty(key) || !((Dictionary<object, object>)(object)props).ContainsKey((object)key)) { return false; } object obj = props[(object)key]; if (obj == null) { return false; } if (!(obj is bool result)) { if (obj is byte) { return (byte)obj != 0; } if (obj is int) { return (int)obj != 0; } if (obj is string && bool.TryParse((string)obj, out var result2)) { return result2; } return false; } return result; } private static void ApplyWingAudioMuteState(ItemUpgradePlayerTumbleWingsLogic logic, string mode) { if (!((Object)(object)Instance == (Object)null)) { bool flag = false; try { flag = Instance._muteWingLoopSound.Value && mode != "off"; } catch { flag = false; } if (flag) { MuteWingLoopAudio(logic); } else { UnmuteWingLoopAudio(logic); } } } private static void MuteWingLoopAudio(ItemUpgradePlayerTumbleWingsLogic logic) { if (IsNullUnity(logic)) { return; } try { if ((Object)(object)logic.localAudioSource != (Object)null) { logic.localAudioSource.mute = true; logic.localAudioSource.volume = 0f; if (logic.localAudioSource.isPlaying) { logic.localAudioSource.Stop(); } } } catch (Exception ex) { LogWarn("localAudioSource mute failed\n" + ex); } try { if (logic.soundWingsLoop != null && (Object)(object)logic.soundWingsLoop.Source != (Object)null) { logic.soundWingsLoop.Source.mute = true; logic.soundWingsLoop.Source.volume = 0f; if (logic.soundWingsLoop.Source.isPlaying) { logic.soundWingsLoop.Source.Stop(); } } } catch (Exception ex2) { LogWarn("soundWingsLoop mute failed\n" + ex2); } } private static void UnmuteWingLoopAudio(ItemUpgradePlayerTumbleWingsLogic logic) { if (IsNullUnity(logic)) { return; } try { if ((Object)(object)logic.localAudioSource != (Object)null) { logic.localAudioSource.mute = false; if (logic.localAudioSource.volume <= 0f) { logic.localAudioSource.volume = 1f; } } } catch (Exception ex) { LogWarn("localAudioSource unmute failed\n" + ex); } try { if (logic.soundWingsLoop != null && (Object)(object)logic.soundWingsLoop.Source != (Object)null) { logic.soundWingsLoop.Source.mute = false; if (logic.soundWingsLoop.Source.volume <= 0f) { logic.soundWingsLoop.Source.volume = 1f; } } } catch (Exception ex2) { LogWarn("soundWingsLoop unmute failed\n" + ex2); } } private static string NormalizeMode(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return "blue"; } return raw.Trim().ToLowerInvariant() switch { "off" => "off", "blue" => "blue", "pink" => "pink", _ => "blue", }; } private static bool IsNullUnity(object obj) { if (obj == null) { return true; } Object val = (Object)((obj is Object) ? obj : null); if (val != null) { return val == (Object)null; } return false; } private void RequestDelayedReapply(string reason) { if (_delayedReapplyCo != null) { ((MonoBehaviour)this).StopCoroutine(_delayedReapplyCo); _delayedReapplyCo = null; } _delayedReapplyCo = ((MonoBehaviour)this).StartCoroutine(CoDelayedReapply(reason)); } [IteratorStateMachine(typeof(<CoDelayedReapply>d__52))] private IEnumerator CoDelayedReapply(string reason) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CoDelayedReapply>d__52(0) { <>4__this = this, reason = reason }; } private static void RequestDelayedReapplyStatic(string reason) { if ((Object)(object)Instance == (Object)null) { return; } try { Instance.RequestDelayedReapply(reason); } catch (Exception ex) { LogWarn("Delayed reapply request failed reason=" + reason + "\n" + ex); } } private void PatchOptionalVisualRefreshMethods() { PatchOptionalMethod("PlayerCosmetics", "SetupCosmeticsLogic", "OptionalSetupCosmeticsLogicPostfix"); PatchOptionalMethod("PlayerCosmetics", "SetupColorsLogic", "OptionalSetupColorsLogicPostfix"); PatchOptionalMethod("PlayerAvatarVisuals", "ApplyLocalVisibilityBody", "OptionalApplyLocalVisibilityBodyPostfix"); } private void PatchOptionalMethod(string typeName, string methodName, string postfixName) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown try { Type type = AccessTools.TypeByName(typeName); if (type == null) { LogInfo("Optional patch skipped. type=" + typeName + " method=" + methodName); return; } MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null); if (methodInfo == null) { LogInfo("Optional patch skipped. type=" + typeName + " method=" + methodName); return; } MethodInfo methodInfo2 = AccessTools.Method(typeof(AlwaysWingsViewPlugin), postfixName, (Type[])null, (Type[])null); if (methodInfo2 == null) { LogInfo("Optional patch skipped. postfix=" + postfixName); return; } _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); LogInfo("Optional patch applied. type=" + typeName + " method=" + methodName); } catch (Exception ex) { LogWarn("Optional patch failed. type=" + typeName + " method=" + methodName + "\n" + ex); } } private static void OptionalSetupCosmeticsLogicPostfix(object __instance) { if (!((Object)(object)Instance == (Object)null) && IsComponentOnLocalAvatar(__instance)) { RequestDelayedReapplyStatic("setupCosmeticsLogic"); } } private static void OptionalSetupColorsLogicPostfix(object __instance) { if (!((Object)(object)Instance == (Object)null) && IsComponentOnLocalAvatar(__instance)) { RequestDelayedReapplyStatic("setupColorsLogic"); } } private static void OptionalApplyLocalVisibilityBodyPostfix(object __instance) { if (!((Object)(object)Instance == (Object)null) && IsComponentOnLocalAvatar(__instance)) { RequestDelayedReapplyStatic("applyLocalVisibilityBody"); } } private static bool IsComponentOnLocalAvatar(object componentObject) { if (IsNullUnity(componentObject)) { return false; } PlayerAvatar localAvatar = GetLocalAvatar(); if (IsNullUnity(localAvatar)) { return false; } Component val = (Component)((componentObject is Component) ? componentObject : null); if ((Object)(object)val == (Object)null) { return false; } try { if ((Object)(object)val.gameObject == (Object)(object)((Component)localAvatar).gameObject) { return true; } if ((Object)(object)val.transform != (Object)null && (Object)(object)((Component)localAvatar).transform != (Object)null) { if ((Object)(object)val.transform == (Object)(object)((Component)localAvatar).transform) { return true; } if (val.transform.IsChildOf(((Component)localAvatar).transform)) { return true; } } } catch { return false; } return false; } private static void LogInfo(string message) { Debug.Log((object)("[AlwaysWingsView] " + message)); if (Log != null) { Log.LogInfo((object)message); } } private static void LogWarn(string message) { Debug.LogWarning((object)("[AlwaysWingsView] " + message)); if (Log != null) { Log.LogWarning((object)message); } } private static void LogError(string message) { Debug.LogError((object)("[AlwaysWingsView] " + message)); if (Log != null) { Log.LogError((object)message); } } } }