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 Afterdeath v1.0.8
Afterdeath.dll
Decompiled 7 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using LocationManager; using Microsoft.CodeAnalysis; using ServerSync; using SoftReferenceableAssets; using TMPro; using UnityEngine; using UnityEngine.PostProcessing; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Afterdeath")] [assembly: AssemblyDescription("https://valheim.thunderstore.io/package/Smoothbrain/Afterdeath")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Afterdeath")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("150BFDAF-FF35-4302-B7CC-BEDCE69118D5")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Afterdeath { [BepInPlugin("org.bepinex.plugins.afterdeath", "Afterdeath", "1.0.8")] [BepInIncompatibility("org.bepinex.plugins.valheim_plus")] public class Afterdeath : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } private enum SkathiPins { All = 1, None = 0, Nearby = 2 } [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class RegisterPrefabs { private static void Prefix(ZNetScene __instance) { __instance.m_prefabs.Add(WispGameObject); __instance.m_prefabs.Add(assets.LoadAsset<GameObject>("AD_Respawn_End")); __instance.m_prefabs.Add(PixieGuideVisual); } } [HarmonyPatch(typeof(Game), "FindSpawnPoint")] public static class MoveToSkathi { public static bool maySkipSkathi; public static bool forceSkipSkathi; private static void Prefix(Game __instance, out bool __state) { __state = __instance.m_respawnAfterDeath || !__instance.m_playerProfile.HaveLogoutPoint(); } private static void Postfix(Game __instance, ref Vector3 point, bool __state, ref bool __result) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (__state && !forceSkipSkathi && (!maySkipSkathi || emptyInventorySkathiSpawn.Value == Toggle.On) && __instance.m_playerProfile.HaveDeathPoint()) { point = Utils.GetClosestLocation(__instance.GetPlayerProfile().GetDeathPoint()); ZNet.instance.SetReferencePosition(point); __result = ZNetScene.instance.IsAreaReady(point); if (!__result) { point = Vector3.zero; } } forceSkipSkathi = (maySkipSkathi = false); } } [HarmonyPatch(typeof(Player), "CreateTombStone")] private static class StoreGhost { private static void Prefix(Player __instance) { if (((Humanoid)__instance).m_inventory.NrOfItems() == 0) { MoveToSkathi.maySkipSkathi = true; } else { __instance.m_customData["Afterdeath Ghost"] = ""; } } } [HarmonyPatch(typeof(Player), "Load")] private static class LoadGhost { private static void Postfix(Player __instance) { if (Utils.IsGhost(__instance)) { ((Character)__instance).m_seman.AddStatusEffect((StatusEffect)(object)ghostStatus, false, 0, 0f); } } } [HarmonyPatch(typeof(Player), "Update")] private static class ResurrectionCompatibility { private static void Postfix(Player __instance) { if (!((Character)__instance).IsDead() && __instance.m_customData.TryGetValue("Afterdeath Ghost", out var value) && value == "") { Utils.ClearCustomData(__instance); } } } [HarmonyPatch(typeof(ZoneSystem), "SendLocationIcons")] public static class SkipFiltering { public static bool skipFiltering; private static void Prefix() { skipFiltering = true; } private static void Finalizer() { skipFiltering = false; } } [HarmonyPatch(typeof(ZoneSystem), "GetLocationIcons")] private static class HideSkathiPins { private static void Postfix(Dictionary<Vector3, string> icons) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) if (SkipFiltering.skipFiltering) { return; } bool isNoGhost = Object.op_Implicit((Object)(object)Player.m_localPlayer) && !Utils.IsGhost(Player.m_localPlayer); Vector3 deathPoint = Vector3.zero; if (Game.instance.GetPlayerProfile().HaveDeathPoint()) { deathPoint = Game.instance.GetPlayerProfile().GetDeathPoint(); } if (!isNoGhost && skathiPins.Value == SkathiPins.All) { return; } string name = ((Object)spiritHealerLocation.location).name; foreach (Vector3 item in (from kv in icons where kv.Value == name && (isNoGhost || skathiPins.Value == SkathiPins.None || (skathiPins.Value == SkathiPins.Nearby && deathPoint != Vector3.zero && Utils.DistanceXZ(deathPoint, kv.Key) > 1500f)) select kv.Key).ToList()) { icons.Remove(item); } } } [HarmonyPatch(typeof(Minimap), "UpdateLocationPins")] private static class SilenceMinimapLog { [CompilerGenerated] private sealed class <Transpiler>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private IEnumerator<CodeInstruction> <>7__wrap1; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; case 2: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { CodeInstruction current = <>7__wrap1.Current; if (CodeInstructionExtensions.Calls(current, Log) || CodeInstructionExtensions.Calls(current, DevLog)) { <>2__current = new CodeInstruction(OpCodes.Pop, (object)null); <>1__state = 1; return true; } <>2__current = current; <>1__state = 2; return true; } <>m__Finally1(); <>7__wrap1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 != null) { <>7__wrap1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__2 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__2(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private static readonly MethodInfo DevLog = AccessTools.DeclaredMethod(typeof(ZLog), "DevLog", (Type[])null, (Type[])null); private static readonly MethodInfo Log = AccessTools.DeclaredMethod(typeof(ZLog), "Log", (Type[])null, (Type[])null); [IteratorStateMachine(typeof(<Transpiler>d__2))] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__2(-2) { <>3__instructions = instructions }; } } private const string ModName = "Afterdeath"; private const string ModVersion = "1.0.8"; private const string ModGUID = "org.bepinex.plugins.afterdeath"; private static readonly ConfigSync configSync = new ConfigSync("Afterdeath") { DisplayName = "Afterdeath", CurrentVersion = "1.0.8", MinimumRequiredVersion = "1.0.8" }; private static ConfigEntry<Toggle> serverConfigLocked = null; public static ConfigEntry<int> respawnTime = null; public static ConfigEntry<int> respawnRange = null; public static ConfigEntry<int> repeatedRespawnMalus = null; public static ConfigEntry<int> respawnTimeCap = null; private static ConfigEntry<Toggle> emptyInventorySkathiSpawn = null; private static ConfigEntry<int> wispMovementSpeedBonus = null; public static ConfigEntry<Toggle> pixieGuide = null; public static ConfigEntry<Toggle> wanderOffProtection = null; private static ConfigEntry<SkathiPins> skathiPins = null; public static ConfigEntry<Toggle> skathiResurrection = null; public static ConfigEntry<Toggle> baseResurrection = null; public static Location spiritHealerLocation = null; public static SE_Stats ghostStatus = null; private static AssetBundle assets = null; public static GameObject WispGameObject = null; public static GameObject PixieGuideVisual = null; private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description); configSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting; return val; } private ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } public void Awake() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Expected O, but got Unknown //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) Localizer.Load(); assets = Location.PrefabManager.RegisterAssetBundle("afterdeath"); serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only."); configSync.AddLockingConfigEntry<Toggle>(serverConfigLocked); respawnTime = config("1 - General", "Respawn Time", 3, new ConfigDescription("Time in seconds you have to stand still close to your corpse to be revived.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 30), Array.Empty<object>())); repeatedRespawnMalus = config("1 - General", "Repeated Respawn Malus", 10, new ConfigDescription("Respawn time in seconds to be added for each death on the same ingame day. Use 0 to disable this.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 30), Array.Empty<object>())); respawnTimeCap = config("1 - General", "Respawn Time Cap", 120, new ConfigDescription("Maximum time in seconds for the respawn time, including the malus.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 300), Array.Empty<object>())); respawnRange = config("1 - General", "Respawn Range", 20, new ConfigDescription("Maximum range from your tombstone to get revived.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>())); emptyInventorySkathiSpawn = config("1 - General", "Empty Inventory Spawn", Toggle.On, "If on, you will spawn at Skathi, if you die without creating a tombstone. If off, you will spawn in your bed."); wispMovementSpeedBonus = config("1 - General", "Wisp Movement Bonus", 50, new ConfigDescription("Movement speed bonus for the wisp.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); wispMovementSpeedBonus.SettingChanged += delegate { ghostStatus.m_speedModifier = (float)wispMovementSpeedBonus.Value / 100f; Player localPlayer = Player.m_localPlayer; StatusEffect obj = ((localPlayer != null) ? ((Character)localPlayer).GetSEMan().GetStatusEffect(((StatusEffect)ghostStatus).NameHash()) : null); SE_Stats val = (SE_Stats)(object)((obj is SE_Stats) ? obj : null); if (val != null) { val.m_speedModifier = (float)wispMovementSpeedBonus.Value / 100f; } }; pixieGuide = config("1 - General", "Pixie Guide", Toggle.On, "If on, a pixie guide will lead you to your tombstone.", synchronizedSetting: false); wanderOffProtection = config("1 - General", "Wander Off Protection", Toggle.Off, new ConfigDescription("If on, players in wisp form will get their movement speed slowed by a whole lot, if they wander off too far from the area between Skathi and their tombstone. Can be used to prevent players from exploring the map as a wisp.", (AcceptableValueBase)null, Array.Empty<object>())); skathiPins = config("1 - General", "Skathi Map Pins", SkathiPins.All, new ConfigDescription("All: Display all Skathis as pins on the map, while in wisp form.\nNearby: Only display Skathis that are close to the tombstone as pins on the map.\nNone: Disable all Skathi map pins.", (AcceptableValueBase)null, Array.Empty<object>())); skathiResurrection = config("1 - General", "Skathi Resurrection", Toggle.On, new ConfigDescription("If off, players will be unable to resurrection at Skathi.", (AcceptableValueBase)null, Array.Empty<object>())); baseResurrection = config("1 - General", "Base Resurrection", Toggle.On, new ConfigDescription("If off, players will be unable to resurrection at their bed.", (AcceptableValueBase)null, Array.Empty<object>())); Assembly executingAssembly = Assembly.GetExecutingAssembly(); new Harmony("org.bepinex.plugins.afterdeath").PatchAll(executingAssembly); spiritHealerLocation = new Location(assets, "AD_Location_Skathi"); ((Component)((Component)spiritHealerLocation.location).transform.Find("PlayerSpawn")).gameObject.AddComponent<PlayerSpawn>(); ((Component)((Component)spiritHealerLocation.location).transform.Find("Skathi")).gameObject.AddComponent<Skathi>(); SetLocationAttributes(spiritHealerLocation); Location location2 = new Location(spiritHealerLocation.location); SetLocationAttributes(location2); location2.Biome = (Biome)32; location2.SpawnArea = (BiomeArea)1; location2.Count = 280; Location location3 = new Location(spiritHealerLocation.location); SetLocationAttributes(location3); location3.Biome = (Biome)32; location3.SpawnArea = (BiomeArea)2; location3.ForestThreshold = new LocationManager.Range(0f, 0.5f); location3.Count = 300; ghostStatus = (SE_Stats)(object)Utils.ConvertStatusEffect<SE_AfterDeath>((StatusEffect)(object)assets.LoadAsset<SE_Stats>("AD_SE_Ghost")); ghostStatus.m_speedModifier = (float)wispMovementSpeedBonus.Value / 100f; ghostStatus.m_jumpStaminaUseModifier = -1f; ghostStatus.m_runStaminaDrainModifier = -1f; ghostStatus.m_damageModifier = -1f; ghostStatus.m_modifyAttackSkill = (SkillType)999; ghostStatus.m_fallDamageModifier = -1f; WispGameObject = assets.LoadAsset<GameObject>("VFX_AD_Ghost_Spirit"); WispGameObject.AddComponent<PlayerGhost>(); PixieGuideVisual = assets.LoadAsset<GameObject>("AD_Spirit_Guide"); static void SetLocationAttributes(Location location) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) try { location.MapIcon = "ghosticon.png"; } catch (FileNotFoundException) { location.MapIconSprite = assets.LoadAsset<Sprite>(location.MapIcon); } location.ShowMapIcon = ShowIcon.Always; location.Biome = (Biome)863; location.SpawnDistance = new LocationManager.Range(100f, 10000f); location.SpawnAltitude = new LocationManager.Range(5f, 500f); location.MinimumDistanceFromGroup = 500f; location.Count = 270; location.Prioritize = true; } } } public class SE_AfterDeath : SE_Stats { public GameObject wisp; private GameObject pixieTrail; public float startPlayerMass; private Vector3 spawnPoint; private Vector3 deathPoint; public override void Setup(Character character) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { val.m_customData.TryGetValue("Afterdeath Ghost", out var value); if (Afterdeath.repeatedRespawnMalus.Value > 0 && value == "") { val.m_customData["Afterdeath Death Counter"] = Utils.CurrentDay() + " " + (Utils.DeathCounter(val) + 1); } Vector3 position = ((Component)val).transform.position; if (string.IsNullOrEmpty(value)) { val.m_customData["Afterdeath Ghost"] = position.x.ToString(CultureInfo.InvariantCulture) + "|" + position.y.ToString(CultureInfo.InvariantCulture) + "|" + position.z.ToString(CultureInfo.InvariantCulture); spawnPoint = position; } else { string[] array = value.Split(new char[1] { '|' }); if (array.Length == 3) { float.TryParse(array[0], out var result); float.TryParse(array[1], out var result2); float.TryParse(array[2], out var result3); spawnPoint = new Vector3(result, result2, result3); } } Game instance = Game.instance; if (instance != null && instance.GetPlayerProfile().HaveDeathPoint()) { deathPoint = Game.instance.GetPlayerProfile().GetDeathPoint(); } bool forceDisableInit = ZNetView.m_forceDisableInit; if (((Component)val).GetComponent<ZNetView>().GetZDO() == null) { ZNetView.m_forceDisableInit = true; } wisp = Object.Instantiate<GameObject>(Afterdeath.WispGameObject, ((Component)val).transform); ZNetView.m_forceDisableInit = forceDisableInit; Skathi[] array2 = Object.FindObjectsOfType<Skathi>(true); for (int i = 0; i < array2.Length; i++) { ((Component)array2[i]).gameObject.SetActive(true); } TombstoneRange[] array3 = Object.FindObjectsOfType<TombstoneRange>(); for (int i = 0; i < array3.Length; i++) { array3[i].ghost = wisp.GetComponent<PlayerGhost>(); } Rigidbody component = ((Component)val).GetComponent<Rigidbody>(); startPlayerMass = component.mass; component.mass = 0.5f; if (Afterdeath.pixieGuide.Value == Afterdeath.Toggle.On) { Game instance2 = Game.instance; if (instance2 != null && instance2.GetPlayerProfile().HaveDeathPoint()) { pixieTrail = Object.Instantiate<GameObject>(Afterdeath.PixieGuideVisual, position, Quaternion.identity); Pixie pixie = pixieTrail.AddComponent<Pixie>(); pixie.player = val; pixie.deathPoint = Game.instance.GetPlayerProfile().GetDeathPoint(); } } } ((SE_Stats)this).Setup(character); } public override void Stop() { Character character = ((StatusEffect)this).m_character; Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { val.m_ghostMode = false; Utils.ClearCustomData(val); ZNetScene.instance.Destroy(wisp); if (Object.op_Implicit((Object)(object)pixieTrail)) { Object.Destroy((Object)(object)pixieTrail); } ((Character)val).m_lavaHeatLevel = 0f; ((Character)val).m_lavaTimer = 1000f; ((Component)val).GetComponent<Rigidbody>().mass = startPlayerMass; } ((StatusEffect)this).Stop(); } public override void OnDamaged(HitData hit, Character attacker) { hit.ApplyModifier(0f); } public override void ModifyWalkVelocity(ref Vector3 vel) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_00c2: Unknown result type (might be due to invalid IL or missing references) ((SE_Stats)this).ModifyWalkVelocity(ref vel); Vector3 position = ((Component)((StatusEffect)this).m_character).transform.position; if (position.y > 3500f) { return; } float num = ZoneSystem.instance.GetGroundHeight(position) + 3.5f - position.y; if (((StatusEffect)this).m_character.AboveOrInLava() && num > 0f) { vel.y = Math.Max(vel.y, Mathf.Min(6f, 6f * num)); } float num2 = ((StatusEffect)this).m_character.GetLiquidLevel() + 3.5f - position.y; if (num2 > 0f) { float num3 = Mathf.Min(4f, 4f * num2); if (vel.y < num3 && ((StatusEffect)this).m_character.GetLiquidLevel() > ZoneSystem.instance.GetGroundHeight(position)) { vel.y = num3; } } } public override void ModifySpeed(float baseSpeed, ref float speed, Character character, Vector3 dir) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0071: 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_0082: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) if (Afterdeath.wanderOffProtection.Value == Afterdeath.Toggle.Off || deathPoint == Vector3.zero || spawnPoint == Vector3.zero) { return; } Vector3 position = ((Component)character).transform.position; Vector3 val = deathPoint; val.y = 0f; Vector3 val2 = val; val = spawnPoint; val.y = 0f; float num = Utils.DistanceSqr(val2, val); float num2 = Vector3.Dot(position - spawnPoint, deathPoint - spawnPoint); float num3 = Mathf.Clamp01(Mathf.Abs(num2) / num); Vector3 val3 = spawnPoint + num3 * (deathPoint - spawnPoint); float num4 = Utils.DistanceXZ(position, val3); if (!(num4 > 50f)) { return; } float num5; if (num3 != 0f) { if (num3 == 1f) { val = dir; val.y = 0f; Vector3 val4 = Vector3.Normalize(val); val = position - deathPoint; val.y = 0f; num5 = Vector3.Dot(val4, Vector3.Normalize(val)); } else { val = dir; val.y = 0f; Vector3 val5 = Vector3.Normalize(val); val = spawnPoint - deathPoint; val.y = 0f; num5 = Vector3.Dot(val5, Vector3.Normalize(val)) * Mathf.Sign(num2); } } else { val = dir; val.y = 0f; Vector3 val6 = Vector3.Normalize(val); val = position - spawnPoint; val.y = 0f; num5 = Vector3.Dot(val6, Vector3.Normalize(val)); } float num6 = Mathf.Max(0f, num5); float num7 = 1f - (1f - Mathf.Max(0.1f, num6)) * Mathf.Min(1f, (num4 - 50f) / 250f); speed *= num7; if (num7 <= 0.7f) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$ad_ghost_wander_off", 0, (Sprite)null); } } } public class PlayerGhost : MonoBehaviour { private GameObject spawnVFX; private ZNetView netview; public Player? player; private readonly List<string> activeVisuals = new List<string>(); public float? resurrectionRemainingTime; public bool carriesStone; public void Awake() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) netview = ((Component)this).GetComponent<ZNetView>(); spawnVFX = ((Component)((Component)this).transform.Find("AD_Respawn_Start")).gameObject; player = ((Component)this).GetComponentInParent<Player>(); if (player == null) { ((Component)((Component)this).transform.Find("wisp/Particle System Force Field")).gameObject.SetActive(false); } else { ZDO zDO = netview.GetZDO(); if (zDO != null) { zDO.Set("player", ((Character)player).GetZDOID()); } } UpdatePlayerVisual(); UpdatePlayerInitial(); } private void UpdatePlayerInitial() { player.m_ghostMode = true; ((Behaviour)((Component)player).GetComponent<FootStep>()).enabled = false; } private void UpdatePlayerVisual() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (player == null) { GameObject val = ZNetScene.instance.FindInstance(netview.GetZDO().GetZDOID("player")); if (val == null) { return; } player = val.GetComponent<Player>(); UpdatePlayerInitial(); } int childCount = ((Character)player).m_visual.transform.childCount; while (childCount-- > 0) { GameObject gameObject = ((Component)((Character)player).m_visual.transform.GetChild(childCount)).gameObject; if (gameObject.activeSelf) { gameObject.SetActive(false); activeVisuals.Add(((Object)gameObject).name); } } } public void Update() { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) UpdatePlayerVisual(); ZDO zDO = netview.GetZDO(); if (zDO != null) { long @long = zDO.GetLong("end time", 0L); if (@long == 0L) { resurrectionRemainingTime = null; } else { resurrectionRemainingTime = (float)(new DateTime(@long) - ZNet.instance.GetTime()).TotalSeconds; } if (!resurrectionRemainingTime.HasValue || resurrectionRemainingTime > Utils.RespawnDelay()) { spawnVFX.SetActive(false); return; } spawnVFX.SetActive(true); MainModule main = ((Component)spawnVFX.transform.Find("Flare")).GetComponent<ParticleSystem>().main; ((MainModule)(ref main)).startSizeMultiplier = 5f - 4f * resurrectionRemainingTime.Value / Utils.RespawnDelay(); } } public void OnDestroy() { if (!Object.op_Implicit((Object)(object)player)) { return; } player.m_ghostMode = false; if (!((Component)player).gameObject.activeInHierarchy || ((Character)player).IsDead()) { return; } foreach (string activeVisual in activeVisuals) { Transform obj = ((Character)player).m_visual.transform.Find(activeVisual); if (obj != null) { ((Component)obj).gameObject.SetActive(true); } } ((Behaviour)((Component)player).GetComponent<FootStep>()).enabled = true; } public void StartResurrection() { netview.GetZDO().Set("end time", ZNet.instance.GetTime().AddSeconds(Utils.RespawnDelay() + 0.2f).Ticks); } public void ResetResurrection() { netview.GetZDO().Set("end time", 0L); } } public static class BlockStuff { [HarmonyPatch(typeof(Player), "AutoPickup")] private static class DisableAutoPickup { private static bool Prefix(Player __instance) { return !Utils.IsGhost(__instance); } } [HarmonyPatch(typeof(Player), "PlayerAttackInput")] private static class DisableAttacking { private static bool Prefix(Player __instance) { return !Utils.IsGhost(__instance); } } [HarmonyPatch(typeof(Character), "UpdateHeatEffects")] private static class DisableLavaDamage { private static bool Prefix(Character __instance) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { return !Utils.IsGhost(val); } return false; } } [HarmonyPatch(typeof(Character), "UpdateSmoke")] private static class DisableSmoke { private static bool Prefix(Character __instance) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { return !Utils.IsGhost(val); } return false; } } [HarmonyPatch(typeof(TeleportWorld), "Teleport")] private static class DisableTeleport { private static bool Prefix() { return !Utils.IsGhost(Player.m_localPlayer); } } [HarmonyPatch(typeof(Player), "UpdateEnvStatusEffects")] private class DisableEnvEffects { private static bool Prefix() { return !Utils.IsGhost(Player.m_localPlayer); } } [HarmonyPatch(typeof(Skills), "RaiseSkill")] private class DisableSkillLeveling { private static bool Prefix(Skills __instance) { return !Utils.IsGhost(__instance.m_player); } } [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(Vector3), typeof(float) })] private class DisableExploration { [HarmonyPriority(800)] private static bool Prefix() { return !Utils.IsGhost(Player.m_localPlayer); } } [HarmonyPatch(typeof(Player), "FindHoverObject")] private static class DisableInteractText { private static void Postfix(Player __instance, ref GameObject? hover) { if (Utils.IsGhost(__instance) && hover != null && Utils.GetPrefabName(hover) != "Skathi") { hover = null; } } } [HarmonyPatch(typeof(Character), "InLiquidWetDepth")] private static class DisableWet { private static void Postfix(Character __instance, ref bool __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && Utils.IsGhost(val)) { __result = false; } } } } public static class GhostWorld { [HarmonyPatch(typeof(PostProcessingBehaviour), "OnEnable")] private static class SaveDefaultSettings { private static void Prefix(PostProcessingBehaviour __instance) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.profile != (Object)null && !DefaultPostProcessingSet) { DefaultColorGradingSettings = __instance.profile.colorGrading.settings; DefaultPostProcessingSet = true; } } } [HarmonyPatch(typeof(PostProcessingBehaviour), "OnPreCull")] private static class SetGhostWorldSettings { private static void Postfix(ref ColorGradingComponent ___m_ColorGrading) { //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0180: 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) Player val = (Object.op_Implicit((Object)(object)FejdStartup.instance) ? Object.FindObjectOfType<Player>() : Player.m_localPlayer); if (val != null && Utils.IsGhost(val)) { TonemappingSettings val2 = default(TonemappingSettings); val2.tonemapper = (Tonemapper)2; val2.neutralBlackIn = 20f; val2.neutralWhiteIn = 10f; val2.neutralBlackOut = 50f; val2.neutralWhiteOut = 10f; val2.neutralWhiteLevel = 5.3f; val2.neutralWhiteClip = 30f; TonemappingSettings tonemapping = val2; BasicSettings val3 = default(BasicSettings); val3.postExposure = 1f; val3.temperature = -8f; val3.tint = 0f; val3.hueShift = 0f; val3.saturation = 0f; val3.contrast = 3f; BasicSettings basic = val3; ChannelMixerSettings val4 = default(ChannelMixerSettings); val4.red = new Vector3(1f, 0f, 0f); val4.green = new Vector3(0f, 1f, 0f); val4.blue = new Vector3(1f, 0f, 1f); val4.currentEditingChannel = 0; ChannelMixerSettings channelMixer = val4; Settings val5 = default(Settings); val5.tonemapping = tonemapping; val5.basic = basic; val5.channelMixer = channelMixer; val5.colorWheels = DefaultColorGradingSettings.colorWheels; val5.curves = DefaultColorGradingSettings.curves; Settings settings = val5; ((PostProcessingComponent<ColorGradingModel>)(object)___m_ColorGrading).model.settings = settings; } else { ((PostProcessingComponent<ColorGradingModel>)(object)___m_ColorGrading).model.settings = DefaultColorGradingSettings; } } } private static bool DefaultPostProcessingSet; private static Settings DefaultColorGradingSettings; } public class Pixie : MonoBehaviour { [CompilerGenerated] private sealed class <MoveOrb>d__5 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Pixie <>4__this; public Vector3 newPosition; private float <timer>5__2; private Vector3 <startPosition>5__3; private Quaternion <targetRotation>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MoveOrb>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003b: 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) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Expected O, but got Unknown int num = <>1__state; Pixie pixie = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; <timer>5__2 = 0f; <startPosition>5__3 = ((Component)pixie).transform.position; Vector3 val = newPosition - <startPosition>5__3; val.y = 0f; <targetRotation>5__4 = Quaternion.LookRotation(val); if (Utils.DistanceXZ(<startPosition>5__3, newPosition) > 5f) { pixie.duration = 0.5f; } goto IL_0142; } case 1: <>1__state = -1; goto IL_0142; case 2: { <>1__state = -1; pixie.pixieArrived = false; return false; } IL_0142: if (<timer>5__2 < pixie.duration) { <timer>5__2 += Time.deltaTime; float num2 = <timer>5__2 / pixie.duration; num2 = (float)Math.Pow(num2, 3.0) * (num2 * (6f * num2 - 15f) + 10f); ((Component)pixie).transform.position = Vector3.Lerp(<startPosition>5__3, newPosition, num2); ((Component)pixie).transform.rotation = Quaternion.RotateTowards(((Component)pixie).transform.rotation, <targetRotation>5__4, 180f * Time.deltaTime); <>2__current = null; <>1__state = 1; return true; } <>2__current = (object)new WaitForSeconds(Random.Range(0.1f, 0.4f)); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public Player player; public Vector3 deathPoint; public bool pixieArrived; private float duration = 1f; public void Update() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_004a: 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) //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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (!pixieArrived) { pixieArrived = true; Vector3 position = ((Component)player).transform.position; Vector3 val = deathPoint - ((Component)player).transform.position; val.y = 0f; Vector3 val2 = position + ((Vector3)(ref val)).normalized * Random.Range(8f, 11f); float num = default(float); Heightmap.GetHeight(val2, ref num); val2.y = Math.Max(((Component)player).transform.position.y, num + 1f); duration = Random.Range(0.5f, 1.5f); ((MonoBehaviour)this).StartCoroutine(MoveOrb(val2)); } } [IteratorStateMachine(typeof(<MoveOrb>d__5))] private IEnumerator MoveOrb(Vector3 newPosition) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MoveOrb>d__5(0) { <>4__this = this, newPosition = newPosition }; } } public class PlayerSpawn : MonoBehaviour { [CompilerGenerated] private sealed class <<Awake>g__WaitForPlayer|0_0>d : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public PlayerSpawn <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <<Awake>g__WaitForPlayer|0_0>d(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0071: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; PlayerSpawn playerSpawn = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitWhile((Func<bool>)(() => !Object.op_Implicit((Object)(object)Player.m_localPlayer))); <>1__state = 1; return true; case 1: <>1__state = -1; if (Utils.IsGhost(Player.m_localPlayer) && Utils.DistanceXZ(((Component)Player.m_localPlayer).transform.position, ((Component)playerSpawn).transform.position) < 10f) { ((Component)Player.m_localPlayer).transform.position = ((Component)playerSpawn).transform.position; Skathi skathi = (from p in Object.FindObjectsOfType<Skathi>() orderby Utils.DistanceXZ(((Component)p).transform.position, ((Component)Player.m_localPlayer).transform.position) select p).FirstOrDefault(); if (skathi != null) { ((Character)Player.m_localPlayer).SetLookDir(((Component)skathi).transform.position - ((Component)Player.m_localPlayer).transform.position, 0f); } Physics.SyncTransforms(); } 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 void Awake() { ((MonoBehaviour)this).StartCoroutine(WaitForPlayer()); [IteratorStateMachine(typeof(<<Awake>g__WaitForPlayer|0_0>d))] IEnumerator WaitForPlayer() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <<Awake>g__WaitForPlayer|0_0>d(0) { <>4__this = this }; } } } public class Skathi : MonoBehaviour, Interactable, Hoverable { [CompilerGenerated] private static class <>O { public static PopupButtonCallback <0>__Pop; } [CompilerGenerated] private sealed class <>c__DisplayClass1_0 { private sealed class <<Interact>g__AwaitAnimationEnd|2>d : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public <>c__DisplayClass1_0 <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <<Interact>g__AwaitAnimationEnd|2>d(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; <>c__DisplayClass1_0 <>c__DisplayClass1_ = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2.8f); <>1__state = 1; return true; case 1: <>1__state = -1; if (Object.op_Implicit((Object)(object)<>c__DisplayClass1_.user)) { ((Character)<>c__DisplayClass1_.user).GetSEMan().RemoveStatusEffect((StatusEffect)(object)Afterdeath.ghostStatus, false); Afterdeath.MoveToSkathi.forceSkipSkathi = true; Vector3 val = default(Vector3); bool flag = default(bool); Game.instance.FindSpawnPoint(ref val, ref flag, 0f); ((Character)<>c__DisplayClass1_.user).TeleportTo(ZNet.instance.GetReferencePosition(), Quaternion.identity, true); } 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(); } } private sealed class <<Interact>g__AwaitAnimationEnd|3>d : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public <>c__DisplayClass1_0 <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <<Interact>g__AwaitAnimationEnd|3>d(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown int num = <>1__state; <>c__DisplayClass1_0 <>c__DisplayClass1_ = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2.8f); <>1__state = 1; return true; case 1: <>1__state = -1; if (Object.op_Implicit((Object)(object)<>c__DisplayClass1_.user)) { ((Character)<>c__DisplayClass1_.user).GetSEMan().RemoveStatusEffect((StatusEffect)(object)Afterdeath.ghostStatus, 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 Skathi <>4__this; public Humanoid user; internal void <Interact>b__0() { ((Component)((Component)<>4__this).transform.parent.Find("PlayerSpawnEffect")).gameObject.SetActive(true); ((Component)<>4__this).GetComponent<Animator>().Play("cast revive"); ((MonoBehaviour)<>4__this).StartCoroutine(AwaitAnimationEnd()); UnifiedPopup.Pop(); [IteratorStateMachine(typeof(<<Interact>g__AwaitAnimationEnd|2>d))] IEnumerator AwaitAnimationEnd() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <<Interact>g__AwaitAnimationEnd|2>d(0) { <>4__this = this }; } } internal void <Interact>b__1() { ((Component)((Component)<>4__this).transform.parent.Find("PlayerSpawnEffect")).gameObject.SetActive(true); ((Component)<>4__this).GetComponent<Animator>().Play("cast revive"); ((MonoBehaviour)<>4__this).StartCoroutine(AwaitAnimationEnd()); UnifiedPopup.Pop(); [IteratorStateMachine(typeof(<<Interact>g__AwaitAnimationEnd|3>d))] IEnumerator AwaitAnimationEnd() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <<Interact>g__AwaitAnimationEnd|3>d(0) { <>4__this = this }; } } } public void Update() { Player localPlayer = Player.m_localPlayer; if (localPlayer != null && !((Character)localPlayer).GetSEMan().HaveStatusEffect(((StatusEffect)Afterdeath.ghostStatus).NameHash())) { ((Component)this).gameObject.SetActive(false); ((Component)((Component)this).transform.parent.Find("StoneCircle")).gameObject.SetActive(true); } else { ((Component)((Component)this).transform.parent.Find("StoneCircle")).gameObject.SetActive(false); } } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //IL_0074: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //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_006e: Expected O, but got Unknown <>c__DisplayClass1_0 CS$<>8__locals0 = new <>c__DisplayClass1_0(); CS$<>8__locals0.<>4__this = this; CS$<>8__locals0.user = user; Humanoid user2 = CS$<>8__locals0.user; Player val = (Player)(object)((user2 is Player) ? user2 : null); if (val != null && Utils.CarriesTombstone(val)) { return false; } if (alt && Afterdeath.baseResurrection.Value == Afterdeath.Toggle.On) { PopupButtonCallback val2 = delegate { ((Component)((Component)CS$<>8__locals0.<>4__this).transform.parent.Find("PlayerSpawnEffect")).gameObject.SetActive(true); ((Component)CS$<>8__locals0.<>4__this).GetComponent<Animator>().Play("cast revive"); ((MonoBehaviour)CS$<>8__locals0.<>4__this).StartCoroutine(AwaitAnimationEnd()); UnifiedPopup.Pop(); }; object obj = <>O.<0>__Pop; if (obj == null) { PopupButtonCallback val3 = UnifiedPopup.Pop; <>O.<0>__Pop = val3; obj = (object)val3; } UnifiedPopup.Push((PopupBase)new YesNoPopup("$ad_skathi_interact_title_alt", "$ad_skathi_interact_message_alt", val2, (PopupButtonCallback)obj, true)); } else if (Afterdeath.skathiResurrection.Value == Afterdeath.Toggle.On) { PopupButtonCallback val4 = delegate { ((Component)((Component)CS$<>8__locals0.<>4__this).transform.parent.Find("PlayerSpawnEffect")).gameObject.SetActive(true); ((Component)CS$<>8__locals0.<>4__this).GetComponent<Animator>().Play("cast revive"); ((MonoBehaviour)CS$<>8__locals0.<>4__this).StartCoroutine(AwaitAnimationEnd()); UnifiedPopup.Pop(); }; object obj2 = <>O.<0>__Pop; if (obj2 == null) { PopupButtonCallback val5 = UnifiedPopup.Pop; <>O.<0>__Pop = val5; obj2 = (object)val5; } UnifiedPopup.Push((PopupBase)new YesNoPopup("$ad_skathi_interact_title", "$ad_skathi_interact_message", val4, (PopupButtonCallback)obj2, true)); } return false; [IteratorStateMachine(typeof(<>c__DisplayClass1_0.<<Interact>g__AwaitAnimationEnd|2>d))] IEnumerator AwaitAnimationEnd() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass1_0.<<Interact>g__AwaitAnimationEnd|2>d(0) { <>4__this = CS$<>8__locals0 }; } [IteratorStateMachine(typeof(<>c__DisplayClass1_0.<<Interact>g__AwaitAnimationEnd|3>d))] IEnumerator AwaitAnimationEnd() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass1_0.<<Interact>g__AwaitAnimationEnd|3>d(0) { <>4__this = CS$<>8__locals0 }; } } public bool UseItem(Humanoid user, ItemData item) { return false; } public string GetHoverText() { string text = ""; if (Utils.CarriesTombstone(Player.m_localPlayer)) { text = "$ad_skathi_interact_tombstone"; } else { if (Afterdeath.skathiResurrection.Value == Afterdeath.Toggle.On) { text = "[<color=yellow><b>$KEY_Use</b></color>] $ad_skathi_hover_text"; } if (Afterdeath.baseResurrection.Value == Afterdeath.Toggle.On) { if (text.Length > 0) { text += "\n"; } text += "[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $ad_skathi_hover_text_alt"; } } return Localization.instance.Localize(text); } public string GetHoverName() { return Localization.instance.Localize("$ad_skathi_hover_name"); } } public class TombstoneRange : MonoBehaviour { [HarmonyPatch(typeof(TombStone), "Start")] private static class AddTombStoneRange { private static void Postfix(TombStone __instance) { ((Component)__instance).gameObject.AddComponent<TombstoneRange>(); } } [HarmonyPatch] private class AddCraftingAnimation { private static MethodInfo TargetMethod() { return typeof(Player).GetMethods().Single((MethodInfo m) => m.Name == "GetActionProgress" && m.GetParameters().Length == 3); } private static void Postfix(Player __instance, ref string name, ref float progress, ref MinorActionData data) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown PlayerGhost componentInChildren = ((Component)__instance).GetComponentInChildren<PlayerGhost>(); if (componentInChildren == null) { return; } float? resurrectionRemainingTime = componentInChildren.resurrectionRemainingTime; if (resurrectionRemainingTime.HasValue) { float valueOrDefault = resurrectionRemainingTime.GetValueOrDefault(); if (valueOrDefault < Utils.RespawnDelay()) { progress = 1f - valueOrDefault / Utils.RespawnDelay(); name = "$ad_respawning"; data = new MinorActionData { m_type = (ActionType)(-1), m_progressText = name, m_duration = 1f }; } } } } [HarmonyPatch(typeof(Player), "ClearActionQueue")] private class CancelResurrection { private static void Postfix(Player __instance) { ((Component)__instance).GetComponentInChildren<PlayerGhost>()?.ResetResurrection(); } } [HarmonyPatch(typeof(TombStone), "PositionCheck")] private static class DisablePositionCheck { private static bool Prefix(TombStone __instance) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) return ZDOMan.instance.GetZDO(((Component)__instance).GetComponent<ZNetView>().GetZDO().GetZDOID("Afterdeath Carried")) == null; } } private Vector3 lastPosition; private ZNetView netview; private ZSyncTransform syncTransform; public PlayerGhost? ghost; private FloatingTerrainDummy? dummy; private TombStone tombStone; private bool playerInRange; private bool? isOwner; private bool carried; private bool? inLava; public void Awake() { tombStone = ((Component)this).GetComponent<TombStone>(); Player localPlayer = Player.m_localPlayer; ghost = ((localPlayer != null) ? ((Component)localPlayer).GetComponentInChildren<PlayerGhost>() : null); netview = ((Component)this).GetComponent<ZNetView>(); syncTransform = ((Component)this).GetComponent<ZSyncTransform>(); netview.Unregister("OpenRespons"); netview.Register<bool>("OpenRespons", (Action<long, bool>)delegate(long uid, bool success) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ghost)) { ((Component)this).GetComponent<Container>().RPC_OpenRespons(uid, success); } else if (success) { syncTransform.m_characterParentSync = true; Transform val = ((Component)ghost).transform.Find("attach"); ((Component)this).transform.SetParent(val, false); ((Component)this).transform.localPosition = Vector3.zero; dummy = ((Component)this).GetComponent<FloatingTerrain>().m_dummy; if (Object.op_Implicit((Object)(object)dummy)) { ((Component)dummy).transform.SetParent(val, false); ((Behaviour)((Component)this).GetComponent<FloatingTerrain>()).enabled = false; ((Component)dummy).transform.localPosition = Vector3.zero; } netview.GetZDO().Set("Afterdeath Carried", ((Character)Player.m_localPlayer).GetZDOID()); } else { ((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_inuse", 0, (Sprite)null); } }); } private void Update() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!netview.IsValid()) { return; } OwnerUpdate(); Rigidbody component = ((Component)this).GetComponent<Rigidbody>(); if (component != null) { bool flag = ZDOMan.instance.GetZDO(netview.GetZDO().GetZDOID("Afterdeath Carried")) != null; if (component.isKinematic != flag) { ((Component)this).GetComponent<FloatingTerrain>().m_lastHeightmap = null; } ((Behaviour)((Component)this).GetComponent<FloatingTerrain>()).enabled = !flag; component.isKinematic = flag; } } private void OwnerUpdate() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ghost)) { return; } bool valueOrDefault = isOwner.GetValueOrDefault(); if (!isOwner.HasValue) { valueOrDefault = (Object)(object)tombStone.FindOwner() == (Object)(object)ghost.player; isOwner = valueOrDefault; } if (!isOwner.Value) { return; } if (Vector3.Distance(((Component)ghost).transform.position, ((Component)this).transform.position) > (float)Afterdeath.respawnRange.Value) { if (playerInRange) { playerInRange = false; ghost.ResetResurrection(); } return; } bool flag = tombStone.m_nview.GetZDO().GetZDOID("Afterdeath Carried") == ((Character)ghost.player).GetZDOID(); if (!carried || flag) { ghost.carriesStone = flag; carried = flag; } if (carried) { ((Component)this).transform.localPosition = Vector3.zero; if (Object.op_Implicit((Object)(object)dummy)) { ((Component)dummy).transform.localPosition = Vector3.zero; } } Vector3 position = ((Component)this).transform.position; float groundHeight = ZoneSystem.instance.GetGroundHeight(((Component)ghost).transform.position); if (!ghost.carriesStone && !playerInRange && position.y < 3500f) { if (!inLava.HasValue && WorldGenerator.IsAshlands(position.x, position.z)) { Vector3 val = default(Vector3); Biome val2 = default(Biome); BiomeArea val3 = default(BiomeArea); Heightmap val4 = default(Heightmap); ZoneSystem.instance.GetGroundData(ref position, ref val, ref val2, ref val3, ref val4); if (Object.op_Implicit((Object)(object)val4)) { inLava = Mathf.Min(new float[3] { 1f, val4.GetLava(position), Utils.SmoothStep(0.1f, 1f, val4.GetLava(position)) }) > ((Character)ghost.player).m_minLavaMaskThreshold; } } if ((ZoneSystem.instance.m_waterLevel > groundHeight && ((Component)tombStone).GetComponent<Floating>().GetFloatDepth() < 0f) || (((Character)ghost.player).AboveOrInLava() && inLava.GetValueOrDefault())) { tombStone.m_nview.InvokeRPC("RequestOpen", new object[1] { Game.instance.GetPlayerProfile().GetPlayerID() }); } } playerInRange = true; if (position.y < 2500f && (ZoneSystem.instance.m_waterLevel > groundHeight || ((Character)ghost.player).AboveOrInLava())) { if (flag) { ((Character)ghost.player).Message((MessageType)2, "$ad_tombstone_picked_up", 0, (Sprite)null); } ghost.ResetResurrection(); return; } if (flag) { if (!Minimap.instance.IsExplored(position)) { ((Character)ghost.player).Message((MessageType)2, "$ad_tombstone_picked_up", 0, (Sprite)null); return; } ((Component)tombStone).transform.SetParent((Transform)null); Vector3 val = position; val.y = groundHeight + 0.5f; Vector3 val5 = val; tombStone.m_nview.GetZDO().Set(ZDOVars.s_spawnPoint, val5); tombStone.m_nview.GetZDO().Set("Afterdeath Carried", ZDOID.None); ((Component)tombStone).transform.position = val5; if (dummy != null) { ((Component)dummy).transform.SetParent((Transform)null); ((Component)dummy).transform.position = val5; } carried = false; ghost.carriesStone = false; } float? resurrectionRemainingTime = ghost.resurrectionRemainingTime; if (!resurrectionRemainingTime.HasValue) { ghost.StartResurrection(); lastPosition = ((Component)ghost).transform.position; } else if (ghost.resurrectionRemainingTime <= 0f) { ((Character)ghost.player).GetSEMan().RemoveStatusEffect((StatusEffect)(object)Afterdeath.ghostStatus, false); ((Component)this).GetComponentInParent<TombStone>().m_container.TakeAll((Humanoid)(object)ghost.player); } else if (VectorExtensions.DistanceTo(lastPosition, ((Component)ghost).transform.position) > 0.2f) { ghost.ResetResurrection(); } } public void OnDestroy() { if (carried && Object.op_Implicit((Object)(object)ghost)) { ghost.carriesStone = false; } } } public static class Utils { public static T ConvertStatusEffect<T>(StatusEffect statusEffect) where T : StatusEffect { T val = ScriptableObject.CreateInstance<T>(); ((Object)(object)val).name = ((Object)statusEffect).name; FieldInfo[] fields = ((object)statusEffect).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(val, fieldInfo.GetValue(statusEffect)); } return val; } public static Vector3 GetClosestLocation(Vector3 position) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) IEnumerable<Vector3> source = ((!ZNet.instance.IsServer()) ? (from kv in ZoneSystem.instance.m_locationIcons where kv.Value == ((Object)Afterdeath.spiritHealerLocation.location).name select kv.Key) : (from i in ZoneSystem.instance.m_locationInstances.Values where i.m_location.m_prefabName == ((Object)Afterdeath.spiritHealerLocation.location).name select i.m_position)); return source.OrderBy((Vector3 p) => Utils.DistanceXZ(p, position)).FirstOrDefault(); } public static bool IsGhost(Player player) { if (player.m_customData.ContainsKey("Afterdeath Ghost")) { return !((Character)player).IsDead(); } return false; } public static bool CarriesTombstone(Player player) { SE_AfterDeath obj = ((Character)player).GetSEMan().GetStatusEffect(((StatusEffect)Afterdeath.ghostStatus).NameHash()) as SE_AfterDeath; if (obj == null) { return false; } return obj.wisp.GetComponent<PlayerGhost>().carriesStone; } public static void ClearCustomData(Player player) { player.m_customData.Remove("Afterdeath Ghost"); } public static int CurrentDay() { return EnvMan.instance.GetDay(ZNet.instance.GetTimeSeconds()); } public static int DeathCounter(Player player) { int result = 0; if (player.m_customData.TryGetValue("Afterdeath Death Counter", out var value) && value.StartsWith(CurrentDay() + " ", StringComparison.Ordinal)) { int.TryParse(player.m_customData["Afterdeath Death Counter"].Split(new char[1] { ' ' })[1], out result); } return result; } public static float RespawnDelay() { return Math.Min(Afterdeath.respawnTime.Value + Math.Max(0, DeathCounter(Player.m_localPlayer) - 1) * Afterdeath.repeatedRespawnMalus.Value, Afterdeath.respawnTimeCap.Value); } } } namespace ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry<T> : OwnConfigEntryBase { public readonly ConfigEntry<T> SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry<T> sourceConfig) { SourceConfig = sourceConfig; base..ctor(); } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })); }).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ZPlayFabSocket, ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; ((ZPlayFabSocket)this)..ctor(); } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (!__instance.IsServer()) { return; } BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket"); object? value = fieldInfo.GetValue(val); ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null); if (val2 != null) { typeof(ZPlayFabSocket).GetField("m_remotePlayerId").SetValue(bufferingSocket, val2.m_remotePlayerId); } fieldInfo.SetValue(val, bufferingSocket); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = bufferingSocket; } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZRpc rpc2 = rpc; ZNet __instance2 = __instance; Dictionary<Assembly, BufferingSocket> __state2 = __state; ZNetPeer peer; if (__instance2.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance2).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc2.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List<PackageEntry> entries = new List<PackageEntry>(); if (configSync.CurrentVersion != null) { entries.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); entries.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc2.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } private class PackageEntry { public string section = null; public string key = null; public Type type = null; public object? value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType); return false; } } [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] private static class PreventConfigRereadChangingValues { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, string value) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null) { return true; } try { ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType); } catch (Exception ex) { Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } return false; } } private class InvalidDeserializationTypeException : Exception { public string expected = null; public string received = null; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; public string? DisplayName; public string? CurrentVersion; public string? MinimumRequiredVersion; public bool ModRequired = false; private bool? forceConfigLocking; private bool isSourceOfTruth = true; private static readonly HashSet<ConfigSync> configSyncs; private readonly HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>(); private HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>(); private static bool isServer; private static bool lockExempt; private OwnConfigEntryBase? lockedConfig = null; private const byte PARTIAL_CONFIGS = 1; private const byte FRAGMENTED_CONFIG = 2; private const byte COMPRESSED_CONFIG = 4; private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>(); private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>(); private static long packageCounter; public bool IsLocked { get { bool? flag = forceConfigLocking; bool num; if (!flag.HasValue) { if (lockedConfig == null) { goto IL_0052; } num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0; } else { num = flag.GetValueOrDefault(); } if (!num) { goto IL_0052; } int result = ((!lockExempt) ? 1 : 0); goto IL_0053; IL_0053: return (byte)result != 0; IL_0052: result = 0; goto IL_0053; } set { forceConfigLocking = value; } } public bool IsAdmin => lockExempt || isSourceOfTruth; public bool IsSourceOfTruth { get { return isSourceOfTruth; } private set { if (value != isSourceOfTruth) { isSourceOfTruth = value; this.SourceOfTruthChanged?.Invoke(value); } } } public bool InitialSyncDone { get; private set; } = false; public event Action<bool>? SourceOfTruthChanged; private event Action? lockedConfigChanged; static ConfigSync() { ProcessingServerUpdate = false; configSyncs = new HashSet<ConfigSync>(); lockExempt = false; packageCounter = 0L; RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle); } public ConfigSync(string name) { Name = name; configSyncs.Add(this); new VersionCheck(this); } public SyncedConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry) { ConfigEntry<T> configEntry2 = configEntry; OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2); SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>; if (syncedEntry == null) { syncedEntry = new SyncedConfigEntry<T>(configEntry2); AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1] { new ConfigurationManagerAttributes() }.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray()); configEntry2.SettingChanged += delegate { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2); } }; allConfigs.Add(syncedEntry); } return syncedEntry; } public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible { if (lockedConfig != null) { throw new Exception("Cannot initialize locking ConfigEntry twice"); } lockedConfig = AddConfigEntry<T>(lockingConfig); lockingConfig.SettingChanged += delegate { this.lockedConfigChanged?.Invoke(); }; return (SyncedConfigEntry<T>)lockedConfig; } internal void AddCustomValue(CustomSyncedValueBase customValue) { CustomSyncedValueBase customValue2 = customValue; if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier)) { throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)"); } allCustomValues.Add(customValue2); allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority)); customValue2.ValueChanged += delegate { if (!ProcessingServerUpdate) { Broadcast(ZRoutedRpc.Everybody, customValue2); } }; } private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package) { lockedConfigChanged += serverLockedSettingChanged; IsSourceOfTruth = false; if (HandleConfigSyncRPC(0L, package, clientUpdate: false)) { InitialSyncDone = true; } } private void RPC_FromOtherClientConfigSync(long sender, ZPackage package) { HandleConfigSyncRPC(sender, package, clientUpdate: true); } private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown try { if (isServer && IsLocked) { ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc; object obj; if (currentRpc == null) { obj = null; } else { ISocket socket = currentRpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (text != null) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text })))) { return false; } } } cacheExpirations.RemoveAll(delegate(KeyValuePair<long, string> kv) { if (kv.Key < DateTimeOffset.Now.Ticks) { configValueCache.Remove(kv.Value); return true; } return false; }); byte b = package.ReadByte(); if ((b & 2u) != 0) { long num = package.ReadLong(); string text2 = sender.ToString() + num; if (!configValueCache.TryGetValue(text2, out SortedDictionary<int, byte[]> value)) { value = new SortedDictionary<int, byte[]>(); configValueCache[text2] = value; cacheExpirations.Add(new KeyValuePair<long, string>(DateTimeOffset.Now.AddSeconds(60.0).Ticks, text2)); } int key = package.ReadInt(); int num2 = package.ReadInt(); value.Add(key, package.ReadByteAr