using 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();
}
}