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 Ultimate QOL v1.0.0
plugins/Ultimate_QOL.dll
Decompiled a day 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.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Ultimate QOL")] [assembly: AssemblyDescription("Performance-first quality-of-life super mod for Valheim: storage, crafting, building, stations, animals, farming, portals, sounds and server tools. Admin controlled, server synchronized.")] [assembly: AssemblyCompany("Igao")] [assembly: AssemblyProduct("Ultimate QOL")] [assembly: AssemblyCopyright("Igao")] [assembly: ComVisible(false)] [assembly: Guid("D2F5D9CF-E735-4F26-B5A5-E767431DAA10")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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; } } } internal static class SCMPanel { private sealed class PendingPanel { public string Command; public bool AdminOnly; } private static readonly object Gate = new object(); private static readonly List<PendingPanel> Pending = new List<PendingPanel>(); private static bool _assemblyHooked; public static void Register(string Command, bool AdminOnly = false) { if (string.IsNullOrWhiteSpace(Command)) { throw new ArgumentException("Panel command cannot be empty.", "Command"); } PendingPanel panel = new PendingPanel { Command = Command.Trim(), AdminOnly = AdminOnly }; if (TryRegister(panel)) { return; } lock (Gate) { if (!Pending.Any((PendingPanel p) => string.Equals(p.Command, panel.Command, StringComparison.OrdinalIgnoreCase) && p.AdminOnly == panel.AdminOnly)) { Pending.Add(panel); } if (!_assemblyHooked) { _assemblyHooked = true; AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad; } } } private static void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args) { try { if (!(args?.LoadedAssembly == null) && string.Equals(args.LoadedAssembly.GetName().Name, "Ultimate_SCM", StringComparison.OrdinalIgnoreCase)) { FlushPending(); } } catch { } } private static void FlushPending() { PendingPanel[] array; lock (Gate) { array = Pending.ToArray(); } PendingPanel[] array2 = array; foreach (PendingPanel pendingPanel in array2) { if (TryRegister(pendingPanel)) { lock (Gate) { Pending.Remove(pendingPanel); } } } lock (Gate) { if (Pending.Count == 0 && _assemblyHooked) { AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad; _assemblyHooked = false; } } } private static bool TryRegister(PendingPanel panel) { try { Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "Ultimate_SCM", StringComparison.OrdinalIgnoreCase)); if (assembly == null) { return false; } Type type = assembly.GetType("UltimateSCM.PanelAPI", throwOnError: false, ignoreCase: false); if (type == null) { return false; } MethodInfo method = type.GetMethod("RegisterPanelForAssembly", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(string), typeof(bool), typeof(Assembly) }, null); if (method == null) { return false; } method.Invoke(null, new object[3] { panel.Command, panel.AdminOnly, typeof(SCMPanel).Assembly }); return true; } catch { return false; } } } namespace UltimateQOL { internal static class BuildCam { internal const string RpcReq = "Igao.UQ.BuildCamReq"; internal const string RpcAns = "Igao.UQ.BuildCamAns"; internal static bool Active; private static Player _player; private static WardState _ws; private static float _yaw; private static float _pitch; private static Vector3 _vel; private static float _lastHealth; private static float _lastCombat = -1000f; private static float _blockedUntil; private static float _nextScan; private static bool _waiting; private static float _askedAt = -100f; private static string _revoke; private static readonly FieldRef<GameCamera, bool> FreeFly = Ref<GameCamera, bool>("m_freeFly"); private static readonly FieldRef<GameCamera, float> FlyYaw = Ref<GameCamera, float>("m_freeFlyYaw"); private static readonly FieldRef<GameCamera, float> FlyPitch = Ref<GameCamera, float>("m_freeFlyPitch"); private static readonly FieldRef<GameCamera, Vector3> FlyVel = Ref<GameCamera, Vector3>("m_freeFlyVel"); private static readonly FieldRef<GameCamera, Transform> FlyLockon = Ref<GameCamera, Transform>("m_freeFlyLockon"); private static readonly FieldRef<GameCamera, Transform> FlyTarget = Ref<GameCamera, Transform>("m_freeFlyTarget"); private static readonly FieldRef<Humanoid, ItemData> RightRef = Ref<Humanoid, ItemData>("m_rightItem"); private static readonly FieldRef<Humanoid, ItemData> LeftRef = Ref<Humanoid, ItemData>("m_leftItem"); internal const float Speed = 8f; internal const float FastFactor = 2f; private static readonly HashSet<long> Granted = new HashSet<long>(); private static readonly List<long> Scratch = new List<long>(8); private static float _nextServer; internal static bool Enabled => Cfg.BuildCamEnabled != null && Cfg.BuildCamEnabled.Value && WardSystem.SanctuaryOn; private static FieldRef<T, F> Ref<T, F>(string name) { try { return (AccessTools.Field(typeof(T), name) != null) ? AccessTools.FieldRefAccess<T, F>(name) : null; } catch { return null; } } internal static void NoteCombat() { _lastCombat = Time.time; } internal static void Tick() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Invalid comparison between Unknown and I4 //IL_00d3: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (Active) { if (GameAccess.KeyDown((KeyCode)27) || Menu.IsVisible() || ConfigPanel.IsOpen) { Exit("bc_closed"); return; } string text = ExitReason(localPlayer); if (text != null) { Exit(text); } } if (_waiting && Time.time - _askedAt > 4f) { _waiting = false; GameAccess.Center(Translation.T("bc_why_server")); } if (!((Object)(object)localPlayer == (Object)null) && Cfg.BuildCamKey != null && (int)Cfg.BuildCamKey.Value != 0 && !GameAccess.KeyboardBusy() && !QolUi.Modal && !ConfigPanel.IsOpen && GameAccess.KeyDown(Cfg.BuildCamKey.Value)) { if (Active) { Exit("bc_closed"); } else if (!_waiting) { TryEnter(localPlayer); } } } private static string ExitReason(Player local) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)local == (Object)null || local != _player || ((Character)local).IsDead() || (Object)(object)GameCamera.instance == (Object)null) { return "bc_closed"; } if (_revoke != null) { string revoke = _revoke; _revoke = null; return revoke; } if (!Enabled) { return "bc_exit_sanct"; } if ((Object)(object)_ws == (Object)null || !WardSystem.IsSanctuary(_ws) || !_ws.Contains(((Component)local).transform.position, 0f)) { return "bc_exit_sanct"; } if (((Character)local).IsTeleporting() || ((Character)local).IsAttached()) { return "bc_closed"; } float health = ((Character)local).GetHealth(); if (health < _lastHealth - 0.01f) { NoteCombat(); return "bc_exit_hit"; } _lastHealth = health; if (!HoldsHammer(local)) { return "bc_exit_tool"; } if (Time.time >= _nextScan) { _nextScan = Time.time + 0.4f; if (HostileNear(local)) { return "bc_exit_enemy"; } } return null; } private static void TryEnter(Player local) { //IL_00c9: 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_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Expected O, but got Unknown if (!Enabled) { GameAccess.Center(Translation.T("bc_why_off")); } else { if (AdminFreecam.Active || ((Character)local).IsDead() || ((Character)local).IsTeleporting() || ((Character)local).IsAttached() || ((Character)local).IsSwimming()) { return; } if (Time.time < _blockedUntil) { GameAccess.Center(Translation.T("bc_why_wait")); return; } if (Time.time - _lastCombat < (float)Mathf.Max(1, Cfg.BuildCamCombatSeconds.Value)) { GameAccess.Center(Translation.T("bc_why_combat")); return; } WardState wardState = WardSystem.SanctuaryAt(((Component)local).transform.position); if ((Object)(object)wardState == (Object)null) { GameAccess.Center(Translation.T("bc_why_sanct")); return; } if (!HoldsHammer(local)) { GameAccess.Center(Translation.T("bc_why_tool")); return; } if (HostileNear(local)) { GameAccess.Center(Translation.T("bc_why_enemy")); return; } ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || ZRoutedRpc.instance == null) { return; } if (instance.IsServer()) { string text = ServerCheck(((Component)local).transform.position, remote: false); if (text != null) { GameAccess.Center(Translation.T(text)); } else { Enter(local, wardState); } return; } if (!ConfigSync.ServerHasMod) { GameAccess.Center(Translation.T("bc_why_off")); return; } ZPackage val = new ZPackage(); val.Write(true); _waiting = true; _askedAt = Time.time; ZNetPeer serverPeer = instance.GetServerPeer(); if (serverPeer != null) { ZRoutedRpc.instance.InvokeRoutedRPC(serverPeer.m_uid, "Igao.UQ.BuildCamReq", new object[1] { val }); } } } internal static void OnAnswer(long sender, ZPackage pkg) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) try { bool flag = pkg.ReadBool(); string text = pkg.ReadString(); Player localPlayer = Player.m_localPlayer; if (flag) { if (_waiting && !((Object)(object)localPlayer == (Object)null)) { _waiting = false; WardState wardState = WardSystem.SanctuaryAt(((Component)localPlayer).transform.position); if ((Object)(object)wardState == (Object)null || !Enabled || !HoldsHammer(localPlayer) || HostileNear(localPlayer)) { SendRelease(); } else { Enter(localPlayer, wardState); } } } else { _waiting = false; if (Active) { _revoke = (string.IsNullOrEmpty(text) ? "bc_exit_sanct" : text); } else { GameAccess.Center(Translation.T(string.IsNullOrEmpty(text) ? "bc_why_sanct" : text)); } } } catch (Exception ex) { Plugin.Warn("Build camera answer: " + ex.Message); } } private static void SendRelease() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown try { ZNet instance = ZNet.instance; if (!((Object)(object)instance == (Object)null) && !instance.IsServer() && ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(false); ZNetPeer serverPeer = instance.GetServerPeer(); if (serverPeer != null) { ZRoutedRpc.instance.InvokeRoutedRPC(serverPeer.m_uid, "Igao.UQ.BuildCamReq", new object[1] { val }); } } } catch { } } private static void Enter(Player p, WardState ws) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00fb: Unknown result type (might be due to invalid IL or missing references) GameCamera instance = GameCamera.instance; if ((Object)(object)instance == (Object)null || FreeFly == null) { SendRelease(); return; } try { _player = p; _ws = ws; _lastHealth = ((Character)p).GetHealth(); _vel = Vector3.zero; _revoke = null; Vector3 eulerAngles = ((Component)instance).transform.eulerAngles; _yaw = eulerAngles.y; _pitch = Mathf.Clamp((eulerAngles.x > 180f) ? (eulerAngles.x - 360f) : eulerAngles.x, -89f, 89f); if (FlyYaw != null) { FlyYaw.Invoke(instance) = eulerAngles.y; } if (FlyPitch != null) { FlyPitch.Invoke(instance) = _pitch; } if (FlyVel != null) { FlyVel.Invoke(instance) = Vector3.zero; } if (FlyLockon != null) { FlyLockon.Invoke(instance) = null; } if (FlyTarget != null) { FlyTarget.Invoke(instance) = null; } if (!FreeFly.Invoke(instance)) { instance.ToggleFreeFly(); } Active = true; GameAccess.Center(Translation.T("bc_on", ((object)Unsafe.As<KeyCode, KeyCode>(ref Cfg.BuildCamKey.Value)/*cast due to .constrained prefix*/).ToString())); } catch (Exception ex) { Plugin.Warn("Build camera could not start: " + ex.Message); Active = true; Exit(null); } } private static void Exit(string messageKey) { //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) bool active = Active; Active = false; try { GameCamera instance = GameCamera.instance; if ((Object)(object)instance != (Object)null && FreeFly != null && FreeFly.Invoke(instance)) { instance.ToggleFreeFly(); } } catch (Exception ex) { Plugin.Warn("Build camera could not stop cleanly: " + ex.Message); } _player = null; _ws = null; _vel = Vector3.zero; _blockedUntil = Time.time + (float)Mathf.Max(0, (Cfg.BuildCamCooldown != null) ? Cfg.BuildCamCooldown.Value : 0); if (active) { SendRelease(); } if (!string.IsNullOrEmpty(messageKey)) { GameAccess.Center(Translation.T(messageKey)); } } private static bool HoldsHammer(Player p) { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Invalid comparison between Unknown and I4 //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Invalid comparison between Unknown and I4 try { ItemData val = ((RightRef != null) ? RightRef.Invoke((Humanoid)(object)p) : null); if (val == null || val.m_shared == null || (Object)(object)val.m_shared.m_buildPieces == (Object)null) { return false; } if (!(val.m_shared.m_name == "$item_hammer") && ((Object)val.m_shared.m_buildPieces).name.IndexOf("Hammer", StringComparison.OrdinalIgnoreCase) < 0) { return false; } ItemData val2 = ((LeftRef != null) ? LeftRef.Invoke((Humanoid)(object)p) : null); if (val2 != null && val2.m_shared != null && (Object)(object)val2.m_shared.m_buildPieces == (Object)null && (int)val2.m_shared.m_itemType != 15 && (int)val2.m_shared.m_itemType != 5) { return false; } return true; } catch { return false; } } private static bool HostileNear(Player p) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0078: Unknown result type (might be due to invalid IL or missing references) //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) float num = Mathf.Max(10, (Cfg.BuildCamEnemyRadius != null) ? Cfg.BuildCamEnemyRadius.Value : 40); float num2 = num * num; Vector3 position = ((Component)p).transform.position; List<Character> allCharacters = Character.GetAllCharacters(); for (int i = 0; i < allCharacters.Count; i++) { Character val = allCharacters[i]; if ((Object)(object)val == (Object)null || (object)val == p || val.IsDead()) { continue; } Vector3 val2 = ((Component)val).transform.position - position; if (((Vector3)(ref val2)).sqrMagnitude > num2) { continue; } Player val3 = (Player)(object)((val is Player) ? val : null); if ((Object)(object)val3 != (Object)null) { if (((Character)val3).IsPVPEnabled() && ((Character)p).IsPVPEnabled()) { return true; } } else if (!val.IsTamed() && (Object)(object)((Component)val).GetComponent<MonsterAI>() != (Object)null && BaseAI.IsEnemy(val, (Character)(object)p)) { return true; } } return false; } private static bool PanelOpen() { try { if (Hud.IsPieceSelectionVisible()) { return true; } if (InventoryGui.IsVisible()) { return true; } if (Menu.IsActive()) { return true; } } catch { } return false; } private static bool Button(string name) { try { return ZInput.GetButton(name); } catch { return false; } } internal static void MoveCamera(GameCamera gc, float dt) { //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_00d5: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0075: 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_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: 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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: 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_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0152: 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_0293: 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_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: 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_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gc == (Object)null || dt <= 0f || (Object)(object)_player == (Object)null) { return; } Transform transform = ((Component)gc).transform; if (PanelOpen()) { _vel = Vector3.zero; return; } if (!Console.IsVisible() && !GameAccess.KeyboardBusy()) { Vector2 val = ZInput.GetMouseDelta() * PlayerController.m_mouseSens; _yaw += val.x; _pitch += (PlayerController.m_invertMouse ? val.y : (0f - val.y)); _pitch = Mathf.Clamp(_pitch, -89f, 89f); } Quaternion val2 = Quaternion.Euler(_pitch, _yaw, 0f); Vector3 val3 = Vector3.zero; if (!GameAccess.KeyboardBusy()) { Vector3 val4 = val2 * Vector3.forward; Vector3 val5 = val2 * Vector3.right; if (Button("Forward")) { val3 += val4; } if (Button("Backward")) { val3 -= val4; } if (Button("Right")) { val3 += val5; } if (Button("Left")) { val3 -= val5; } if (Button("Jump")) { val3 += Vector3.up; } if (Button("Crouch")) { val3 -= Vector3.up; } if (((Vector3)(ref val3)).sqrMagnitude > 1f) { ((Vector3)(ref val3)).Normalize(); } val3 *= 8f * (Button("Run") ? 2f : 1f); } _vel = Vector3.Lerp(_vel, val3, Mathf.Clamp01(dt * 10f)); Vector3 val6 = transform.position + _vel * dt; Vector3 position = ((Component)_player).transform.position; float num = Mathf.Max(5, (Cfg.BuildCamRadius != null) ? Cfg.BuildCamRadius.Value : 25); Vector3 val7 = val6 - position; if (((Vector3)(ref val7)).sqrMagnitude > num * num) { val6 = position + ((Vector3)(ref val7)).normalized * num; } if ((Object)(object)_ws != (Object)null && !_ws.Contains(val6, 0f)) { val6 = transform.position; _vel = Vector3.zero; } if ((Object)(object)ZoneSystem.instance != (Object)null) { float groundHeight = ZoneSystem.instance.GetGroundHeight(val6); if (val6.y < groundHeight + 0.5f) { val6.y = groundHeight + 0.5f; } } transform.position = val6; transform.rotation = val2; } private static string ServerCheck(Vector3 pos, bool remote) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (Cfg.BuildCamEnabled == null || !Cfg.BuildCamEnabled.Value || !WardSystem.SanctuaryOn) { return "bc_why_off"; } if (!(remote ? WardSystem.SanctuaryInWorldData(pos) : WardSystem.InSanctuary(pos))) { return "bc_why_sanct"; } return null; } internal static void OnRequest(long sender, ZPackage pkg) { //IL_005b: 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_008b: Expected O, but got Unknown try { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || !instance.IsServer() || sender == 0) { return; } if (!pkg.ReadBool()) { Granted.Remove(sender); return; } ZNetPeer peer = instance.GetPeer(sender); string text = ((peer == null) ? "bc_why_off" : ServerCheck(peer.m_refPos, remote: true)); if (text == null) { Granted.Add(sender); } ZPackage val = new ZPackage(); val.Write(text == null); val.Write(text ?? ""); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "Igao.UQ.BuildCamAns", new object[1] { val }); } catch (Exception ex) { Plugin.Warn("Build camera request: " + ex.Message); } } internal static void ServerStep() { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || !instance.IsServer() || Granted.Count == 0 || Time.time < _nextServer) { return; } _nextServer = Time.time + 1f; Scratch.Clear(); foreach (long item in Granted) { Scratch.Add(item); } for (int i = 0; i < Scratch.Count; i++) { long num = Scratch[i]; ZNetPeer peer = instance.GetPeer(num); if (peer == null) { Granted.Remove(num); continue; } string text = ServerCheck(peer.m_refPos, remote: true); if (text != null) { Granted.Remove(num); ZPackage val = new ZPackage(); val.Write(false); val.Write("bc_exit_sanct"); ZRoutedRpc.instance.InvokeRoutedRPC(num, "Igao.UQ.BuildCamAns", new object[1] { val }); } } } internal static void Reset() { Granted.Clear(); _waiting = false; if (Active) { Exit(null); } } } [HarmonyPatch(typeof(GameCamera), "UpdateFreeFly")] internal static class BuildCamMovePatch { [HarmonyPriority(600)] private static bool Prefix(GameCamera __instance, float dt) { if (!BuildCam.Active) { return true; } try { BuildCam.MoveCamera(__instance, dt); } catch { } return false; } } [HarmonyPatch(typeof(GameCamera), "InFreeFly")] internal static class BuildCamInputPatch { private static void Postfix(ref bool __result) { if (BuildCam.Active) { __result = false; } } } internal static class BuildCamFind { internal static MethodBase Method(Type type, string name) { try { MethodBase methodBase = null; MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == name && (methodBase == null || methodInfo.GetParameters().Length > methodBase.GetParameters().Length)) { methodBase = methodInfo; } } return methodBase; } catch { return null; } } } internal static class BuildCamControls { private static readonly MethodBase SetControls = BuildCamFind.Method(typeof(Player), "SetControls"); internal static void Zero(Player p) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || SetControls == null) { return; } try { ParameterInfo[] parameters = SetControls.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Type type = parameters[i].ParameterType; if (type.IsByRef) { type = type.GetElementType(); } array[i] = ((type == typeof(Vector3)) ? ((object)Vector3.zero) : ((type == typeof(bool)) ? ((object)false) : (type.IsValueType ? Activator.CreateInstance(type) : null))); } SetControls.Invoke(p, array); } catch { } } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class BuildCamControlsPatch { private static readonly FieldRef<Player, bool> AutoRun = SafeRef(); private static FieldRef<Player, bool> SafeRef() { try { return (AccessTools.Field(typeof(Player), "m_autoRun") != null) ? AccessTools.FieldRefAccess<Player, bool>("m_autoRun") : null; } catch { return null; } } internal static bool Frozen(Player p) { return (BuildCam.Active || AdminFreecam.Active) && (Object)(object)p != (Object)null && p == Player.m_localPlayer; } internal static void StopAutoRun(Player p) { if (AutoRun != null && (Object)(object)p != (Object)null) { AutoRun.Invoke(p) = false; } } private static void Prefix(Player __instance, ref Vector3 movedir, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold, ref bool jump, ref bool crouch, ref bool run, ref bool autoRun, ref bool dodge) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (Frozen(__instance)) { movedir = Vector3.zero; attack = (attackHold = (secondaryAttack = (secondaryAttackHold = false))); block = (blockHold = (jump = (crouch = (run = (autoRun = (dodge = false)))))); StopAutoRun(__instance); } } } [HarmonyPatch(typeof(PlayerController), "FixedUpdate")] internal static class BuildCamControllerPatch { private static void Postfix() { Player localPlayer = Player.m_localPlayer; if (BuildCamControlsPatch.Frozen(localPlayer)) { BuildCamControlsPatch.StopAutoRun(localPlayer); if (BuildCam.Active) { BuildCamControls.Zero(localPlayer); } } } } [HarmonyPatch] internal static class BuildCamReachPatch { private static readonly FieldInfo EyeField = AccessTools.Field(typeof(Character), "m_eye"); private static Transform _eye; private static Vector3 _saved; private static bool _moved; private static IEnumerable<MethodBase> TargetMethods() { string[] names = new string[2] { "PieceRayTest", "RemovePiece" }; int i = 0; while (i < names.Length) { MethodBase m = BuildCamFind.Method(typeof(Player), names[i]); if (m != null) { yield return m; } int num = i + 1; i = num; } } private static void Prefix(Player __instance) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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) _moved = false; if (BuildCam.Active && __instance == Player.m_localPlayer && !(EyeField == null) && !((Object)(object)GameCamera.instance == (Object)null)) { object? value = EyeField.GetValue(__instance); Transform val = (Transform)((value is Transform) ? value : null); if (!((Object)(object)val == (Object)null)) { _eye = val; _saved = val.position; val.position = ((Component)GameCamera.instance).transform.position; _moved = true; } } } private static void Finalizer() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (_moved) { _moved = false; if ((Object)(object)_eye != (Object)null) { _eye.position = _saved; } } } } [HarmonyPatch] internal static class BuildCamUseItemPatch { private static MethodBase Find() { return AccessTools.Method(typeof(Humanoid), "UseItem", (Type[])null, (Type[])null); } private static bool Prepare() { return Find() != null; } private static MethodBase TargetMethod() { return Find(); } private static bool Prefix(Humanoid __instance, object[] __args) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 if (!BuildCam.Active || (object)__instance != Player.m_localPlayer || __args == null) { return true; } foreach (object obj in __args) { ItemData val = (ItemData)((obj is ItemData) ? obj : null); if (val != null && val.m_shared != null && (int)val.m_shared.m_itemType == 2) { return false; } } return true; } } [HarmonyPatch(typeof(Humanoid), "StartAttack")] internal static class BuildCamAttackPatch { private static void Postfix(Humanoid __instance, bool __result) { try { if (__result && (object)__instance == Player.m_localPlayer) { ItemData currentWeapon = __instance.GetCurrentWeapon(); if (currentWeapon == null || currentWeapon.m_shared == null || !((Object)(object)currentWeapon.m_shared.m_buildPieces != (Object)null)) { BuildCam.NoteCombat(); } } } catch { } } } [HarmonyPatch(typeof(EnemyHud), "TestShow")] internal static class BuildCamEnemyHudPatch { private static void Postfix(ref bool __result) { if (__result && BuildCam.Active && Cfg.BuildCamHideEnemies != null && Cfg.BuildCamHideEnemies.Value) { __result = false; } } } internal static class BuildPull { private static int _handledFrame = -1; private static float _lastAt = -10f; private static readonly List<Container> Pool = new List<Container>(32); private static bool _menuWasOpen; private static Piece _retryPiece; private static float _retryAt = -1f; private static readonly Dictionary<string, int> RetryLeft = new Dictionary<string, int>(StringComparer.Ordinal); private static readonly Dictionary<string, int> NoLimit = null; private static readonly FieldInfo HoveredButtonField = AccessTools.Field(typeof(BuildUi), "m_currentHoveredPieceButton"); private static readonly FieldInfo HoveredPieceField = AccessTools.Field(typeof(Hud), "m_hoveredPiece"); internal static bool On => Cfg.BuildPullMaterials != null && Cfg.BuildPullMaterials.Value; internal static bool Poll(bool fromGameClick) { try { if (!On || _handledFrame == Time.frameCount) { return false; } Player localPlayer = Player.m_localPlayer; Hud instance = Hud.instance; bool flag = (Object)(object)localPlayer != (Object)null && (Object)(object)instance != (Object)null && !((Character)localPlayer).IsDead() && Hud.IsPieceSelectionVisible(); if (flag && !_menuWasOpen) { Prewarm(localPlayer); } _menuWasOpen = flag; if (_retryAt >= 0f && Time.time >= _retryAt) { Retry(localPlayer); } if (!fromGameClick && !ZInput.GetMouseButtonDown(1)) { return false; } if (!flag) { return false; } Piece val = HoveredPiece(instance); if ((Object)(object)val == (Object)null) { return false; } _handledFrame = Time.frameCount; if (Time.time - _lastAt < 0.15f) { return true; } _lastAt = Time.time; _retryAt = -1f; _retryPiece = null; RetryLeft.Clear(); Pull(localPlayer, val, NoLimit, mayRetry: true); return true; } catch (Exception ex) { Plugin.Warn("Right-click materials: " + ex.Message); return false; } } private static Piece HoveredPiece(Hud hud) { try { if ((Object)(object)hud.m_buildUi != (Object)null && HoveredButtonField != null) { object? value = HoveredButtonField.GetValue(hud.m_buildUi); BuildUiPieceButton val = (BuildUiPieceButton)((value is BuildUiPieceButton) ? value : null); if ((Object)(object)val != (Object)null && (Object)(object)val.Piece != (Object)null) { return val.Piece; } } if (HoveredPieceField != null) { object? value2 = HoveredPieceField.GetValue(hud); return (Piece)((value2 is Piece) ? value2 : null); } } catch { } return null; } private static void Say(Player player, string text) { ((Character)player).Message((MessageType)1, text, 0, (Sprite)null, false); } private static string Pretty(string shared) { return GameAccess.Localize(shared); } private static void Prewarm(Player player) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) try { ContainerRegistry.Query(((Component)player).transform.position, Cfg.BuildingRange.Value, automation: false, player.GetPlayerID(), Pool); for (int i = 0; i < Pool.Count; i++) { ContainerRegistry.PlayerReady(Pool[i]); } } catch { } Pool.Clear(); } private static void Retry(Player player) { _retryAt = -1f; Piece retryPiece = _retryPiece; _retryPiece = null; if (!((Object)(object)player == (Object)null) && !((Object)(object)retryPiece == (Object)null) && RetryLeft.Count != 0 && Hud.IsPieceSelectionVisible()) { Dictionary<string, int> only = new Dictionary<string, int>(RetryLeft, StringComparer.Ordinal); RetryLeft.Clear(); Pull(player, retryPiece, only, mayRetry: false); } } private static void Pull(Player player, Piece piece, Dictionary<string, int> only, bool mayRetry) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: 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_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) string text = Pretty(piece.m_name); Requirement[] resources = piece.m_resources; if (resources == null || resources.Length == 0) { Say(player, Translation.T("pull_free", text)); return; } ContainerRegistry.PlayerClaimPending = false; ContainerRegistry.Query(((Component)player).transform.position, Cfg.BuildingRange.Value, automation: false, player.GetPlayerID(), Pool); if (Pool.Count == 0) { Say(player, Translation.T("pull_nochest")); return; } Inventory inventory = ((Humanoid)player).GetInventory(); int num = ((Cfg.CraftKeepOne != null && Cfg.CraftKeepOne.Value) ? 1 : 0); List<string> list = new List<string>(4); List<string> list2 = new List<string>(4); bool flag = false; bool flag2 = false; foreach (Requirement val in resources) { if (val == null || (Object)(object)val.m_resItem == (Object)null) { continue; } ItemData itemData = val.m_resItem.m_itemData; string name = itemData.m_shared.m_name; int num2 = val.GetAmount(1); if (only != null) { num2 = (only.TryGetValue(name, out var value) ? Mathf.Min(num2, value) : 0); } if (num2 <= 0) { continue; } int num3 = ContainerRegistry.FreeSpaceFor(inventory, itemData); int num4 = Mathf.Min(num2, num3); if (num4 < num2) { flag = true; } if (num4 <= 0) { continue; } int num5 = 0; for (int j = 0; j < Pool.Count; j++) { if (num5 >= num4) { break; } Inventory inventory2 = Pool[j].GetInventory(); if (inventory2 != null && inventory2.CountItems(name, -1, false) > num && ContainerRegistry.PrepareWrite(Pool[j])) { int num6 = inventory2.CountItems(name, -1, false) - num; int num7 = Mathf.Min(num4 - num5, num6); if (num7 > 0) { inventory2.RemoveItem(name, num7, -1, false); num5 += num7; } } } if (num5 < num4) { if (ContainerRegistry.PlayerClaimPending) { RetryLeft[name] = num4 - num5; } else { flag2 = true; } } if (num5 <= 0) { if (!RetryLeft.ContainsKey(name)) { list2.Add(Pretty(name)); } continue; } ItemData val2 = ContainerTransfer.Template(val.m_resItem, cheated: false); int num8 = ContainerRegistry.AddExact(inventory, val2, num5); if (num8 < num5) { Transform transform = ((Component)player).transform; ItemDrop.DropItem(val2, num5 - num8, transform.position + transform.forward + Vector3.up, transform.rotation); flag = true; } list.Add(num5 + " " + Pretty(name)); } Pool.Clear(); NearbyCounts.InvalidateAll(); bool flag3 = RetryLeft.Count > 0; if (flag3 && mayRetry) { _retryPiece = piece; _retryAt = Time.time + 1.5f + 0.3f; } else if (flag3) { foreach (string key in RetryLeft.Keys) { list2.Add(Pretty(key)); } RetryLeft.Clear(); flag2 = true; } if (list.Count == 0) { if (flag3 && mayRetry) { Say(player, Translation.T("pull_wait")); return; } if (flag && list2.Count == 0) { Say(player, Translation.T("pull_full")); return; } Say(player, Translation.T("pull_none", string.Join(", ", list2.ToArray()))); return; } try { if (((Humanoid)player).m_pickupEffects != null) { ((Humanoid)player).m_pickupEffects.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, ZDOID.None); } } catch { } string text2 = (flag ? Translation.T("pull_sfx_full") : ((flag2 || list2.Count > 0) ? Translation.T("pull_sfx_short") : "")); Say(player, Translation.T("pull_done", string.Join(", ", list.ToArray()), text2)); } } [HarmonyPatch(typeof(Hud), "OnRightClickPiece")] internal static class BuildPullHudPatch { private static bool Prefix() { return !BuildPull.Poll(fromGameClick: true); } } [HarmonyPatch(typeof(BuildUi), "Update")] internal static class BuildPullUiPatch { private static void Prefix() { BuildPull.Poll(fromGameClick: false); } } internal static class TreeRegrow { private static readonly int HTree = StringExtensionMethods.GetStableHashCode("Igao.UQ.treeprefab"); private static readonly int HCut = StringExtensionMethods.GetStableHashCode("Igao.UQ.treecut"); private static readonly int HScale = StringExtensionMethods.GetStableHashCode("Igao.UQ.treescale"); private const float CheckEvery = 120f; private const float BlockedRetry = 300f; private const float FallbackMinutes = 60f; private const float SaplingMinutes = 10f; private static readonly List<ZNetView> Stumps = new List<ZNetView>(64); private static readonly Dictionary<ZNetView, float> RetryAt = new Dictionary<ZNetView, float>(); private static readonly Dictionary<string, string> Saplings = new Dictionary<string, string>(StringComparer.Ordinal); private static readonly Dictionary<string, float> SaplingRadius = new Dictionary<string, float>(StringComparer.Ordinal); private static readonly Dictionary<string, float> SaplingSeconds = new Dictionary<string, float>(StringComparer.Ordinal); private static readonly Collider[] Hits = (Collider[])(object)new Collider[64]; private static int _spaceMask; private static readonly HashSet<int> StubHashes = new HashSet<int>(); private static bool _stubsScanned; private static float _next; private static bool _plantsScanned; internal static bool Falling; internal static string FallingName; internal static string FallingStub; internal static Vector3 FallingPos; internal static float FallingScale = 1f; internal static bool Enabled => Cfg.TreeRegrow != null && Cfg.TreeRegrow.Value; internal static void OnViewAwake(ZNetView view) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)view == (Object)null) { return; } ZDO zDO = view.GetZDO(); if (zDO == null || !zDO.IsValid()) { return; } if (!_stubsScanned) { ScanStubs(); } if (!StubHashes.Contains(zDO.GetPrefab())) { return; } if (Falling && view.IsOwner()) { string prefabName = Utils.GetPrefabName(((Component)view).gameObject); if (prefabName == FallingStub) { Vector3 val = ((Component)view).transform.position - FallingPos; if (((Vector3)(ref val)).sqrMagnitude < 4f) { zDO.Set(HTree, FallingName); zDO.Set(HCut, (long)ZNet.instance.GetTimeSeconds()); zDO.Set(HScale, FallingScale); Falling = false; } } } if (zDO.GetString(HTree, "").Length > 0) { Stumps.Add(view); } } internal static void Step() { if (Stumps.Count == 0) { return; } float time = Time.time; if (time < _next) { return; } _next = time + 120f; if (!Enabled) { return; } ZNetScene instance = ZNetScene.instance; ZNet instance2 = ZNet.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null) { return; } double timeSeconds = instance2.GetTimeSeconds(); for (int num = Stumps.Count - 1; num >= 0; num--) { ZNetView val = Stumps[num]; if ((Object)(object)val == (Object)null || !val.IsValid()) { RetryAt.Remove(val); Stumps.RemoveAt(num); } else if (val.IsOwner()) { ZDO zDO = val.GetZDO(); string text = zDO.GetString(HTree, ""); if (text.Length == 0) { RetryAt.Remove(val); Stumps.RemoveAt(num); } else { double num2 = zDO.GetLong(HCut, 0L); double num3 = WaitSeconds(text, instance); if (!(timeSeconds - num2 < num3) && (!RetryAt.TryGetValue(val, out var value) || !(time < value)) && !Grow(val, zDO, text, instance, timeSeconds - num2)) { RetryAt[val] = time + 300f; } } } } } private static bool Grow(ZNetView stump, ZDO zdo, string tree, ZNetScene scene, double elapsed) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_013d: 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) string value; bool flag = Saplings.TryGetValue(tree, out value); if (flag && !SaplingFits(stump, tree)) { if (!SaplingSeconds.TryGetValue(tree, out var value2) || elapsed < (double)value2) { return false; } flag = false; } GameObject prefab = scene.GetPrefab(flag ? value : tree); if ((Object)(object)prefab == (Object)null) { zdo.Set(HTree, ""); return true; } Vector3 position = ((Component)stump).transform.position; if (Blocked(position)) { return false; } Quaternion val = (flag ? Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) : ((Component)stump).transform.rotation); float num = (flag ? 1f : zdo.GetFloat(HScale, 1f)); GameObject val2 = Object.Instantiate<GameObject>(prefab, position, val); if ((Object)(object)val2 == (Object)null) { return false; } if (Mathf.Abs(num - 1f) > 0.001f) { val2.transform.localScale = new Vector3(num, num, num); ZNetView component = val2.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { try { MethodInfo methodInfo = AccessTools.Method(typeof(ZNetView), "SetLocalScale", new Type[1] { typeof(Vector3) }, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(component, new object[1] { val2.transform.localScale }); } } catch { } } } RetryAt.Remove(stump); scene.Destroy(((Component)stump).gameObject); return true; } private static bool SaplingFits(ZNetView stump, string tree) { //IL_0077: 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_00dd: Invalid comparison between Unknown and I4 if (!SaplingRadius.TryGetValue(tree, out var value) || value <= 0f) { return true; } try { if (_spaceMask == 0) { _spaceMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" }); } int num = Physics.OverlapSphereNonAlloc(((Component)stump).transform.position, value, Hits, _spaceMask); for (int i = 0; i < num; i++) { Collider val = Hits[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).GetComponentInParent<ZNetView>() == (Object)(object)stump)) { Plant component = ((Component)val).GetComponent<Plant>(); if (!((Object)(object)component != (Object)null) || (int)component.GetStatus() <= 0) { return false; } } } } catch { } return true; } private static bool Blocked(Vector3 pos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) try { Collider[] array = Physics.OverlapSphere(pos + Vector3.up * 1.5f, 1.4f); foreach (Collider val in array) { if (!((Object)(object)val == (Object)null)) { if ((Object)(object)((Component)val).GetComponentInParent<Piece>() != (Object)null) { return true; } if ((Object)(object)((Component)val).GetComponentInParent<Character>() != (Object)null) { return true; } } } } catch { } return false; } private static void ScanStubs() { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return; } try { FieldInfo fieldInfo = AccessTools.Field(typeof(ZNetScene), "m_prefabs"); List<GameObject> list = ((fieldInfo != null) ? (fieldInfo.GetValue(instance) as List<GameObject>) : null); if (list == null) { return; } for (int i = 0; i < list.Count; i++) { TreeBase val = (((Object)(object)list[i] != (Object)null) ? list[i].GetComponent<TreeBase>() : null); if ((Object)(object)val != (Object)null && (Object)(object)val.m_stubPrefab != (Object)null) { StubHashes.Add(StringExtensionMethods.GetStableHashCode(((Object)val.m_stubPrefab).name)); } } _stubsScanned = StubHashes.Count > 0; } catch (Exception ex) { _stubsScanned = true; Plugin.Warn("Tree stumps: " + ex.Message); } } private static float WaitSeconds(string tree, ZNetScene scene) { if (!_plantsScanned) { ScanPlants(scene); } return (Saplings.ContainsKey(tree) ? 10f : 60f) * 60f; } private static void ScanPlants(ZNetScene scene) { _plantsScanned = true; try { FieldInfo fieldInfo = AccessTools.Field(typeof(ZNetScene), "m_prefabs"); List<GameObject> list = ((fieldInfo != null) ? (fieldInfo.GetValue(scene) as List<GameObject>) : null); if (list == null) { return; } for (int i = 0; i < list.Count; i++) { GameObject val = list[i]; Plant val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Plant>() : null); if ((Object)(object)val2 == (Object)null || val2.m_grownPrefabs == null) { continue; } for (int j = 0; j < val2.m_grownPrefabs.Length; j++) { GameObject val3 = val2.m_grownPrefabs[j]; if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.GetComponent<TreeBase>() == (Object)null) && !Saplings.ContainsKey(((Object)val3).name)) { Saplings[((Object)val3).name] = ((Object)val).name; SaplingRadius[((Object)val3).name] = val2.m_growRadius; SaplingSeconds[((Object)val3).name] = (val2.m_growTime + Mathf.Max(val2.m_growTime, val2.m_growTimeMax)) * 0.5f; } } } } catch (Exception ex) { Plugin.Warn("Tree saplings: " + ex.Message); } } internal static void Reset() { Stumps.Clear(); RetryAt.Clear(); Falling = false; } } [HarmonyPatch(typeof(TreeBase), "RPC_Damage")] internal static class TreeRegrowFallPatch { private static void Prefix(TreeBase __instance) { //IL_0053: 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_0063: Unknown result type (might be due to invalid IL or missing references) try { TreeRegrow.Falling = false; if (TreeRegrow.Enabled && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.m_stubPrefab == (Object)null)) { TreeRegrow.FallingName = Utils.GetPrefabName(((Component)__instance).gameObject); TreeRegrow.FallingStub = Utils.GetPrefabName(__instance.m_stubPrefab); TreeRegrow.FallingPos = ((Component)__instance).transform.position; TreeRegrow.FallingScale = ((Component)__instance).transform.localScale.x; TreeRegrow.Falling = true; } } catch { } } private static void Postfix() { TreeRegrow.Falling = false; } } [HarmonyPatch(typeof(ZNetView), "Awake")] internal static class TreeRegrowViewPatch { private static void Postfix(ZNetView __instance) { try { TreeRegrow.OnViewAwake(__instance); } catch { } } } internal static class DungeonRooms { private sealed class Vanilla { internal int Min; internal int Max; } internal const int Floor = 10; internal const int MinCeiling = 150; internal const int MaxCeiling = 500; private static readonly ConditionalWeakTable<DungeonGenerator, Vanilla> Originals = new ConditionalWeakTable<DungeonGenerator, Vanilla>(); private static readonly HashSet<string> Seen = new HashSet<string>(StringComparer.Ordinal); internal const int KindOther = 0; internal const int KindBurial = 1; internal const int KindSunken = 2; internal const int KindCave = 3; internal const int KindMine = 4; internal const int KindQueen = 5; internal const int KindHole = 6; internal const int KindMork = 7; internal static bool Enabled => Cfg.DgEnabled != null && Cfg.DgEnabled.Value; internal static void Apply(DungeonGenerator dg) { if (!((Object)(object)dg == (Object)null)) { if (!Originals.TryGetValue(dg, out var value)) { value = new Vanilla { Min = dg.m_minRooms, Max = dg.m_maxRooms }; Originals.Add(dg, value); } int min = value.Min; int max = value.Max; string text = (((Object)(object)((Component)dg).gameObject != (Object)null) ? Utils.GetPrefabName(((Component)dg).gameObject) : "?"); if (Enabled) { Resolve(text, out min, out max); } dg.m_minRooms = min; dg.m_maxRooms = max; if (Seen.Add(text)) { Plugin.Log("Dungeon " + text + ": rooms " + value.Min + "-" + value.Max + " (game) -> " + min + "-" + max + (Enabled ? " (admin)" : " (unchanged)")); } } } internal static int KindOf(string prefab) { if (Is(prefab, "DG_ForestCrypt")) { return 1; } if (Is(prefab, "DG_SunkenCrypt")) { return 2; } if (Is(prefab, "DG_Cave")) { return 3; } if (Is(prefab, "DG_DvergrTown")) { return 4; } if (Is(prefab, "DG_DvergrBoss")) { return 5; } if (Is(prefab, "DG_Hole")) { return 6; } if (Is(prefab, "DG_MorkHalla")) { return 7; } return 0; } internal static void Resolve(string prefab, out int min, out int max) { int num = 0; int num2 = 0; switch (KindOf(prefab)) { case 1: num = Cfg.DgBurialMin.Value; num2 = Cfg.DgBurialMax.Value; break; case 2: num = Cfg.DgSunkenMin.Value; num2 = Cfg.DgSunkenMax.Value; break; case 3: num = Cfg.DgCaveMin.Value; num2 = Cfg.DgCaveMax.Value; break; case 4: num = Cfg.DgMineMin.Value; num2 = Cfg.DgMineMax.Value; break; case 5: num = Cfg.DgQueenMin.Value; num2 = Cfg.DgQueenMax.Value; break; case 6: num = Cfg.DgHoleMin.Value; num2 = Cfg.DgHoleMax.Value; break; case 7: num = Cfg.DgMorkMin.Value; num2 = Cfg.DgMorkMax.Value; break; } min = ((num > 0) ? num : Cfg.DgMin.Value); max = ((num2 > 0) ? num2 : Cfg.DgMax.Value); min = Mathf.Clamp(min, 10, 150); max = Mathf.Clamp(max, 10, 500); if (max < min) { max = min; } } private static bool Is(string prefab, string wanted) { return string.Equals(prefab, wanted, StringComparison.OrdinalIgnoreCase); } } [HarmonyPatch(typeof(DungeonGenerator), "GenerateRooms")] internal static class DungeonRoomsPatch { [HarmonyPriority(800)] private static void Prefix(DungeonGenerator __instance) { try { DungeonRooms.Apply(__instance); } catch (Exception ex) { Plugin.Warn("Dungeon rooms: " + ex.Message); } } } internal static class DungeonReset { internal enum Result { Wait, NotDue, Blocked, Done } private sealed class Origin { internal Vector3 Pos; } private const string StampKey = "Igao.UQ.dgreset"; private const float SkyY = 4000f; internal const float NearRange = 120f; private static readonly ConditionalWeakTable<DungeonGenerator, Origin> Origins = new ConditionalWeakTable<DungeonGenerator, Origin>(); private static readonly List<DungeonGenerator> Live = new List<DungeonGenerator>(8); private static FieldInfo _functions; private static bool _functionsLooked; internal static bool Busy; internal static bool Enabled => Cfg.DgrEnabled != null && Cfg.DgrEnabled.Value; internal static void Before(DungeonGenerator dg) { //IL_0039: 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) if (!((Object)(object)dg == (Object)null) && !Busy && !Origins.TryGetValue(dg, out var _)) { Origins.Add(dg, new Origin { Pos = dg.m_originalPosition }); } } internal static void After(DungeonGenerator dg) { if (!((Object)(object)dg == (Object)null) && !Busy) { Live.RemoveAll((DungeonGenerator x) => (Object)(object)x == (Object)null); if (!Live.Contains(dg)) { Live.Add(dg); } if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && (Object)(object)((Component)dg).GetComponent<DungeonResetWatcher>() == (Object)null) { ((Component)dg).gameObject.AddComponent<DungeonResetWatcher>(); } } } internal static int DaysFor(string prefab) { int num = 0; switch (DungeonRooms.KindOf(prefab)) { case 1: num = Cfg.DgrBurialDays.Value; break; case 2: num = Cfg.DgrSunkenDays.Value; break; case 3: num = Cfg.DgrCaveDays.Value; break; case 4: num = Cfg.DgrMineDays.Value; break; case 5: num = Cfg.DgrQueenDays.Value; break; case 6: num = Cfg.DgrHoleDays.Value; break; case 7: num = Cfg.DgrMorkDays.Value; break; } return Mathf.Clamp((num > 0) ? num : Cfg.DgrDays.Value, 1, 3650); } private static float Radius(DungeonGenerator dg) { float num = dg.m_zoneSize.x * 0.5f; float num2 = dg.m_zoneSize.z * 0.5f; return Mathf.Sqrt(num * num + num2 * num2); } private static bool Within(Vector3 a, Vector3 b, float distance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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) //IL_0015: Unknown result type (might be due to invalid IL or missing references) float num = a.x - b.x; float num2 = a.z - b.z; return num * num + num2 * num2 <= distance * distance; } private static bool Occupied(DungeonGenerator dg, float radius) { //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_001d: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) bool value = Cfg.DgrKeepBuilds.Value; Vector3 position = ((Component)dg).transform.position; Scene activeScene = SceneManager.GetActiveScene(); GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if ((Object)(object)val == (Object)null || val.transform.position.y < 4000f || !Within(position, val.transform.position, radius)) { continue; } if ((Object)(object)val.GetComponent<Player>() != (Object)null) { return true; } if (value) { if ((Object)(object)val.GetComponent<TombStone>() != (Object)null) { return true; } Piece component = val.GetComponent<Piece>(); if ((Object)(object)component != (Object)null && component.GetCreator() != 0) { return true; } } } return false; } internal static Result Try(DungeonGenerator dg, bool force) { //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)dg == (Object)null || (Object)(object)EnvMan.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return Result.Wait; } ZNetView component = ((Component)dg).GetComponent<ZNetView>(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val == null) { return Result.Wait; } if (!component.IsOwner()) { if (!force) { return Result.Blocked; } component.ClaimOwnership(); return Result.Wait; } string prefabName = Utils.GetPrefabName(((Component)dg).gameObject); int day = EnvMan.instance.GetDay(); int num = val.GetInt("Igao.UQ.dgreset", -1); if (!force) { if (num < 0 || num > day) { val.Set("Igao.UQ.dgreset", day); return Result.NotDue; } if (day - num < DaysFor(prefabName)) { return Result.NotDue; } } float radius = Radius(dg); if (Occupied(dg, radius)) { if (force) { Plugin.Log("Dungeon " + prefabName + " not reset: a player or something a player left is inside."); } return Result.Blocked; } FieldInfo fieldInfo = FunctionsField(); if (fieldInfo == null) { return Result.Blocked; } val.Set("Igao.UQ.dgreset", day); Busy = true; try { Clear(dg, radius); if (Origins.TryGetValue(dg, out var value)) { dg.m_originalPosition = value.Pos; } fieldInfo.SetValue(component, Activator.CreateInstance(fieldInfo.FieldType)); dg.Generate((SpawnMode)0); Plugin.Log("Dungeon " + prefabName + " reset (day " + day + ((num >= 0) ? (", " + (day - num) + " days after the last reset") : "") + ")."); return Result.Done; } catch (Exception ex) { Plugin.Warn("Dungeon reset failed for " + prefabName + ": " + ex.Message); return Result.Blocked; } finally { Busy = false; } } private static void Clear(DungeonGenerator dg, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0052: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)dg).transform.position; Scene activeScene = SceneManager.GetActiveScene(); GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if (!((Object)(object)val == (Object)null) && !(val.transform.position.y < 4000f) && Within(position, val.transform.position, radius) && !((Object)(object)val.GetComponent<DungeonGenerator>() != (Object)null) && !((Object)(object)val.GetComponent<LocationProxy>() != (Object)null) && !((Object)(object)val.GetComponent<Player>() != (Object)null) && !((Object)(object)val.GetComponent<OfferingBowl>() != (Object)null)) { ZNetView component = val.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.GetZDO() != null) { component.GetZDO().SetOwner(ZDOMan.GetSessionID()); } ZNetScene.instance.Destroy(val); } } } private static FieldInfo FunctionsField() { if (_functionsLooked) { return _functions; } _functionsLooked = true; _functions = AccessTools.Field(typeof(ZNetView), "m_functions"); if (_functions == null) { Plugin.Warn("Dungeon reset: the game changed (ZNetView.m_functions not found); dungeons will not be reset."); } return _functions; } internal static int ForceNear(float range) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return 0; } int num = 0; Live.RemoveAll((DungeonGenerator x) => (Object)(object)x == (Object)null); for (int num2 = 0; num2 < Live.Count; num2++) { DungeonGenerator val = Live[num2]; if (Within(((Component)localPlayer).transform.position, ((Component)val).transform.position, range)) { DungeonResetWatcher dungeonResetWatcher = ((Component)val).GetComponent<DungeonResetWatcher>(); if ((Object)(object)dungeonResetWatcher == (Object)null) { dungeonResetWatcher = ((Component)val).gameObject.AddComponent<DungeonResetWatcher>(); } dungeonResetWatcher.Force = true; dungeonResetWatcher.Hurry(); num++; } } return num; } } internal sealed class DungeonResetWatcher : MonoBehaviour { internal bool Force; private DungeonGenerator _dg; private float _next; private void Awake() { _dg = ((Component)this).GetComponent<DungeonGenerator>(); _next = Time.unscaledTime + 5f; } internal void Hurry() { _next = 0f; } private void Update() { float unscaledTime = Time.unscaledTime; if (unscaledTime < _next) { return; } _next = unscaledTime + 1f; try { Step(unscaledTime); } catch (Exception ex) { _next = unscaledTime + 60f; Plugin.Warn("Dungeon reset check: " + ex.Message); } } private void Step(float now) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_dg == (Object)null) { Object.Destroy((Object)(object)this); return; } if (!Force && !DungeonReset.Enabled) { _next = now + 30f; return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } Vector3 position = ((Component)localPlayer).transform.position; Vector3 position2 = ((Component)this).transform.position; float num = position.x - position2.x; float num2 = position.z - position2.z; if (num * num + num2 * num2 > 14400f) { _next = now + 15f; } else if (!((Object)(object)ZNetScene.instance == (Object)null) && ZNetScene.instance.IsAreaReady(position2)) { switch (DungeonReset.Try(_dg, Force)) { case DungeonReset.Result.NotDue: _next = now + 120f; break; case DungeonReset.Result.Blocked: _next = now + 30f; Force = false; break; case DungeonReset.Result.Done: _next = now + 120f; Force = false; break; } } } } [HarmonyPatch(typeof(DungeonGenerator), "Awake")] internal static class DungeonResetAwakePatch { private static void Postfix(DungeonGenerator __instance) { if (DungeonReset.Busy || (Object)(object)__instance == (Object)null) { return; } try { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { DungeonReset.After(__instance); } } catch (Exception ex) { Plugin.Warn("Dungeon reset (load): " + ex.Message); } } } [HarmonyPatch(typeof(DungeonGenerator), "Generate", new Type[] { typeof(SpawnMode) })] internal static class DungeonResetGeneratePatch { private static void Prefix(DungeonGenerator __instance) { try { DungeonReset.Before(__instance); } catch (Exception ex) { Plugin.Warn("Dungeon reset (before): " + ex.Message); } } private static void Postfix(DungeonGenerator __instance) { try { DungeonReset.After(__instance); } catch (Exception ex) { Plugin.Warn("Dungeon reset (after): " + ex.Message); } } } internal static class BlockTuning { private const float VanillaWindow = 0.25f; private static float _pingAt; private static int _pingMs; internal static float ParryWindow(Humanoid defender, Character attacker) { try { int num = ((Cfg.ParryMaxExtraMs != null) ? Cfg.ParryMaxExtraMs.Value : 0); if (num <= 0 || (Object)(object)defender == (Object)null || (Object)(object)attacker == (Object)null) { return 0.25f; } if ((Object)(object)defender != (Object)(object)Player.m_localPlayer || (Object)(object)attacker == (Object)(object)defender || attacker.IsOwner()) { return 0.25f; } int num2 = ServerPing(); if (num2 <= 0) { return 0.25f; } float num3 = (float)num2 * 0.5f; if (attacker.IsPlayer()) { num3 += (float)num2 * 0.5f; } if (num3 > (float)num) { num3 = num; } return 0.25f + num3 / 1000f; } catch { return 0.25f; } } internal static bool RejectOnStagger(bool staggered, Humanoid defender) { if (!staggered) { return false; } try { if (Cfg.BlockStaggerReliable != null && Cfg.BlockStaggerReliable.Value && (Object)(object)defender != (Object)null && (Object)(object)defender == (Object)(object)Player.m_localPlayer && ((Character)defender).IsOwner()) { return false; } } catch { } return true; } private static int ServerPing() { float unscaledTime = Time.unscaledTime; if (unscaledTime < _pingAt) { return _pingMs; } _pingAt = unscaledTime + 2f; _pingMs = 0; try { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || instance.IsServer()) { return 0; } ZNetPeer serverPeer = instance.GetServerPeer(); if (serverPeer == null || serverPeer.m_socket == null) { return 0; } float num = default(float); float num2 = default(float); int num3 = default(int); float num4 = default(float); float num5 = default(float); serverPeer.m_socket.GetConnectionQuality(ref num, ref num2, ref num3, ref num4, ref num5); _pingMs = ((num3 > 0) ? num3 : 0); } catch { _pingMs = 0; } return _pingMs; } } [HarmonyPatch(typeof(Humanoid), "BlockAttack")] internal static class BlockAttackPatch { private static readonly MethodInfo AddStagger = AccessTools.Method(typeof(Character), "AddStaggerDamage", (Type[])null, (Type[])null); private static readonly MethodInfo BlockDamage = AccessTools.Method(typeof(HitData), "BlockDamage", (Type[])null, (Type[])null); private static readonly FieldInfo BlockTimer = AccessTools.Field(typeof(Humanoid), "m_blockTimer"); private static readonly MethodInfo WindowM = AccessTools.Method(typeof(BlockTuning), "ParryWindow", (Type[])null, (Type[])null); private static readonly MethodInfo RejectM = AccessTools.Method(typeof(BlockTuning), "RejectOnStagger", (Type[])null, (Type[])null); private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); try { if (!PatchWindow(list)) { Plugin.Warn("Combat: the parry window was not found in this game version; parry lag compensation stays off."); } } catch (Exception ex) { Plugin.Warn("Combat: parry window patch failed: " + ex.Message); } try { if (!PatchStagger(list)) { Plugin.Warn("Combat: the stagger check was not found in this game version; reliable block stays off."); } } catch (Exception ex2) { Plugin.Warn("Combat: reliable block patch failed: " + ex2.Message); } return list; } private static bool PatchWindow(List<CodeInstruction> code) { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Expected O, but got Unknown if (BlockTimer == null || WindowM == null) { return false; } for (int i = 0; i < code.Count; i++) { if (code[i].opcode != OpCodes.Ldfld || !object.Equals(code[i].operand, BlockTimer)) { continue; } for (int j = i + 1; j < code.Count && j <= i + 4; j++) { if (!(code[j].opcode != OpCodes.Ldc_R4) && code[j].operand is float && !(Math.Abs((float)code[j].operand - 0.25f) > 0.0001f)) { code[j].opcode = OpCodes.Ldarg_0; code[j].operand = null; code.Insert(j + 1, new CodeInstruction(OpCodes.Ldarg_2, (object)null)); code.Insert(j + 2, new CodeInstruction(OpCodes.Call, (object)WindowM)); return true; } } } return false; } private static bool PatchStagger(List<CodeInstruction> code) { //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown if (AddStagger == null || BlockDamage == null || RejectM == null) { return false; } int num = -1; int num2 = -1; for (int i = 0; i < code.Count; i++) { if (IsCall(code[i], AddStagger)) { if (num >= 0) { return false; } num = i; } else if (IsCall(code[i], BlockDamage)) { if (num2 >= 0) { return false; } num2 = i; } } if (num < 0 || num2 < num + 3) { return false; } int num3 = LocalOf(code[num + 1], load: false); if (num3 < 0) { return false; } for (int j = num + 2; j + 1 < num2; j++) { if (LocalOf(code[j], load: true) == num3) { OpCode opcode = code[j + 1].opcode; if ((!(opcode != OpCodes.Brtrue) || !(opcode != OpCodes.Brtrue_S)) && code[j + 1].operand is Label && IndexOfLabel(code, (Label)code[j + 1].operand) > num2) { code.Insert(j + 1, new CodeInstruction(OpCodes.Call, (object)RejectM)); code.Insert(j + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null)); return true; } } } return false; } private static bool IsCall(CodeInstruction ci, MethodInfo m) { return (ci.opcode == OpCodes.Call || ci.opcode == OpCodes.Callvirt) && object.Equals(ci.operand, m); } private static int IndexOfLabel(List<CodeInstruction> code, Label label) { for (int i = 0; i < code.Count; i++) { if (code[i].labels.Contains(label)) { return i; } } return -1; } private static int LocalOf(CodeInstruction ci, bool load) { OpCode opcode = ci.opcode; if (opcode == (load ? OpCodes.Ldloc_0 : OpCodes.Stloc_0)) { return 0; } if (opcode == (load ? OpCodes.Ldloc_1 : OpCodes.Stloc_1)) { return 1; } if (opcode == (load ? OpCodes.Ldloc_2 : OpCodes.Stloc_2)) { return 2; } if (opcode == (load ? OpCodes.Ldloc_3 : OpCodes.Stloc_3)) { return 3; } if (opcode != (load ? OpCodes.Ldloc : OpCodes.Stloc) && opcode != (load ? OpCodes.Ldloc_S : OpCodes.Stloc_S)) { return -1; } if (!(ci.operand is LocalBuilder { LocalIndex: var localIndex })) { if (ci.operand is int) { return (int)ci.operand; } if (ci.operand is byte) { return (byte)ci.operand; } if (ci.operand is short) { return (short)ci.operand; } return -1; } return localIndex; } } internal enum PinCat { None, Dungeon, Runestone, Boss, DunBurial, DunSunken, DunFrost, DunMine, DunTroll, DunPutrid, DunTunnels, DunMork, Copper, Tin, Iron, Silver, Obsidian, Flametal, BlackMarble, Bloodgold, Leviathan, OreOther, Raspberry, Blueberry, Cloudberry, Thistle, Mushroom, Dandelion, Fiddlehead, SmokePuff, Lingonberry, Count } internal static class PinCats { private struct Info { internal string Key; internal Color Color; internal int Group; internal int Style; internal string Item; internal bool UsePin; internal PinType Pin; internal bool Tint; } internal const int GroupPlaces = 0; internal const int GroupOres = 1; internal const int GroupPlants = 2; internal const int GroupDungeons = 3; internal static readonly int[] GroupOrder = new int[4] { 3, 0, 1, 2 }; internal static readonly PinCat[] Order = new PinCat[30] { PinCat.DunBurial, PinCat.DunSunken, PinCat.DunFrost, PinCat.DunMine, PinCat.DunTroll, PinCat.DunPutrid, PinCat.DunTunnels, PinCat.DunMork, PinCat.Dungeon, PinCat.Runestone, PinCat.Boss, PinCat.Copper, PinCat.Tin, PinCat.Iron, PinCat.Silver, PinCat.Obsidian, PinCat.Flametal, PinCat.BlackMarble, PinCat.Bloodgold, PinCat.Leviathan, PinCat.OreOther, PinCat.Raspberry, PinCat.Blueberry, PinCat.Cloudberry, PinCat.Thistle, PinCat.Mushroom, PinCat.Dandelion, PinCat.Fiddlehead, PinCat.SmokePuff, PinCat.Lingonberry }; private static readonly Info[] Table = Build(); private static readonly Sprite[] Sprites = (Sprite[])(object)new Sprite[31]; private static readonly Sprite[] Discs = (Sprite[])(object)new Sprite[31]; private static readonly float[] NextTry = new float[31]; private static readonly Dictionary<int, Sprite> PinBase = new Dictionary<int, Sprite>(); private static readonly FieldInfo IconsField = AccessTools.Field(typeof(Minimap), "m_icons"); private static FieldInfo _spriteName; private static FieldInfo _spriteIcon; internal const int ModeNear = 0; internal const int ModeEnter = 1; internal const int ModeMine = 2; internal const int ModePick = 3; private static Info ItemInfo(string key, float r, float g, float b, int group, int style, string item) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) return new Info { Key = key, Color = new Color(r, g, b, 1f), Group = group, Style = style, Item = item }; } private static Info PinInfo(string key, float r, float g, float b, int group, PinType pin, bool tint) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0042: Unknown result type (might be due to invalid IL or missing references) return new Info { Key = key, Color = new Color(r, g, b, 1f), Group = group, Style = 2, UsePin = true, Pin = pin, Tint = tint }; } private static Info[] Build() { Info[] array = new Info[31]; array[1] = PinInfo("ap_cat_dungeon", 0.86f, 0.86f, 0.9f, 3, (PinType)2, tint: true); array[4] = PinInfo("ap_cat_dun_burial", 1f, 0.82f, 0.16f, 3, (PinType)2, tint: true); array[5] = PinInfo("ap_cat_dun_sunken", 0.24f, 0.86f, 0.38f, 3, (PinType)2, tint: true); array[6] = PinInfo("ap_cat_dun_frost", 0.42f, 0.78f, 1f, 3, (PinType)2, tint: true); array[7] = PinInfo("ap_cat_dun_mine", 0.78f, 0.4f, 1f, 3, (PinType)2, tint: true); array[8] = PinInfo("ap_cat_dun_troll", 0.8f, 0.52f, 0.28f, 3, (PinType)2, tint: true); array[9] = PinInfo("ap_cat_dun_putrid", 1f, 0.4f, 0.1f, 3, (PinType)2, tint: true); array[10] = PinInfo("ap_cat_dun_tunnels", 1f, 0.36f, 0.66f, 3, (PinType)2, tint: true); array[11] = PinInfo("ap_cat_dun_mork", 0.36f, 0.34f, 0.95f, 3, (PinType)2, tint: true); array[2] = PinInfo("ap_cat_rune", 0.2f, 0.88f, 0.98f, 0, (PinType)6, tint: true); array[3] = PinInfo("ap_cat_boss", 0.9f, 0.1f, 0.18f, 0, (PinType)9, tint: false); array[12] = ItemInfo("ap_cat_copper", 0.82f, 0.5f, 0.28f, 1, 0, "CopperOre"); array[13] = ItemInfo("ap_cat_tin", 0.18f, 0.76f, 0.7f, 1, 0, "TinOre"); array[14] = ItemInfo("ap_cat_iron", 0.45f, 0.52f, 0.62f, 1, 0, "IronScrap"); array[15] = ItemInfo("ap_cat_silver", 0.86f, 0.89f, 1f, 1, 0, "SilverOre"); array[16] = ItemInfo("ap_cat_obsidian", 0.4f, 0.14f, 0.66f, 1, 0, "Obsidian"); array[17] = ItemInfo("ap_cat_flametal", 1f, 0.45f, 0.04f, 1, 0, "FlametalOreNew|FlametalOre"); array[18] = ItemInfo("ap_cat_blackmarble", 0.22f, 0.23f, 0.28f, 1, 0, "BlackMarble"); array[19] = ItemInfo("ap_cat_bloodgold", 0.78f, 0.1f, 0.16f, 1, 0, "GoldOre"); array[20] = ItemInfo("ap_cat_leviathan", 0.25f, 0.65f, 0.8f, 1, 0, "Chitin"); array[21] = ItemInfo("ap_cat_oreother", 0.78f, 0.78f, 0.78f, 1, 0, null); array[22] = ItemInfo("ap_cat_raspberry", 0.98f, 0.3f, 0.56f, 2, 1, "Raspberry"); array[23] = ItemInfo("ap_cat_blueberry", 0.3f, 0.45f, 1f, 2, 1, "Blueberries"); array[24] = ItemInfo("ap_cat_cloudberry", 1f, 0.74f, 0.1f, 2, 1, "Cloudberry"); array[25] = ItemInfo("ap_cat_thistle", 0.3f, 0.8f, 0.36f, 2, 1, "Thistle"); array[26] = ItemInfo("ap_cat_mushroom", 0.76f, 0.56f, 0.36f, 2, 1, "Mushroom"); array[27] = ItemInfo("ap_cat_dandelion", 1f, 0.96f, 0.55f, 2, 1, "Dandelion"); array[28] = ItemInfo("ap_cat_fiddlehead", 0.8f, 0.22f, 0.2f, 2, 1, "Fiddleheadfern"); array[29] = ItemInfo("ap_cat_smokepuff", 0.95f, 0.8f, 0.2f, 2, 1, "MushroomSmokePuff"); array[30] = ItemInfo("ap_cat_lingonberry", 0.85f, 0.15f, 0.3f, 2, 1, "Lingonberry"); return array; } internal static string Key(PinCat c) { return Table[(int)c].Key; } internal static Color ColorOf(PinCat c) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) return Table[(int)c].Color; } internal static int Group(PinCat c) { return Table[(int)c].Group; } internal static int ModeOf(PinCat c) { if (c == PinCat.None) { return 0; } switch (Table[(int)c].Group) { case 3: return 1; case 2: return 0; case 1: return (c != PinCat.Leviathan) ? 2 : 0; default: if (c == PinCat.Runestone) { return 3; } return 0; } } internal static float NearLimit(PinCat c) { if (c == PinCat.Leviathan) { return 40f; } if (Table[(int)c].Group == 2) { return 10f; } return float.MaxValue; } internal static bool IsDungeon(PinCat c) { return c != PinCat.None && Table[(int)c].Group == 3; } internal static bool Persistent(PinCat c) { int num = Table[(int)c].Group; return num == 0 || num == 3; } internal static bool TakesOldPins(PinCat c) { return IsDungeon(c) || c == PinCat.Runestone; } internal static PinType SavedType(PinCat c) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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) Info info = Table[(int)c]; return (PinType)((!info.UsePin) ? 8 : ((int)info.Pin)); } internal static string GroupKey(int group) { return group switch { 3 => "ap_grp_dungeons", 0 => "ap_grp_places", 1 => "ap_grp_ores", _ => "ap_grp_plants", }; } internal static PinCat DungeonOf(string prefab) { if (string.IsNullOrEmpty(prefab)) { return PinCat.None; } if (Starts(prefab, "SunkenCrypt")) { return PinCat.DunSunken; } if (Starts(prefab, "Crypt") || Starts(prefab, "Hildir_crypt")) { return PinCat.DunBurial; } if (Starts(prefab, "MountainCave") || Starts(prefab, "Hildir_cave")) { return PinCat.DunFrost; } if (Starts(prefab, "Mistlands_DvergrTownEntrance") || Starts(prefab, "Mistlands_DvergrBossEntrance")) { return PinCat.DunMine; } if (Starts(prefab, "TrollCave")) { return PinCat.DunTroll; } if (Starts(prefab, "MorgenHole")) { return PinCat.DunPutrid; } if (Starts(prefab, "TheHole")) { return PinCat.DunTunnels; } if (Starts(prefab, "MorkBorg")) { return PinCat.DunMork; } return PinCat.None; } private static bool Starts(string s, string prefix) { return s.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); } internal static void NotePinSprite(PinType type, Sprite sprite) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected I4, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected I4, but got Unknown if ((int)type != 8 && !((Object)(object)sprite == (Object)null) && !PinBase.ContainsKey((int)type)) { PinBase[(int)type] = sprite; } } internal static bool IsFallback(PinCat c) { return (Object)(object)Sprites[(int)c] == (Object)null; } internal static Sprite SpriteOf(PinCat c) { //IL_007f: 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) if ((Object)(object)Sprites[(int)c] != (Object)null) { return Sprites[(int)c]; } Info info = Table[(int)c]; if ((info.Item != null || info.UsePin) && Time.unscaledTime >= NextTry[(int)c]) { NextTry[(int)c] = Time.unscaledTime + 3f; Sprite val = null; try { if (info.UsePin) { Sprite val2 = BaseSprite(info.Pin); if ((Object)(object)val2 != (Object)null) { val = (info.Tint ? Painted(val2, info.Color) : val2); } } else { val = ItemSprite(info.Item); } } catch { val = null; } if ((Object)(object)val != (Object)null) { Sprites[(int)c] = val; Discs[(int)c] = null; return val; } } if ((Object)(object)Discs[(int)c] == (Object)null) { Discs[(int)c] = MakeDisc(info); } return Discs[(int)c]; } private static Sprite ItemSprite(string names) { string[] array = names.Split(new char[1] { '|' }); for (int i = 0; i < array.Length; i++) { Sprite val = GameAccess.ItemIcon(array[i]); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Sprite BaseSprite(PinType type) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected I4, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected I4, but got Unknown if (PinBase.TryGetValue((int)type, out var value) && (Object)(object)value != (Object)null) { return value; } value = FindInMinimap(type); if ((Object)(object)value != (Object)null) { PinBase[(int)type] = value; } return value; } private static Sprite FindInMinimap(PinType type) { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) try { Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || IconsField == null) { return null; } if (!(IconsField.GetValue(instance) is IList list)) { return null; } for (int i = 0; i < list.Count; i++) { object obj = list[i]; if (obj == null) { continue; } if (_spriteName == null || _spriteIcon == null) { Type type2 = obj.GetType(); _spriteName = AccessTools.Field(type2, "m_name"); _spriteIcon = AccessTools.Field(type2, "m_icon"); if (_spriteName == null || _spriteIcon == null) { return null; } } object value = _spriteName.GetValue(obj); if (value is PinType && (PinType)value == type) { object? value2 = _spriteIcon.GetValue(obj); return (Sprite)((value2 is Sprite) ? value2 : null); } } } catch { } return null; } private static Sprite Painted(Sprite src, Color tint) { //IL_0027: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_009b: 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_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) RenderTexture val = null; RenderTexture active = RenderTexture.active; try { Texture2D texture = src.texture; if ((Object)(object)texture == (Object)null) { return null; } Rect textureRect = src.textureRect; int num = Mathf.Max(1, Mathf.RoundToInt(((Rect)(ref textureRect)).width)); int num2 = Mathf.Max(1, Mathf.RoundToInt(((Rect)(ref textureRect)).height)); val = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0); Graphics.Blit((Texture)(object)texture, val); RenderTexture.active = val; Texture2D val2 = new Texture2D(num, num2, (TextureFormat)4, false); val2.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0); val2.Apply(false); Color32[] pixels = val2.GetPixels32(); float num3 = 0.01f; for (int i = 0; i < pixels.Length; i++) { if (pixels[i].a >= 128) { float num4 = (float)Mathf.Max((int)pixels[i].r, Mathf.Max((int)pixels[i].g, (int)pixels[i].b)) / 255f; if (num4 > num3) { num3 = num4; } } } for (int j = 0; j < pixels.Length; j++) { float num5 = (float)Mathf.Max((int)pixels[j].r, Mathf.Max((int)pixels[j].g, (int)pixels[j].b)) / 255f; float num6 = Mathf.Clamp01(num5 / num3); num6 = Mathf.Pow(num6, 0.85f); pixels[j] = new Color32((byte)Mathf.RoundToInt(Mathf.Clamp01(tint.r * num6) * 255f), (byte)Mathf.RoundToInt(Mathf.Clamp01(tint.g * num6) * 255f), (byte)Mathf.RoundToInt(Mathf.Clamp01(tint.b * num6) * 255f), pixels[j].a); } val2.SetPixels32(pixels); val2.Apply(false, false); ((Object)val2).hideFlags = (HideFlags)61; ((Texture)val2).wrapMode = (TextureWrapMode)1; ((Texture)val2).filterMode = (FilterMode)1; Sprite val3 = Sprite.Create(val2, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), 100f); ((Object)val3).hideFlags = (HideFlags)61; return val3; } catch { return null; } finally { RenderTexture.active = active; if ((Object)(object)val != (Object)null) { RenderTexture.ReleaseTemporary(val); } } } internal static void DrawIcon(Rect where, Sprite sprite) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0081: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)sprite == (Object)null)) { Texture2D texture = sprite.texture; if (!((Object)(object)texture == (Object)null) && ((Texture)texture).width > 0 && ((Texture)texture).height > 0) { Rect textureRect = sprite.textureRect; GUI.DrawTextureWithTexCoords(where, (Texture)(object)texture, new Rect(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height)); } } } private static Sprite MakeDisc(Info info) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_004a: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be d