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 AuroraProjectButter v1.3.3
plugins/AuroraProjectButter.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("AuroraProjectButter")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.0.0")] [assembly: AssemblyInformationalVersion("1.3.0")] [assembly: AssemblyProduct("AuroraProjectButter")] [assembly: AssemblyTitle("AuroraProjectButter")] [assembly: AssemblyVersion("1.3.0.0")] namespace AuroraProjectButter; internal static class GhostUserIDRegistry { private static readonly HashSet<string> _ids = new HashSet<string>(StringComparer.Ordinal); public static void Register(string userId) { if (!string.IsNullOrEmpty(userId)) { _ids.Add(userId); } } public static bool IsGhost(string userId) { if (!string.IsNullOrEmpty(userId)) { return _ids.Contains(userId); } return false; } } [HarmonyPatch(typeof(RelationsManager), "CheckPermissionAsync")] internal static class RelationsManager_CheckPermissionAsync_GhostFilter { [HarmonyPrefix] public static bool Prefix(PlatformUserID user) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (GhostUserIDRegistry.IsGhost(user.m_userID)) { return false; } return true; } } internal static class GhostChatBypass { public static ConfigEntry<string> PermanentGhostName; private static readonly string[] KnownGhostNames = new string[122] { "Bjorn", "Sigrid", "Ragnar", "Freya", "Leif", "Astrid", "Ulf", "Ingrid", "Thorstein", "Gudrun", "Ivar", "Helga", "Sven", "Thyra", "Erik", "Hilda", "Harald", "Runa", "Olaf", "Solveig", "Gunnar", "Eira", "Knut", "Liv", "Torbjorn", "Sigrun", "Vidar", "Brynhild", "Arne", "Dagny", "Halfdan", "Ylva", "Fenrir", "Saga", "Ketil", "Alva", "Hakon", "Jorunn", "Styrbjorn", "Tove", "Bjarke", "Revna", "Grim", "Embla", "Thorgrim", "Nanna", "Oddvar", "Sif", "Skjold", "Idun", "Bragi", "Sigyn", "Baldur", "Hermod", "Magni", "Modi", "Vali", "Forseti", "Thrud", "Eir", "Gefjon", "Skadi", "Ran", "Aegir", "Ironside", "Stormborn", "Shieldmaiden", "Ravenclaw", "Wolfsbane", "Frostbite", "Shadowmere", "Nighthawk", "Stonewall", "Firebrand", "Dawnbreaker", "Thunderstrike", "Ashwalker", "Bonecrusher", "Grimjaw", "Bloodraven", "Warhammer", "Duskblade", "Starforger", "Voidwalker", "xNordicVibes", "TrollSlayer99", "MeadLord", "VikingChad", "SkadiMain", "OdinFan42", "NeckHunter", "GreydwarfGang", "LoxRider", "RuneMaster", "DraugrDave", "FulingKing", "BossHunter", "TreePuncher", "CoinHoarder", "IronPickAxe", "SerpentBait", "MushroomGuy", "ThistleQueen", "HoneyBear", "Magnus", "Elara", "Rorik", "Keira", "Thandor", "Lyra", "Draven", "Nova", "Caspian", "Ember", "Orion", "Wren", "Axel", "Ivy", "Zeke", "Mira", "Knox", "Sage" }; public static bool IsKnownGhostName(string name) { if (string.IsNullOrEmpty(name)) { return false; } string value = PermanentGhostName?.Value ?? "Aurora"; if (name.Equals(value, StringComparison.OrdinalIgnoreCase)) { return true; } for (int i = 0; i < KnownGhostNames.Length; i++) { if (KnownGhostNames[i].Equals(name, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } [HarmonyPatch(typeof(Chat), "RPC_ChatMessage")] internal static class Chat_RPC_ChatMessage_GhostPatch { [HarmonyPrefix] public static bool Prefix(Chat __instance, long sender, Vector3 position, int type, UserInfo userInfo, string text) { //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Invalid comparison between Unknown and I4 //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Invalid comparison between Unknown and I4 //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { return true; } string text2 = userInfo?.Name ?? ""; if (!GhostChatBypass.IsKnownGhostName(text2)) { return true; } GhostPlayerInjector.RememberGhost(text2); try { Type val = (Type)type; bool flag = false; try { MethodInfo method = typeof(Chat).GetMethod("AddString", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3] { typeof(PlatformUserID), typeof(string), typeof(Type) }, null); if (method != null) { PlatformUserID val2 = (PlatformUserID)(((??)userInfo?.UserId) ?? new PlatformUserID("Steam", "0")); method.Invoke(__instance, new object[3] { val2, text ?? "", val }); flag = true; } else { ManualLogSource logger = ButterPlugin.Logger; if (logger != null) { logger.LogWarning((object)"[GhostChatBypass] Chat.AddString(PlatformUserID,string,Talker.Type) not found on this Valheim version."); } } } catch (Exception ex) { ManualLogSource logger2 = ButterPlugin.Logger; if (logger2 != null) { logger2.LogWarning((object)("[GhostChatBypass] AddString invoke: " + ex.Message)); } } if (!flag) { string text3 = (((int)val == 2) ? ("<color=yellow>" + text2 + "</color>: <color=yellow><b>" + (text ?? "").ToUpper() + "</b></color>") : ("<color=yellow>" + text2 + "</color>: " + text)); ((Terminal)__instance).AddString(text3); } try { typeof(Chat).GetField("m_hideTimer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(__instance, 0f); } catch { } if ((Object)(object)Player.m_localPlayer != (Object)null && (int)val != 3) { try { Vector3 val3 = position; if (val3 == Vector3.zero) { val3 = ((Component)Player.m_localPlayer).transform.position + Vector3.up * 2.5f; } MethodInfo method2 = typeof(Chat).GetMethod("AddInworldText", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method2 != null && method2.GetParameters().Length == 6) { method2.Invoke(__instance, new object[6] { null, sender, val3, val, userInfo, text }); } } catch { } } } catch (Exception ex2) { ManualLogSource logger3 = ButterPlugin.Logger; if (logger3 != null) { logger3.LogWarning((object)("[GhostChatBypass] Failed: " + ex2.Message)); } } return false; } } internal static class GhostPlayerInjector { internal class GhostInjectorMB : MonoBehaviour { private float _nextPoll; private int _pollCount; private void Update() { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < _nextPoll) { return; } _nextPoll = Time.unscaledTime + 2f; try { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || instance.IsServer()) { return; } FieldInfo field = typeof(ZNet).GetField("m_players", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || !(field.GetValue(instance) is List<PlayerInfo> list)) { return; } int count = list.Count; string text = GhostChatBypass.PermanentGhostName?.Value ?? "Aurora"; string currentRotatingGhostName = GetCurrentRotatingGhostName(); List<int> list2 = new List<int>(); FieldInfo field2 = typeof(PlayerInfo).GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null) { for (int i = 0; i < list.Count; i++) { string text2 = field2.GetValue(list[i]) as string; if (string.IsNullOrEmpty(text2) || string.Equals(text2, text, StringComparison.OrdinalIgnoreCase) || string.Equals(text2, currentRotatingGhostName, StringComparison.OrdinalIgnoreCase)) { continue; } bool flag = false; for (int j = 0; j < RotatingGhostPool.Length; j++) { if (RotatingGhostPool[j].Equals(text2, StringComparison.OrdinalIgnoreCase)) { flag = true; break; } } if (flag) { list2.Add(i); } } } for (int num = list2.Count - 1; num >= 0; num--) { list.RemoveAt(list2[num]); } ZNet_RPC_PlayerList_Patch_AddIfMissing(list, text); ZNet_RPC_PlayerList_Patch_AddIfMissing(list, currentRotatingGhostName); foreach (string seenGhostName in _seenGhostNames) { ZNet_RPC_PlayerList_Patch_AddIfMissing(list, seenGhostName); } _pollCount++; if (_pollCount == 1 || _pollCount % 30 == 0) { ManualLogSource logger = ButterPlugin.Logger; if (logger != null) { logger.LogInfo((object)$"[GhostPlayerInjector-Poll] poll #{_pollCount}: m_players {count} → {list.Count} (added {list.Count - count}). Seen: {_seenGhostNames.Count}"); } } } catch (Exception ex) { ManualLogSource logger2 = ButterPlugin.Logger; if (logger2 != null) { logger2.LogWarning((object)("[GhostPlayerInjector-Poll] " + ex.Message)); } } } private static void ZNet_RPC_PlayerList_Patch_AddIfMissing(List<PlayerInfo> list, string name) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(name)) { return; } FieldInfo field = typeof(PlayerInfo).GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return; } for (int i = 0; i < list.Count; i++) { if (string.Equals(field.GetValue(list[i]) as string, name, StringComparison.OrdinalIgnoreCase)) { return; } } list.Add(MakeGhostPlayerInfo(name)); } } [HarmonyPatch(typeof(ZNet), "RPC_PlayerList")] internal static class ZNet_RPC_PlayerList_Patch { [HarmonyPostfix] public static void Postfix(ZNet __instance) { if ((Object)(object)__instance == (Object)null || __instance.IsServer()) { return; } try { FieldInfo field = typeof(ZNet).GetField("m_players", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { if (_postfixRunCount == 0) { ManualLogSource logger = ButterPlugin.Logger; if (logger != null) { logger.LogWarning((object)"[GhostPlayerInjector] m_players field not found on ZNet."); } } _postfixRunCount++; return; } if (!(field.GetValue(__instance) is List<PlayerInfo> list)) { if (_postfixRunCount == 0) { ManualLogSource logger2 = ButterPlugin.Logger; if (logger2 != null) { logger2.LogWarning((object)"[GhostPlayerInjector] m_players is null or wrong type."); } } _postfixRunCount++; return; } int count = list.Count; string name = GhostChatBypass.PermanentGhostName?.Value ?? "Aurora"; string currentRotatingGhostName = GetCurrentRotatingGhostName(); AddIfMissing(list, name); AddIfMissing(list, currentRotatingGhostName); foreach (string seenGhostName in _seenGhostNames) { AddIfMissing(list, seenGhostName); } _postfixRunCount++; if (_postfixRunCount == 1 || _postfixRunCount % 20 == 0) { ManualLogSource logger3 = ButterPlugin.Logger; if (logger3 != null) { logger3.LogInfo((object)$"[GhostPlayerInjector] Postfix run #{_postfixRunCount}. m_players was {count} → {list.Count} (added {list.Count - count} ghost(s)). Seen ghost names: {_seenGhostNames.Count}."); } } } catch (Exception ex) { ManualLogSource logger4 = ButterPlugin.Logger; if (logger4 != null) { logger4.LogWarning((object)("[GhostPlayerInjector] Postfix failed: " + ex.Message + "\n" + ex.StackTrace)); } } } private static void AddIfMissing(List<PlayerInfo> list, string name) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(name)) { return; } for (int i = 0; i < list.Count; i++) { FieldInfo field = typeof(PlayerInfo).GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { break; } if (string.Equals(field.GetValue(list[i]) as string, name, StringComparison.OrdinalIgnoreCase)) { return; } } list.Add(MakeGhostPlayerInfo(name)); } } private static readonly HashSet<string> _seenGhostNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private const int RotationMinutes = 30; private static readonly string[] RotatingGhostPool = new string[48] { "Bjorn", "Sigrid", "Ragnar", "Freya", "Leif", "Astrid", "Ulf", "Ingrid", "Thorstein", "Gudrun", "Ivar", "Helga", "Sven", "Thyra", "Erik", "Hilda", "Harald", "Runa", "Olaf", "Solveig", "Gunnar", "Eira", "Knut", "Liv", "Torbjorn", "Sigrun", "Vidar", "Brynhild", "Arne", "Dagny", "Halfdan", "Ylva", "Fenrir", "Saga", "Ketil", "Alva", "Hakon", "Jorunn", "Styrbjorn", "Tove", "Bjarke", "Revna", "Grim", "Embla", "Thorgrim", "Nanna", "Oddvar", "Sif" }; private static bool _diagDumped = false; private static readonly HashSet<string> _verifiedGhosts = new HashSet<string>(); private static int _postfixRunCount = 0; public static string GetCurrentRotatingGhostName() { DateTime dateTime = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc); int num = (int)(Math.Abs((long)((DateTime.UtcNow - dateTime).TotalMinutes / 30.0)) % RotatingGhostPool.Length); return RotatingGhostPool[num]; } public static void RememberGhost(string name) { if (!string.IsNullOrEmpty(name)) { _seenGhostNames.Add(name); } } private static Vector3 PositionFor(string name) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) int num = 0; string text = name ?? ""; foreach (char c in text) { num = num * 31 + c; } Random random = new Random(num); float num2 = (float)(random.NextDouble() * Math.PI * 2.0); float num3 = 2000f + (float)(random.NextDouble() * 5000.0); float num4 = Mathf.Cos(num2) * num3; float num5 = Mathf.Sin(num2) * num3; return new Vector3(num4, 30f, num5); } private static void DumpPlayerInfoSchema() { if (_diagDumped) { return; } _diagDumped = true; try { Type typeFromHandle = typeof(PlayerInfo); ManualLogSource logger = ButterPlugin.Logger; if (logger != null) { logger.LogInfo((object)"[Diag] ZNet.PlayerInfo fields:"); } FieldInfo[] fields = typeFromHandle.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { ManualLogSource logger2 = ButterPlugin.Logger; if (logger2 != null) { logger2.LogInfo((object)(" " + fieldInfo.FieldType.FullName + " " + fieldInfo.Name)); } } FieldInfo field = typeFromHandle.GetField("m_userInfo", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field != null)) { return; } ManualLogSource logger3 = ButterPlugin.Logger; if (logger3 != null) { logger3.LogInfo((object)("[Diag] " + field.FieldType.FullName + " fields:")); } fields = field.FieldType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo2 in fields) { ManualLogSource logger4 = ButterPlugin.Logger; if (logger4 != null) { logger4.LogInfo((object)(" " + fieldInfo2.FieldType.FullName + " " + fieldInfo2.Name)); } } FieldInfo field2 = field.FieldType.GetField("m_id", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field2 != null)) { return; } ManualLogSource logger5 = ButterPlugin.Logger; if (logger5 != null) { logger5.LogInfo((object)("[Diag] " + field2.FieldType.FullName + " (PlatformUserID) fields:")); } fields = field2.FieldType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo3 in fields) { ManualLogSource logger6 = ButterPlugin.Logger; if (logger6 != null) { logger6.LogInfo((object)(" " + fieldInfo3.FieldType.FullName + " " + fieldInfo3.Name)); } } } catch (Exception ex) { ManualLogSource logger7 = ButterPlugin.Logger; if (logger7 != null) { logger7.LogWarning((object)("[Diag] dump failed: " + ex.Message)); } } } internal static PlayerInfo MakeGhostPlayerInfo(string name) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) DumpPlayerInfoSchema(); object obj = (object)default(PlayerInfo); Type typeFromHandle = typeof(PlayerInfo); typeFromHandle.GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, name); long num = 1879048192L; uint num2 = 1u; try { uint num3 = 2166136261u; string text = name ?? ""; foreach (char c in text) { num3 ^= c; num3 *= 16777619; } num = 0x70000000L | (long)(num3 & 0x7FFFFFFF); num2 = num3 % 255 + 1; } catch { } try { ConstructorInfo constructor = typeof(ZDOID).GetConstructor(new Type[2] { typeof(long), typeof(uint) }); object value = ((constructor != null) ? constructor.Invoke(new object[2] { num, num2 }) : ((object)ZDOID.None)); typeFromHandle.GetField("m_characterID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, value); } catch { typeFromHandle.GetField("m_characterID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, ZDOID.None); } typeFromHandle.GetField("m_publicPosition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, true); typeFromHandle.GetField("m_position", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, PositionFor(name)); typeFromHandle.GetField("m_serverAssignedDisplayName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, name); try { FieldInfo field = typeFromHandle.GetField("m_userInfo", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object obj4 = Activator.CreateInstance(field.FieldType); field.FieldType.GetField("m_displayName")?.SetValue(obj4, name); FieldInfo field2 = field.FieldType.GetField("m_id"); if (field2 != null) { ulong num4 = 14695981039346656037uL; string text = name ?? ""; foreach (char c2 in text) { num4 ^= c2; num4 *= 1099511628211L; } string text2 = (76561197960265728L + num4 % 1000000000).ToString(); object obj5; try { obj5 = (object)new PlatformUserID("Steam", text2); } catch { obj5 = Activator.CreateInstance(field2.FieldType); FieldInfo field3 = field2.FieldType.GetField("m_platform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field3 != null) { try { ConstructorInfo constructor2 = field3.FieldType.GetConstructor(new Type[1] { typeof(string) }); if (constructor2 != null) { field3.SetValue(obj5, constructor2.Invoke(new object[1] { "Steam" })); } } catch { } } field2.FieldType.GetField("m_userID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj5, text2); } GhostUserIDRegistry.Register(text2); field2.SetValue(obj4, obj5); } field.SetValue(obj, obj4); } } catch { } if (!_verifiedGhosts.Contains(name)) { _verifiedGhosts.Add(name); try { PlayerInfo val = (PlayerInfo)obj; string text3 = typeFromHandle.GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val) as string; object obj9 = typeFromHandle.GetField("m_position", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val); object obj10 = typeFromHandle.GetField("m_userInfo", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val); string text4 = null; string text5 = null; string text6 = null; if (obj10 != null) { Type type = obj10.GetType(); text4 = type.GetField("m_displayName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj10) as string; object obj11 = type.GetField("m_id", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj10); if (obj11 != null) { Type type2 = obj11.GetType(); text6 = (type2.GetField("m_platform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj11))?.ToString(); text5 = type2.GetField("m_userID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj11) as string; } } ManualLogSource logger = ButterPlugin.Logger; if (logger != null) { logger.LogInfo((object)$"[Diag] ghost '{name}' built → m_name='{text3}' m_position={obj9} m_userInfo.m_displayName='{text4}' m_id.m_platform={text6} m_id.m_userID='{text5}'"); } } catch (Exception ex) { ManualLogSource logger2 = ButterPlugin.Logger; if (logger2 != null) { logger2.LogWarning((object)("[Diag] verify failed: " + ex.Message)); } } } return (PlayerInfo)obj; } private static void SetField(object target, string name, object value) { try { target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(target, value); } catch { } } } [BepInPlugin("freyja.AuroraProjectButter", "AuroraProjectButter", "1.3.9")] public class ButterPlugin : BaseUnityPlugin { internal struct DeferredDungeon { public DungeonGenerator Generator; public Vector3 Position; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__27_0; public static Func<MethodInfo, bool> <>9__31_0; public static Func<MethodInfo, bool> <>9__31_1; public static Func<MethodInfo, bool> <>9__31_2; public static Func<MethodInfo, bool> <>9__31_3; public static Func<MethodInfo, bool> <>9__32_0; public static Func<ParameterInfo, string> <>9__32_1; public static Predicate<DeferredDungeon> <>9__37_0; internal void <Awake>b__27_0(ConsoleEventArgs args) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) DungeonCleanup(); Player localPlayer = Player.m_localPlayer; float num = ((localPlayer != null) ? ((Component)localPlayer).transform.position.y : float.NaN); bool flag = IsPlayerTeleporting(); bool flag2 = IsInGracePeriod(); args.Context.AddString("[AuroraProjectButter v1.3.9]"); args.Context.AddString($" Dungeon Deferral: {TotalDeferred} deferred, {TotalAllowed} allowed, {Deferred.Count} queued"); args.Context.AddString($" Sky Filter: {SkyObjectsBlocked} blocked, {SkyObjectsAllowed} allowed"); args.Context.AddString($" Player Y: {num:F1} Teleporting: {flag} Grace: {flag2}"); args.Context.AddString($" World radius: {WorldRadius.Value}"); } internal bool <ApplyDungeonPatches>b__31_0(MethodInfo m) { if (m.Name == "Generate") { return !m.IsAbstract; } return false; } internal bool <ApplyDungeonPatches>b__31_1(MethodInfo mi) { return mi.Name == "Interact"; } internal bool <ApplyDungeonPatches>b__31_2(MethodInfo mi) { return mi.Name == "HaveTarget"; } internal bool <ApplyDungeonPatches>b__31_3(MethodInfo mi) { return mi.Name == "OnSpawned"; } internal bool <ApplySkyFilterPatches>b__32_0(MethodInfo m) { if (m.Name == "CreateObject") { return !m.IsAbstract; } return false; } internal string <ApplySkyFilterPatches>b__32_1(ParameterInfo p) { return p.ParameterType.Name; } internal bool <DungeonCleanup>b__37_0(DeferredDungeon d) { return (Object)(object)d.Generator == (Object)null; } } public const string PluginGUID = "freyja.AuroraProjectButter"; public const string PluginName = "AuroraProjectButter"; public const string PluginVersion = "1.3.9"; internal static ButterPlugin Instance; internal static ManualLogSource Logger; private Harmony _harmony; internal static readonly List<DeferredDungeon> Deferred = new List<DeferredDungeon>(); internal static bool IsForceLoading; internal static bool IsTeleporting; internal static float PlayerSpawnTime = -1f; internal static float TeleportEndTime = -1f; internal static MethodInfo DG_AwakeMethod; internal static int TotalDeferred; internal static int TotalAllowed; internal static int SkyObjectsBlocked; internal static int SkyObjectsAllowed; public static ConfigEntry<bool> ModEnabled; public static ConfigEntry<bool> VerboseLogging; public static ConfigEntry<float> SearchRadius; public static ConfigEntry<float> TeleportDelay; public static ConfigEntry<bool> ShowLoadingMsg; public static ConfigEntry<float> SpawnGracePeriod; public static ConfigEntry<bool> SkyFilterEnabled; public static ConfigEntry<float> SkyThreshold; public static ConfigEntry<float> TeleportGracePeriod; public static ConfigEntry<float> WorldRadius; private void Awake() { //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Expected O, but got Unknown //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; if (!ServerGuard.Init(this)) { return; } ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle."); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, "Extra logging."); GhostChatBypass.PermanentGhostName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "PermanentAI", "Aurora", "Permanent AI player name (server-side AI chat uses this identifier)."); SearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("DungeonDeferral", "SearchRadius", 300f, "Max distance from entrance to find deferred dungeon."); TeleportDelay = ((BaseUnityPlugin)this).Config.Bind<float>("DungeonDeferral", "TeleportDelay", 2.5f, "Seconds to wait after loading dungeon before teleport."); ShowLoadingMsg = ((BaseUnityPlugin)this).Config.Bind<bool>("DungeonDeferral", "ShowLoadingMessage", true, "Show 'Loading dungeon...' message."); SpawnGracePeriod = ((BaseUnityPlugin)this).Config.Bind<float>("DungeonDeferral", "SpawnGracePeriod", 2f, "Seconds after login to allow all loading."); SkyFilterEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("SkyFilter", "Enabled", true, "Skip creating GameObjects for dungeon interior objects while on surface."); SkyThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("SkyFilter", "SkyThresholdY", 1000f, "Objects above this Y are considered dungeon interiors."); TeleportGracePeriod = ((BaseUnityPlugin)this).Config.Bind<float>("SkyFilter", "TeleportGracePeriod", 5f, "Seconds after ANY teleport where sky filter is disabled. Prevents loading screen freeze."); WorldRadius = ((BaseUnityPlugin)this).Config.Bind<float>("SkyFilter", "WorldRadius", 15000f, "Objects beyond this X/Z distance from world center are never filtered. Set higher than your world radius to protect custom sky zones. Default 15000 covers most Expand World Size configs."); _harmony = new Harmony("freyja.AuroraProjectButter"); Logger.LogInfo((object)"── Dungeon Deferral patches ──"); ApplyDungeonPatches(); Logger.LogInfo((object)"── Sky Object Filter patches ──"); ApplySkyFilterPatches(); Logger.LogInfo((object)"── Ghost Chat Bypass + Player Injector patches ──"); try { _harmony.PatchAll(typeof(Chat_RPC_ChatMessage_GhostPatch)); Logger.LogInfo((object)" OK: Chat.RPC_ChatMessage (ghost chat bypass)"); } catch (Exception ex) { Logger.LogWarning((object)(" FAILED: Chat_RPC_ChatMessage_GhostPatch: " + ex.Message)); } try { _harmony.PatchAll(typeof(GhostPlayerInjector.ZNet_RPC_PlayerList_Patch)); Logger.LogInfo((object)" OK: ZNet.RPC_PlayerList (ghost player injector — F2 menu + map pins)"); } catch (Exception ex2) { Logger.LogWarning((object)(" FAILED: GhostPlayerInjector.ZNet_RPC_PlayerList_Patch: " + ex2.Message)); } GameObject val = new GameObject("AuroraGhostInjectorPoller"); Object.DontDestroyOnLoad((Object)val); val.AddComponent<GhostPlayerInjector.GhostInjectorMB>(); Logger.LogInfo((object)" OK: GhostInjectorMB polling fallback active (checks m_players every 2s)"); object obj = <>c.<>9__27_0; if (obj == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) DungeonCleanup(); Player localPlayer = Player.m_localPlayer; float num = ((localPlayer != null) ? ((Component)localPlayer).transform.position.y : float.NaN); bool flag = IsPlayerTeleporting(); bool flag2 = IsInGracePeriod(); args.Context.AddString("[AuroraProjectButter v1.3.9]"); args.Context.AddString($" Dungeon Deferral: {TotalDeferred} deferred, {TotalAllowed} allowed, {Deferred.Count} queued"); args.Context.AddString($" Sky Filter: {SkyObjectsBlocked} blocked, {SkyObjectsAllowed} allowed"); args.Context.AddString($" Player Y: {num:F1} Teleporting: {flag} Grace: {flag2}"); args.Context.AddString($" World radius: {WorldRadius.Value}"); }; <>c.<>9__27_0 = val2; obj = (object)val2; } new ConsoleCommand("butter_status", "Show AuroraProjectButter stats", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); Logger.LogInfo((object)"=== AuroraProjectButter v1.3.9 loaded ==="); Logger.LogInfo((object)" Dungeon Deferral: ON"); Logger.LogInfo((object)string.Format(" Sky Filter: {0} (Y > {1}, grace {2}s, radius {3})", SkyFilterEnabled.Value ? "ON" : "OFF", SkyThreshold.Value, TeleportGracePeriod.Value, WorldRadius.Value)); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } internal static bool IsPlayerTeleporting() { if (IsTeleporting) { return true; } if (IsForceLoading) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } try { FieldInfo field = typeof(Player).GetField("m_teleporting", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { return (bool)field.GetValue(localPlayer); } } catch { } return false; } internal static bool IsInGracePeriod() { float time = Time.time; if (PlayerSpawnTime > 0f && time - PlayerSpawnTime < SpawnGracePeriod.Value) { return true; } if (TeleportEndTime > 0f && time - TeleportEndTime < TeleportGracePeriod.Value) { return true; } return false; } private void ApplyDungeonPatches() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Expected O, but got Unknown //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Expected O, but got Unknown //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Expected O, but got Unknown try { DG_AwakeMethod = typeof(DungeonGenerator).GetMethod("Awake", BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (DG_AwakeMethod != null) { _harmony.Patch((MethodBase)DG_AwakeMethod, new HarmonyMethod(typeof(DungeonPatches), "Awake_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.LogInfo((object)" OK: DungeonGenerator.Awake()"); } else { Logger.LogError((object)" FAIL: DungeonGenerator.Awake()"); } } catch (Exception arg) { Logger.LogError((object)$" DG.Awake: {arg}"); } try { MethodInfo method = typeof(DungeonGenerator).GetMethod("LoadRoomPrefabsAsync", BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method != null) { _harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(DungeonPatches), "LoadAsync_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.LogInfo((object)" OK: LoadRoomPrefabsAsync() (fallback)"); } } catch (Exception ex) { Logger.LogWarning((object)(" LoadAsync: " + ex.Message)); } try { List<MethodInfo> list = (from m in typeof(DungeonGenerator).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "Generate" && !m.IsAbstract select m).ToList(); MethodInfo method2 = typeof(DungeonPatches).GetMethod("Generate_Prefix", BindingFlags.Static | BindingFlags.Public); int num = 0; foreach (MethodInfo item in list) { try { _harmony.Patch((MethodBase)item, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch { } } Logger.LogInfo((object)$" OK: {num} Generate overload(s)"); } catch (Exception arg2) { Logger.LogError((object)$" Generate: {arg2}"); } try { MethodInfo methodInfo = typeof(Teleport).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo mi) => mi.Name == "Interact"); if (methodInfo != null) { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(DungeonPatches), "Teleport_Interact_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.LogInfo((object)" OK: Teleport.Interact"); } } catch (Exception arg3) { Logger.LogError((object)$" Teleport.Interact: {arg3}"); } try { MethodInfo methodInfo2 = typeof(Teleport).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo mi) => mi.Name == "HaveTarget"); if (methodInfo2 != null) { _harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(DungeonPatches), "HaveTarget_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.LogInfo((object)" OK: Teleport.HaveTarget"); } } catch (Exception ex2) { Logger.LogWarning((object)(" HaveTarget: " + ex2.Message)); } try { MethodInfo methodInfo3 = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo mi) => mi.Name == "OnSpawned"); if (methodInfo3 != null) { _harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(DungeonPatches), "Player_OnSpawned_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.LogInfo((object)" OK: Player.OnSpawned"); } } catch (Exception ex3) { Logger.LogWarning((object)(" Player.OnSpawned: " + ex3.Message)); } } private void ApplySkyFilterPatches() { //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown if (!SkyFilterEnabled.Value) { Logger.LogInfo((object)" Sky Filter DISABLED in config."); return; } try { List<MethodInfo> list = (from m in typeof(ZNetScene).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "CreateObject" && !m.IsAbstract select m).ToList(); MethodInfo method = typeof(SkyFilterPatches).GetMethod("CreateObject_Prefix", BindingFlags.Static | BindingFlags.Public); int num = 0; foreach (MethodInfo item in list) { ParameterInfo[] parameters = item.GetParameters(); if (parameters.Length >= 1 && parameters[0].ParameterType == typeof(ZDO)) { _harmony.Patch((MethodBase)item, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); string text = string.Join(", ", parameters.Select((ParameterInfo p) => p.ParameterType.Name)); Logger.LogInfo((object)(" OK: ZNetScene.CreateObject(" + text + ")")); num++; } } if (num == 0) { Logger.LogWarning((object)" No ZDO-parameter CreateObject found. Trying all overloads..."); foreach (MethodInfo item2 in list) { try { _harmony.Patch((MethodBase)item2, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch { } } } if (num == 0) { Logger.LogError((object)" FAIL: Could not patch any ZNetScene.CreateObject!"); } } catch (Exception arg) { Logger.LogError((object)$" ZNetScene.CreateObject: {arg}"); } } internal static bool ShouldDefer(string caller, Vector3 genPos) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) if (!ModEnabled.Value) { return false; } if (IsForceLoading) { return false; } if ((Object)(object)Player.m_localPlayer == (Object)null) { if (VerboseLogging.Value) { Logger.LogInfo((object)$"[ALLOW:no-player] {caller} at {genPos:F0}"); } TotalAllowed++; return false; } Vector3 position = ((Component)Player.m_localPlayer).transform.position; if (IsInGracePeriod()) { if (VerboseLogging.Value) { Logger.LogInfo((object)$"[ALLOW:grace] {caller} at {genPos:F0}"); } TotalAllowed++; return false; } if (position.y > 1000f) { if (VerboseLogging.Value) { Logger.LogInfo((object)$"[ALLOW:in-dungeon] {caller} at {genPos:F0}"); } TotalAllowed++; return false; } if (IsPlayerTeleporting()) { if (VerboseLogging.Value) { Logger.LogInfo((object)$"[ALLOW:teleporting] {caller} at {genPos:F0}"); } TotalAllowed++; return false; } Logger.LogInfo((object)$"[DEFER] {caller} at {genPos:F0}, player Y={position.y:F0}"); TotalDeferred++; return true; } internal static void DeferDungeon(DungeonGenerator gen) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)gen).transform.position; if (!Deferred.Any((DeferredDungeon d) => (Object)(object)d.Generator == (Object)(object)gen)) { Deferred.Add(new DeferredDungeon { Generator = gen, Position = position }); } } internal static DeferredDungeon? FindNearest(Vector3 origin, float maxDist) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) DungeonCleanup(); DeferredDungeon? result = null; float num = float.MaxValue; foreach (DeferredDungeon item in Deferred) { float num2 = item.Position.x - origin.x; float num3 = item.Position.z - origin.z; float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3); if (num4 < maxDist && num4 < num) { num = num4; result = item; } } return result; } internal static void RemoveDeferred(DungeonGenerator gen) { Deferred.RemoveAll((DeferredDungeon d) => (Object)(object)d.Generator == (Object)(object)gen || (Object)(object)d.Generator == (Object)null); } internal static void DungeonCleanup() { Deferred.RemoveAll((DeferredDungeon d) => (Object)(object)d.Generator == (Object)null); } internal static void ForceLoadDungeon(DungeonGenerator gen) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (DG_AwakeMethod == null) { Logger.LogError((object)"[REPLAY] No Awake method!"); return; } IsForceLoading = true; try { Logger.LogInfo((object)$"[REPLAY] Awake() at {((Component)gen).transform.position:F0}"); DG_AwakeMethod.Invoke(gen, null); } finally { IsForceLoading = false; } } internal static Coroutine RunCoroutine(IEnumerator routine) { ButterPlugin instance = Instance; if (instance == null) { return null; } return ((MonoBehaviour)instance).StartCoroutine(routine); } } internal static class SkyFilterPatches { public static bool CreateObject_Prefix(ZDO __0) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if (!ButterPlugin.SkyFilterEnabled.Value) { return true; } if (__0 == null) { return true; } if ((Object)(object)Player.m_localPlayer == (Object)null) { return true; } if (ButterPlugin.IsPlayerTeleporting()) { ButterPlugin.SkyObjectsAllowed++; return true; } if (ButterPlugin.IsInGracePeriod()) { ButterPlugin.SkyObjectsAllowed++; return true; } Vector3 position = __0.GetPosition(); float y = position.y; if (y <= ButterPlugin.SkyThreshold.Value) { return true; } float num = Mathf.Sqrt(position.x * position.x + position.z * position.z); if (num > ButterPlugin.WorldRadius.Value) { ButterPlugin.SkyObjectsAllowed++; if (ButterPlugin.VerboseLogging.Value) { ButterPlugin.Logger.LogInfo((object)$"[SkyFilter:ALLOW] Outside world radius: Y={y:F0} dist={num:F0}"); } return true; } if (((Component)Player.m_localPlayer).transform.position.y > ButterPlugin.SkyThreshold.Value) { ButterPlugin.SkyObjectsAllowed++; return true; } ButterPlugin.SkyObjectsBlocked++; if (ButterPlugin.VerboseLogging.Value && ButterPlugin.SkyObjectsBlocked % 100 == 1) { ButterPlugin.Logger.LogInfo((object)$"[SkyFilter:BLOCK] #{ButterPlugin.SkyObjectsBlocked} Y={y:F0} dist={num:F0}"); } return false; } } internal static class DungeonPatches { [CompilerGenerated] private sealed class <LoadAndTeleport>d__5 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ButterPlugin.DeferredDungeon deferred; public Teleport teleport; public Humanoid character; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAndTeleport>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (ButterPlugin.ShowLoadingMsg.Value) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Loading dungeon...", 0, (Sprite)null); } } ButterPlugin.TeleportEndTime = Time.time; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)deferred.Generator != (Object)null) { try { ButterPlugin.ForceLoadDungeon(deferred.Generator); } catch (Exception arg2) { ButterPlugin.Logger.LogError((object)$"[OnDemand] Failed: {arg2}"); } ButterPlugin.RemoveDeferred(deferred.Generator); } <>2__current = (object)new WaitForSeconds(ButterPlugin.TeleportDelay.Value); <>1__state = 2; return true; case 2: <>1__state = -1; ButterPlugin.TeleportEndTime = Time.time; if ((Object)(object)teleport != (Object)null && (Object)(object)character != (Object)null) { ButterPlugin.IsTeleporting = true; try { teleport.Interact(character, false, false); } catch (Exception arg) { ButterPlugin.Logger.LogError((object)$"[OnDemand] Teleport: {arg}"); } finally { ButterPlugin.IsTeleporting = false; } } 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(); } } public static void Player_OnSpawned_Postfix(Player __instance) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { ButterPlugin.PlayerSpawnTime = Time.time; ButterPlugin.TeleportEndTime = Time.time; ButterPlugin.Logger.LogInfo((object)$"[Spawn] Player at {((Component)__instance).transform.position:F0}"); } } public static bool Awake_Prefix(DungeonGenerator __instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (ButterPlugin.ShouldDefer("Awake", ((Component)__instance).transform.position)) { ButterPlugin.DeferDungeon(__instance); return false; } return true; } public static bool LoadAsync_Prefix(DungeonGenerator __instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (ButterPlugin.ShouldDefer("LoadAsync", ((Component)__instance).transform.position)) { ButterPlugin.DeferDungeon(__instance); return false; } return true; } public static bool Generate_Prefix(DungeonGenerator __instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (ButterPlugin.ShouldDefer("Generate", ((Component)__instance).transform.position)) { ButterPlugin.DeferDungeon(__instance); return false; } return true; } public static bool Teleport_Interact_Prefix(Teleport __instance, Humanoid character, bool hold, bool alt) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) if (!ButterPlugin.ModEnabled.Value) { return true; } if (ButterPlugin.IsTeleporting) { return true; } if ((Object)(object)character != (Object)(object)Player.m_localPlayer) { return true; } if (hold) { return true; } if (((Component)Player.m_localPlayer).transform.position.y > 1000f) { ButterPlugin.TeleportEndTime = Time.time; return true; } ButterPlugin.DeferredDungeon? deferredDungeon = ButterPlugin.FindNearest(((Component)__instance).transform.position, ButterPlugin.SearchRadius.Value); if (!deferredDungeon.HasValue) { ButterPlugin.TeleportEndTime = Time.time; return true; } ButterPlugin.Logger.LogInfo((object)$"[OnDemand] Entrance → loading dungeon at {deferredDungeon.Value.Position:F0}"); ButterPlugin.RunCoroutine(LoadAndTeleport(__instance, deferredDungeon.Value, character)); return false; } [IteratorStateMachine(typeof(<LoadAndTeleport>d__5))] private static IEnumerator LoadAndTeleport(Teleport teleport, ButterPlugin.DeferredDungeon deferred, Humanoid character) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAndTeleport>d__5(0) { teleport = teleport, deferred = deferred, character = character }; } public static void HaveTarget_Postfix(Teleport __instance, ref bool __result) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (ButterPlugin.ModEnabled.Value && (!((Object)(object)Player.m_localPlayer != (Object)null) || !(((Component)Player.m_localPlayer).transform.position.y > 1000f)) && !__result && ButterPlugin.FindNearest(((Component)__instance).transform.position, ButterPlugin.SearchRadius.Value).HasValue) { __result = true; } } } internal static class ServerGuard { private const string PasswordHash = "e7aab22a4200ed38c615552e666633ba96140d314df8e1c00d08b886527a1dd4"; private const string ConfigSection = "Protection"; private const string ConfigKey = "password"; private static ConfigEntry<string> _cfgPassword; public static bool Init(ButterPlugin plugin) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 _cfgPassword = ((BaseUnityPlugin)plugin).Config.Bind<string>("Protection", "password", "enter_password_here", "Server password required to run AuroraProjectButter on a dedicated server. Leave as-is on game clients — this check is ignored there."); if ((int)SystemInfo.graphicsDeviceType != 4) { ManualLogSource logger = ButterPlugin.Logger; if (logger != null) { logger.LogInfo((object)"[ServerGuard] Running on client - auth skipped"); } return true; } if (HashPassword(_cfgPassword.Value?.Trim() ?? string.Empty) == "e7aab22a4200ed38c615552e666633ba96140d314df8e1c00d08b886527a1dd4") { ManualLogSource logger2 = ButterPlugin.Logger; if (logger2 != null) { logger2.LogInfo((object)"[ServerGuard] Server auth OK."); } return true; } ManualLogSource logger3 = ButterPlugin.Logger; if (logger3 != null) { logger3.LogError((object)"══════════════════════════════════════════════════\n INVALID PASSWORD — AuroraProjectButter will not load.\n Set the correct password in:\n BepInEx/config/freyja.AuroraProjectButter.cfg\n under [Protection] > password\n══════════════════════════════════════════════════"); } return false; } private static string HashPassword(string input) { using SHA256 sHA = SHA256.Create(); byte[] bytes = Encoding.UTF8.GetBytes(input); byte[] array = sHA.ComputeHash(bytes); StringBuilder stringBuilder = new StringBuilder(64); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2")); } return stringBuilder.ToString(); } }